private void InitializeArrayCreateInstruction(Instruction instruction, LocalsAndOperands <V> state, IOperation currentOperation) { /* Contract.Requires(instruction != null); * Contract.Requires(stack != null); * Contract.Requires(currentOperation != null); * IArrayTypeReference arrayType = (IArrayTypeReference)currentOperation.Value; * Contract.Assume(arrayType != null); //This is an informally specified property of the Metadata model. * var rank = arrayType.Rank; * if (currentOperation.OperationCode == OperationCode.Array_Create_WithLowerBound) rank *= 2; * var indices = new Instruction[rank]; * instruction.Operand2 = indices; * for (var i = rank; i > 0; i--) * indices[i - 1] = stack.Pop(); * stack.Push(instruction); */ IArrayTypeReference arrayType = (IArrayTypeReference)currentOperation.Value; Contract.Assume(arrayType != null); //This is an informally specified property of the Metadata model. var rank = arrayType.Rank; if (currentOperation.OperationCode == OperationCode.Array_Create_WithLowerBound) { rank *= 2; } for (var i = rank; i > 0; i--) { state.Pop(); } state.Push(ValueAbstraction.Top); // can be smarter than Top }
private void InitializeArrayIndexerInstruction(Instruction instruction, LocalsAndOperands <V> state, IArrayTypeReference arrayType) { // Copied from Cci's DataFlowInferencer.cs /* Contract.Requires(instruction != null); * Contract.Requires(stack != null); * Contract.Requires(arrayType != null); * var rank = arrayType.Rank; * var indices = new Instruction[rank]; * instruction.Operand2 = indices; * for (var i = rank; i > 0; i--) * indices[i - 1] = stack.Pop(); * instruction.Operand1 = stack.Pop(); * stack.Push(instruction); */ var rank = arrayType.Rank; for (var i = rank; i > 0; i--) { state.Pop(); } state.Pop(); state.Push(ValueAbstraction.Top); // need to be smarter about top }
public override LocalsAndOperands <V> EntryPreState(IMethodDefinition method) { // entry pre-state is empty operand stack // with locals initialized // LocalsAndOperands <V> state = new LocalsAndOperands <V>(); // If method has a this, parameter, it is the first argument if (!method.IsStatic && !method.HasExplicitThisParameter) { ITypeDefinition instantiatedThis = GarbageCollectHelper.InstantiatedTypeIfPossible(method.ContainingTypeDefinition); state.Arguments.Add(ValueAbstraction.GetAbstractValueForType(instantiatedThis)); } foreach (IParameterDefinition parameter in method.Parameters) { state.Arguments.Add(ValueAbstraction.GetAbstractValueForType(parameter.Type.ResolvedType)); } foreach (ILocalDefinition localVariable in method.Body.LocalVariables) { ITypeDefinition typeOfLocal = localVariable.Type.ResolvedType; state.Locals.Add(ValueAbstraction.GetAbstractValueForType(typeOfLocal)); } return(state); }
private void InterpretCallWithSignature(LocalsAndOperands <V> state, ISignature signature, bool hasReceiver) { /*Contract.Requires(instruction != null); * Contract.Requires(stack != null); * Contract.Requires(signature != null); * var numArguments = IteratorHelper.EnumerableCount(signature.Parameters); * var arguments = new Instruction[numArguments]; * instruction.Operand2 = arguments; * for (var i = numArguments; i > 0; i--) * arguments[i - 1] = stack.Pop(); * if (signature.Type.TypeCode != PrimitiveTypeCode.Void) * stack.Push(instruction); */ var numArguments = IteratorHelper.EnumerableCount(signature.Parameters); for (var i = numArguments; i > 0; i--) { state.Pop(); } if (hasReceiver) { state.Pop(); } if (signature.Type.TypeCode != PrimitiveTypeCode.Void) { state.Push(ValueAbstraction.GetAbstractValueForType(FixupTypeForFlow(signature.Type.ResolvedType))); // Should be smarter than just Top } }
public bool LessThanOrEqual(LocalsAndOperands <V> lhs, LocalsAndOperands <V> rhs) { if (lhs == Bottom) { return(true); } else if (rhs == Bottom) { // if we've gotten here lhs is NOT bottom // so there is no way lhs <= rhs return(false); } if (rhs == Top) { return(true); } else if (lhs == Top) { return(false); } Contract.Assert(lhs.Arguments.Count() == rhs.Arguments.Count()); Contract.Assert(lhs.Locals.Count() == rhs.Locals.Count()); Contract.Assert(lhs.OperandStack.Count() == rhs.OperandStack.Count()); return(ValueListLessThanOrEqual(lhs.Locals, rhs.Locals) && ValueListLessThanOrEqual(lhs.OperandStack, lhs.OperandStack)); }
private V FindReceiverInPreStateOperandStack(LocalsAndOperands <V> preState, IMethodReference methodCalled) { int countOfParameters = methodCalled.Parameters.Count(); //Operand stack in preState is ..., receiver, param1, param2, param3. int indexOfReceiverInOperandStack = (preState.OperandStack.Count() - countOfParameters) - 1; return(preState.OperandStack.ElementAt(indexOfReceiverInOperandStack)); }
public override LocalsAndOperands <V> IntepretBlockInState(BasicBlock <Instruction> block, LocalsAndOperands <V> preState, IMethodDefinition method) { LocalsAndOperands <V> currentState = preState; foreach (Instruction instruction in block.Instructions) { currentState = InterpretInstructionInState(instruction, currentState, method); } return(currentState); }
public LocalsAndOperands <V> Copy() { // We don't make copies of the values themselves; // just the lists. LocalsAndOperands <V> copy = new LocalsAndOperands <V>(); copy.Arguments = new List <V>(Arguments); copy.Locals = new List <V>(Locals); copy.OperandStack = new List <V>(OperandStack); return(copy); }
protected override void NotePreStateBeforeInterpretingInstruction(LocalsAndOperands <V> preState, Instruction instruction) { if (instruction.Operation.OperationCode == OperationCode.Callvirt) { // This copy is CRUCIAL: the preState is mutable and the analysis // WILL change it behind our back. LocalsAndOperands <V> preStateCopy = preState.Copy(); preStatesByOperation[instruction.Operation] = preStateCopy; } }
public LocalsAndOperands <V> Join(LocalsAndOperands <V> lhs, LocalsAndOperands <V> rhs) { if (lhs == Bottom) { return(rhs); } else if (rhs == Bottom) { return(lhs); } if (lhs == Top || rhs == Top) { return(Top); } LocalsAndOperands <V> joinedState = new LocalsAndOperands <V>(); JoinListsIntoTarget(lhs.Arguments, rhs.Arguments, joinedState.Arguments); JoinListsIntoTarget(lhs.Locals, rhs.Locals, joinedState.Locals); JoinListsIntoTarget(lhs.OperandStack, rhs.OperandStack, joinedState.OperandStack); return(joinedState); }
/// <summary> /// Hook for subclasses to use to get their hands the analysis prestate before a given instruction. /// /// This is called every time the instruction is interpreted (i.e. it may be called multiple times if the /// instruction is in a loop. Overrides should only use the final version of the prestate passed. /// /// Note: it is the overrider's responsibility to COPY the preState if it stashes it away. This state is MUTABLE /// and will change as further instructions in the basic block are interpreted. /// You've been warned. /// </summary> /// <param name="preState"></param> /// <param name="instruction"></param> virtual protected void NotePreStateBeforeInterpretingInstruction(LocalsAndOperands <V> preState, Instruction instruction) { // default is to do nothing }
// Interpret the instruction in the given abstract state and return the resulting abstract state private LocalsAndOperands <V> InterpretInstructionInState(Instruction instruction, LocalsAndOperands <V> preState, IMethodDefinition method) { LocalsAndOperands <V> currentState = preState.Copy(); // Switch cases copied directly from Cci's DataFlowInferencer NotePreStateBeforeInterpretingInstruction(currentState, instruction); switch (instruction.Operation.OperationCode) { case OperationCode.Add: case OperationCode.Add_Ovf: case OperationCode.Add_Ovf_Un: case OperationCode.And: case OperationCode.Ceq: case OperationCode.Cgt: case OperationCode.Cgt_Un: case OperationCode.Clt: case OperationCode.Clt_Un: case OperationCode.Div: case OperationCode.Div_Un: case OperationCode.Ldelema: case OperationCode.Ldelem: case OperationCode.Ldelem_I: case OperationCode.Ldelem_I1: case OperationCode.Ldelem_I2: case OperationCode.Ldelem_I4: case OperationCode.Ldelem_I8: case OperationCode.Ldelem_R4: case OperationCode.Ldelem_R8: case OperationCode.Ldelem_Ref: case OperationCode.Ldelem_U1: case OperationCode.Ldelem_U2: case OperationCode.Ldelem_U4: case OperationCode.Mul: case OperationCode.Mul_Ovf: case OperationCode.Mul_Ovf_Un: case OperationCode.Or: case OperationCode.Rem: case OperationCode.Rem_Un: case OperationCode.Shl: case OperationCode.Shr: case OperationCode.Shr_Un: case OperationCode.Sub: case OperationCode.Sub_Ovf: case OperationCode.Sub_Ovf_Un: case OperationCode.Xor: //instruction.Operand2 = stack.Pop(); //instruction.Operand1 = stack.Pop(); //stack.Push(instruction); currentState.Pop(); currentState.Pop(); //currentState.Push(ValueAbstraction.Top); // Not right currentState.Push(ValueAbstraction.GetAbstractValueForType(FixupTypeForFlow(instruction.Type.ResolvedType))); // still not right break; case OperationCode.Ldarg: case OperationCode.Ldarg_0: case OperationCode.Ldarg_1: case OperationCode.Ldarg_2: case OperationCode.Ldarg_3: case OperationCode.Ldarg_S: { int argumentIndex = GetArgumentIndexFromParameterOperation(instruction.Operation, method); V argumentValue = currentState.Arguments.ElementAt(argumentIndex); currentState.Push(argumentValue); } break; case OperationCode.Ldloc: case OperationCode.Ldloc_0: case OperationCode.Ldloc_1: case OperationCode.Ldloc_2: case OperationCode.Ldloc_3: case OperationCode.Ldloc_S: { Contract.Assume(instruction.Operation.Value is ILocalDefinition); ILocalDefinition local = instruction.Operation.Value as ILocalDefinition; int localIndex = GetLocalIndexFromLocalOperation(instruction.Operation, method); V localValue = currentState.Locals.ElementAt(localIndex); currentState.Push(localValue); } break; case OperationCode.Ldsfld: case OperationCode.Ldarga: case OperationCode.Ldarga_S: case OperationCode.Ldsflda: case OperationCode.Ldloca: case OperationCode.Ldloca_S: case OperationCode.Ldftn: case OperationCode.Ldc_I4: case OperationCode.Ldc_I4_0: case OperationCode.Ldc_I4_1: case OperationCode.Ldc_I4_2: case OperationCode.Ldc_I4_3: case OperationCode.Ldc_I4_4: case OperationCode.Ldc_I4_5: case OperationCode.Ldc_I4_6: case OperationCode.Ldc_I4_7: case OperationCode.Ldc_I4_8: case OperationCode.Ldc_I4_M1: case OperationCode.Ldc_I4_S: case OperationCode.Ldc_I8: case OperationCode.Ldc_R4: case OperationCode.Ldc_R8: case OperationCode.Ldnull: case OperationCode.Ldstr: case OperationCode.Ldtoken: case OperationCode.Sizeof: case OperationCode.Arglist: //stack.Push(instruction); //currentState.Push(ValueAbstraction.Top); // not right currentState.Push(ValueAbstraction.GetAbstractValueForType(FixupTypeForFlow(instruction.Type.ResolvedType))); // Still not right break; case OperationCode.Array_Addr: case OperationCode.Array_Get: Contract.Assume(instruction.Operation.Value is IArrayTypeReference); //This is an informally specified property of the Metadata model. //InitializeArrayIndexerInstruction(instruction, stack, (IArrayTypeReference)instruction.Operation.Value); InitializeArrayIndexerInstruction(instruction, currentState, (IArrayTypeReference)instruction.Operation.Value); break; case OperationCode.Array_Create: case OperationCode.Array_Create_WithLowerBound: case OperationCode.Newarr: InitializeArrayCreateInstruction(instruction, currentState, instruction.Operation); break; case OperationCode.Array_Set: /*stack.Pop(); * Contract.Assume(instruction.Operation.Value is IArrayTypeReference); //This is an informally specified property of the Metadata model. * InitializeArrayIndexerInstruction(instruction, stack, (IArrayTypeReference)instruction.Operation.Value); */ currentState.Pop(); Contract.Assume(instruction.Operation.Value is IArrayTypeReference); //This is an informally specified property of the Metadata model. InitializeArrayIndexerInstruction(instruction, currentState, (IArrayTypeReference)instruction.Operation.Value); break; case OperationCode.Beq: case OperationCode.Beq_S: case OperationCode.Bge: case OperationCode.Bge_S: case OperationCode.Bge_Un: case OperationCode.Bge_Un_S: case OperationCode.Bgt: case OperationCode.Bgt_S: case OperationCode.Bgt_Un: case OperationCode.Bgt_Un_S: case OperationCode.Ble: case OperationCode.Ble_S: case OperationCode.Ble_Un: case OperationCode.Ble_Un_S: case OperationCode.Blt: case OperationCode.Blt_S: case OperationCode.Blt_Un: case OperationCode.Blt_Un_S: case OperationCode.Bne_Un: case OperationCode.Bne_Un_S: /*instruction.Operand2 = stack.Pop(); * instruction.Operand1 = stack.Pop(); */ currentState.Pop(); currentState.Pop(); break; case OperationCode.Box: case OperationCode.Castclass: case OperationCode.Ckfinite: case OperationCode.Conv_I: case OperationCode.Conv_I1: case OperationCode.Conv_I2: case OperationCode.Conv_I4: case OperationCode.Conv_I8: case OperationCode.Conv_Ovf_I: case OperationCode.Conv_Ovf_I_Un: case OperationCode.Conv_Ovf_I1: case OperationCode.Conv_Ovf_I1_Un: case OperationCode.Conv_Ovf_I2: case OperationCode.Conv_Ovf_I2_Un: case OperationCode.Conv_Ovf_I4: case OperationCode.Conv_Ovf_I4_Un: case OperationCode.Conv_Ovf_I8: case OperationCode.Conv_Ovf_I8_Un: case OperationCode.Conv_Ovf_U: case OperationCode.Conv_Ovf_U_Un: case OperationCode.Conv_Ovf_U1: case OperationCode.Conv_Ovf_U1_Un: case OperationCode.Conv_Ovf_U2: case OperationCode.Conv_Ovf_U2_Un: case OperationCode.Conv_Ovf_U4: case OperationCode.Conv_Ovf_U4_Un: case OperationCode.Conv_Ovf_U8: case OperationCode.Conv_Ovf_U8_Un: case OperationCode.Conv_R_Un: case OperationCode.Conv_R4: case OperationCode.Conv_R8: case OperationCode.Conv_U: case OperationCode.Conv_U1: case OperationCode.Conv_U2: case OperationCode.Conv_U4: case OperationCode.Conv_U8: case OperationCode.Isinst: 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: case OperationCode.Ldobj: case OperationCode.Ldflda: case OperationCode.Ldfld: case OperationCode.Ldlen: case OperationCode.Ldvirtftn: case OperationCode.Localloc: case OperationCode.Mkrefany: case OperationCode.Neg: case OperationCode.Not: case OperationCode.Refanytype: case OperationCode.Refanyval: case OperationCode.Unbox: case OperationCode.Unbox_Any: /*instruction.Operand1 = stack.Pop(); * stack.Push(instruction); */ currentState.Pop(); //currentState.Push(ValueAbstraction.Top); // Could be smarter than Top currentState.Push(ValueAbstraction.GetAbstractValueForType(FixupTypeForFlow(instruction.Type.ResolvedType))); // Still not right break; case OperationCode.Brfalse: case OperationCode.Brfalse_S: case OperationCode.Brtrue: case OperationCode.Brtrue_S: //instruction.Operand1 = stack.Pop(); currentState.Pop(); break; case OperationCode.Call: /*var signature = instruction.Operation.Value as ISignature; * Contract.Assume(signature != null); //This is an informally specified property of the Metadata model. * if (!signature.IsStatic) instruction.Operand1 = stack.Pop(); * InitializeArgumentsAndPushReturnResult(instruction, stack, signature); */ var signature = instruction.Operation.Value as ISignature; Contract.Assume(signature != null); //This is an informally specified property of the Metadata model. InterpretCallWithSignature(currentState, signature, !signature.IsStatic); break; case OperationCode.Callvirt: /* * instruction.Operand1 = stack.Pop(); * Contract.Assume(instruction.Operation.Value is ISignature); //This is an informally specified property of the Metadata model. * InitializeArgumentsAndPushReturnResult(instruction, stack, (ISignature)instruction.Operation.Value); */ Contract.Assume(instruction.Operation.Value is ISignature); //This is an informally specified property of the Metadata model. InterpretCallWithSignature(currentState, (ISignature)instruction.Operation.Value, true); break; case OperationCode.Calli: /* * Contract.Assume(instruction.Operation.Value is ISignature); //This is an informally specified property of the Metadata model. * InitializeArgumentsAndPushReturnResult(instruction, stack, (ISignature)instruction.Operation.Value); * instruction.Operand1 = stack.Pop(); */ currentState.Pop(); // the method pointer signature = instruction.Operation.Value as ISignature; Contract.Assume(signature != null); //This is an informally specified property of the Metadata model. InterpretCallWithSignature(currentState, (ISignature)instruction.Operation.Value, !signature.IsStatic); break; case OperationCode.Cpobj: case OperationCode.Stfld: 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: case OperationCode.Stobj: /* * instruction.Operand2 = stack.Pop(); * instruction.Operand1 = stack.Pop(); */ currentState.Pop(); currentState.Pop(); break; case OperationCode.Cpblk: case OperationCode.Initblk: case OperationCode.Stelem: case OperationCode.Stelem_I: case OperationCode.Stelem_I1: case OperationCode.Stelem_I2: case OperationCode.Stelem_I4: case OperationCode.Stelem_I8: case OperationCode.Stelem_R4: case OperationCode.Stelem_R8: case OperationCode.Stelem_Ref: /*var indexAndValue = new Instruction[2]; * indexAndValue[1] = stack.Pop(); * indexAndValue[0] = stack.Pop(); * instruction.Operand2 = indexAndValue; * instruction.Operand1 = stack.Pop(); */ currentState.Pop(); currentState.Pop(); currentState.Pop(); break; case OperationCode.Dup: /* * var dupop = stack.Pop(); * instruction.Operand1 = dupop; * stack.Push(dupop); * stack.Push(instruction); */ // Pop the top and push it twice var dupValue = currentState.Pop(); currentState.Push(dupValue); currentState.Push(dupValue); break; case OperationCode.Starg: case OperationCode.Starg_S: { int argumentIndex = GetArgumentIndexFromParameterOperation(instruction.Operation, method); V newArgumentValue = currentState.Pop(); currentState.Arguments[argumentIndex] = newArgumentValue; } break; case OperationCode.Stloc: case OperationCode.Stloc_0: case OperationCode.Stloc_1: case OperationCode.Stloc_2: case OperationCode.Stloc_3: case OperationCode.Stloc_S: { Contract.Assume(instruction.Operation.Value is ILocalDefinition); ILocalDefinition local = instruction.Operation.Value as ILocalDefinition; int localIndex = GetLocalIndexFromLocalOperation(instruction.Operation, method); V newLocalValue = currentState.Pop(); currentState.Locals[localIndex] = newLocalValue; } break; case OperationCode.Endfilter: case OperationCode.Initobj: case OperationCode.Pop: case OperationCode.Stsfld: case OperationCode.Throw: case OperationCode.Switch: //instruction.Operand1 = stack.Pop(); currentState.Pop(); break; case OperationCode.Newobj: /* * Contract.Assume(instruction.Operation.Value is ISignature); //This is an informally specified property of the Metadata model. * InitializeArgumentsAndPushReturnResult(instruction, stack, (ISignature)instruction.Operation.Value); //won't push anything * stack.Push(instruction); */ Contract.Assume(instruction.Operation.Value is IMethodReference); //This is an informally specified property of the Metadata model. InterpretCallWithSignature(currentState, (ISignature)instruction.Operation.Value, false); //won't push anything, since return type is void currentState.Push(ValueAbstraction.GetAbstractValueForType(FixupTypeForFlow(((IMethodReference)instruction.Operation.Value).ResolvedMethod.ContainingTypeDefinition))); break; case OperationCode.Ret: /*if (this.cdfg.MethodBody.MethodDefinition.Type.TypeCode != PrimitiveTypeCode.Void) * instruction.Operand1 = stack.Pop(); */ if (method.Type.TypeCode != PrimitiveTypeCode.Void) { currentState.Pop(); } break; } return(currentState); }
public LocalsAndOperandsStateAbstraction(A ValueAbstraction) { this.ValueAbstraction = ValueAbstraction; top = new LocalsAndOperands <V>(); // We use an arbitrary allocated value to be top }