/// <summary> /// Add sources that are disposable on entry, such as byref disposables /// </summary> /// <param name="dictionary"></param> private IEnumerable <Instruction> InitialSources(FMap <IParameterDefinition, Instruction> initialParameters) { foreach (var p in this.currentMethod.Parameters) { Instruction initialDummyInit; if (p.IsByReference && !p.IsOut && IsDisposableType(p.Type) && initialParameters.TryGetValue(p, out initialDummyInit)) { yield return(initialDummyInit); } } }
private static Analysis.Instruction ReadLocation(FMap <ILocalDefinition, Analysis.Instruction> currentLocals, FMap <IParameterDefinition, Analysis.Instruction> currentParameters, object localOrParameter) { Analysis.Instruction result; var local = localOrParameter as ILocalDefinition; if (local != null) { currentLocals.TryGetValue(local, out result); return(result); } var param = localOrParameter as IParameterDefinition; if (param != null) { currentParameters.TryGetValue(param, out result); return(result); } return(null); }
private static void ComputeDataFlowThroughLocals(ControlAndDataFlowGraph <BasicBlock, Instruction> cdg) { FMap <ILocalDefinition, Microsoft.Cci.Analysis.Instruction> currentLocals; var todo = new Queue <BlockPC>(); var seen = new HashSet <BlockPC>(); var startBlock = cdg.RootBlocks[0]; FMap <IParameterDefinition, Microsoft.Cci.Analysis.Instruction> currentParameters = new FMap <IParameterDefinition, Microsoft.Cci.Analysis.Instruction>(k => k.Index); var initialLocation = GetStartLocation(startBlock); // push parameters onto start block foreach (var arg in cdg.MethodBody.MethodDefinition.Parameters) { var initialOp = new InitialParameterAssignment(arg, initialLocation); var initialDef = new Instruction() { Operation = initialOp }; currentParameters = currentParameters.Insert(arg, initialDef); } startBlock.ParamDefs = currentParameters; todo.Enqueue(new BlockPC(startBlock.Offset.Singleton())); while (todo.Count > 0) { var currentPC = todo.Dequeue(); if (seen.Contains(currentPC)) { continue; } seen.Add(currentPC); var block = cdg.CurrentBlock(currentPC); Contract.Assume(block != null); currentLocals = block.LocalDefs; currentParameters = block.ParamDefs; foreach (var instr in block.Instructions) { if (instr.IsMergeNode) { continue; } switch (instr.Operation.OperationCode) { case OperationCode.Starg: case OperationCode.Starg_S: // without pdb we seem to have no parameter info. var pdef = (IParameterDefinition)instr.Operation.Value; if (pdef != null) { currentParameters = currentParameters.Insert(pdef, instr.Operand1); } break; case OperationCode.Stloc: case OperationCode.Stloc_0: case OperationCode.Stloc_1: case OperationCode.Stloc_2: case OperationCode.Stloc_3: case OperationCode.Stloc_S: var ldef = (ILocalDefinition)instr.Operation.Value; currentLocals = currentLocals.Insert(ldef, instr.Operand1); break; case OperationCode.Ldloc: case OperationCode.Ldloc_0: case OperationCode.Ldloc_1: case OperationCode.Ldloc_2: case OperationCode.Ldloc_3: case OperationCode.Ldloc_S: // save the source in Aux { currentLocals.TryGetValue((ILocalDefinition)instr.Operation.Value, out instr.Aux); break; } case OperationCode.Ldarg: case OperationCode.Ldarg_0: case OperationCode.Ldarg_1: case OperationCode.Ldarg_2: case OperationCode.Ldarg_3: case OperationCode.Ldarg_S: // save the source in Aux var pdef2 = (IParameterDefinition)instr.Operation.Value; if (pdef2 == null) { // this parameter. Assume it's never overwritten } else { currentParameters.TryGetValue(pdef2, out instr.Aux); } break; case OperationCode.Stind_I: case OperationCode.Stind_I1: case OperationCode.Stind_I2: case OperationCode.Stind_I4: case OperationCode.Stind_I8: case OperationCode.Stind_R4: case OperationCode.Stind_R8: case OperationCode.Stind_Ref: { var location = cdg.LocalOrParameter(instr.Operand1); UpdateLocation(ref currentLocals, ref currentParameters, location, (Analysis.Instruction)instr.Operand2); break; } case OperationCode.Ldind_I: case OperationCode.Ldind_I1: case OperationCode.Ldind_I2: case OperationCode.Ldind_I4: case OperationCode.Ldind_I8: case OperationCode.Ldind_R4: case OperationCode.Ldind_R8: case OperationCode.Ldind_Ref: case OperationCode.Ldind_U1: case OperationCode.Ldind_U2: case OperationCode.Ldind_U4: { // save the read value in Aux var location = cdg.LocalOrParameter(instr.Operand1); instr.Aux = ReadLocation(currentLocals, currentParameters, location); break; } case OperationCode.Call: case OperationCode.Callvirt: { // update byref / out parameters var methodRef = instr.Operation.Value as IMethodReference; var args = instr.Operand2 as Instruction[]; if (args != null && methodRef != null) { foreach (var p in methodRef.Parameters) { if (p.IsByReference && p.Index < args.Length) { var arg = args[p.Index]; if (arg != null) { var loc = cdg.LocalOrParameter(arg); var syntheticOp = new CallByRefAssignment(instr, p); UpdateLocation(ref currentLocals, ref currentParameters, loc, new Instruction() { Operation = syntheticOp, Type = p.Type }); } } } } break; } } instr.PostLocalDefs = currentLocals; instr.PostParamDefs = currentParameters; } foreach (var succ in cdg.Successors(currentPC)) { MergeLocalsAndParameters(cdg.CurrentBlock(succ), currentLocals, currentParameters); todo.Enqueue(succ); } } }