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; } }
// 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); }