/// <summary> /// Determines the number of values that are pushed onto the stack by this instruction. /// </summary> /// <param name="instruction">The instruction.</param> /// <returns>The number of values pushed onto the stack.</returns> /// <exception cref="ArgumentOutOfRangeException">Occurs when the instruction's operation code provides an /// invalid stack behaviour.</exception> public static int GetStackPushCount(this CilInstruction instruction) { switch (instruction.OpCode.StackBehaviourPush) { case CilStackBehaviour.Push0: return(0); case CilStackBehaviour.Push1: case CilStackBehaviour.PushI: case CilStackBehaviour.PushI8: case CilStackBehaviour.PushR4: case CilStackBehaviour.PushR8: case CilStackBehaviour.PushRef: return(1); case CilStackBehaviour.Push1_Push1: return(2); case CilStackBehaviour.VarPush: return(DetermineVarPushCount(instruction)); default: throw new ArgumentOutOfRangeException(); } }
public void OptimizeMacrosArguments() { var instructions = CreateDummyCollection(true); var method = instructions.Owner.Method; for (int i = 0; i <= 256; i++) { method.Signature.Parameters.Add(new ParameterSignature(method.Image.TypeSystem.Object)); } instructions.AddRange(new[] { CilInstruction.Create(CilOpCodes.Ldarg, method.Signature.Parameters[0]), CilInstruction.Create(CilOpCodes.Ldarg, method.Signature.Parameters[1]), CilInstruction.Create(CilOpCodes.Ldarg, method.Signature.Parameters[255]), CilInstruction.Create(CilOpCodes.Ldarg, method.Signature.Parameters[256]), }); instructions.OptimizeMacros(); Assert.Equal(CilCode.Ldarg_0, instructions[0].OpCode.Code); Assert.Null(instructions[0].Operand); Assert.Equal(CilCode.Ldarg_1, instructions[1].OpCode.Code); Assert.Null(instructions[1].Operand); Assert.Equal(CilCode.Ldarg_S, instructions[2].OpCode.Code); Assert.Equal(method.Signature.Parameters[255], instructions[2].Operand); Assert.Equal(CilCode.Ldarg, instructions[3].OpCode.Code); Assert.Equal(method.Signature.Parameters[256], instructions[3].Operand); }
public void PersistentManagedFatMethodVariables() { const string expectedOutput = "Hello, world!"; var assembly = CreateTempAssembly(); var image = assembly.NetDirectory.MetadataHeader.Image; var importer = new ReferenceImporter(image); var mainMethod = image.Assembly.Modules[0].TopLevelTypes.First(x => x.Name == TypeName).Methods.First(x => x.Name == MainMethodName); mainMethod.CilMethodBody.Signature = new StandAloneSignature( new LocalVariableSignature(new[] { image.TypeSystem.String })); var instructions = mainMethod.CilMethodBody.Instructions; instructions.AddRange(new[] { CilInstruction.Create(CilOpCodes.Ldstr, expectedOutput), CilInstruction.Create(CilOpCodes.Stloc_0), CilInstruction.Create(CilOpCodes.Ldloc_0), CilInstruction.Create(CilOpCodes.Call, importer.ImportMethod(typeof(Console).GetMethod("WriteLine", new[] { typeof(string) }))), CilInstruction.Create(CilOpCodes.Ret) }); assembly.NetDirectory.MetadataHeader.UnlockMetadata(); _context.VerifyOutput(assembly, expectedOutput); }
/// <inheritdoc /> protected override DispatchResult Execute(ExecutionContext context, CilInstruction instruction, IntegerValue left, IntegerValue right) { var result = left.IsGreaterThan(right, instruction.OpCode.Code == CilCode.Cgt); return(ConvertToI4AndReturnSuccess(context, result)); }
/// <inheritdoc /> protected override DispatchResult Execute(ExecutionContext context, CilInstruction instruction, IntegerValue value, int shiftCount) { value.LeftShift(shiftCount); context.ProgramState.Stack.Push(value); return(DispatchResult.Success()); }
/// <inheritdoc /> public override DispatchResult Execute(CilExecutionContext context, CilInstruction instruction) { var stack = context.ProgramState.Stack; // Pop arguments. var indexValue = stack.Pop(); var arrayValue = stack.Pop(); // Check if both array and index are known. if (!arrayValue.IsKnown || !indexValue.IsKnown) { stack.Push(GetUnknownElementValue(context, instruction)); return(base.Execute(context, instruction)); } // Expect an int32 or a native int for index, and extract its value. if (indexValue.CliValueType != CliValueType.Int32 && indexValue.CliValueType != CliValueType.NativeInt) { return(DispatchResult.InvalidProgram()); } int index = indexValue.InterpretAsI4().I32; // Obtain element. ICliValue elementValue; switch (arrayValue) { case OValue { IsZero: { Value : TrileanValue.True } } : // Pushed array object is null. return(new DispatchResult(new NullReferenceException()));
public void PersistentEntrypoint() { // Create new assembly. var assembly = NetAssemblyFactory.CreateAssembly(DummyAssemblyName, false); var image = assembly.NetDirectory.MetadataHeader.LockMetadata(); var importer = new ReferenceImporter(image); var writeLine = importer.ImportMethod(typeof(Console).GetMethod("WriteLine", new[] { typeof(string) })); // Create and add main method. var main = new MethodDefinition("Main", MethodAttributes.Public | MethodAttributes.Static, new MethodSignature(image.TypeSystem.Void)); main.CilMethodBody = new CilMethodBody(main); main.CilMethodBody.Instructions.AddRange(new[] { CilInstruction.Create(CilOpCodes.Ldstr, "Hello world!"), CilInstruction.Create(CilOpCodes.Call, writeLine), CilInstruction.Create(CilOpCodes.Ret), }); image.Assembly.Modules[0].TopLevelTypes[0].Methods.Add(main); image.ManagedEntrypoint = main; // Commit. var mapping = image.Header.UnlockMetadata(); // Test. Assert.Equal(mapping[main].ToUInt32(), assembly.NetDirectory.EntryPointToken); var newImage = assembly.NetDirectory.MetadataHeader.LockMetadata(); Assert.Equal(main, newImage.ManagedEntrypoint, _comparer); }
public void PersistentInstructions() { var methodBody = CreateDummyMethodBody(); var image = methodBody.Method.Image; var importer = new ReferenceImporter(image); var writeLine = importer.ImportMethod(typeof(Console).GetMethod("WriteLine", new[] { typeof(string) })); var instructions = methodBody.Instructions; instructions.AddRange(new[] { CilInstruction.Create(CilOpCodes.Ldstr, "Lorem Ipsum"), CilInstruction.Create(CilOpCodes.Call, writeLine), CilInstruction.Create(CilOpCodes.Ret), }); var mapping = image.Header.UnlockMetadata(); image = image.Header.LockMetadata(); var newMethod = (MethodDefinition)image.ResolveMember(mapping[methodBody.Method]); Assert.Equal(instructions, newMethod.CilMethodBody.Instructions, new CilInstructionComparer()); }
public void OperandTypeInts() { const sbyte shortOperand = 0x12; const int operand = 0x1234; const long longOperand = 0x12345678; var methodBody = CreateDummyMethodBody(); var image = methodBody.Method.Image; var instructions = methodBody.Instructions; instructions.AddRange(new[] { CilInstruction.Create(CilOpCodes.Ldc_I4_S, shortOperand), CilInstruction.Create(CilOpCodes.Ldc_I4, operand), CilInstruction.Create(CilOpCodes.Ldc_I8, longOperand), CilInstruction.Create(CilOpCodes.Pop), CilInstruction.Create(CilOpCodes.Pop), CilInstruction.Create(CilOpCodes.Pop), CilInstruction.Create(CilOpCodes.Ret), }); var mapping = image.Header.UnlockMetadata(); image = image.Header.LockMetadata(); var newMethod = (MethodDefinition)image.ResolveMember(mapping[methodBody.Method]); instructions = newMethod.CilMethodBody.Instructions; Assert.Equal(shortOperand, instructions[0].Operand); Assert.Equal(operand, instructions[1].Operand); Assert.Equal(longOperand, instructions[2].Operand); }
public void ComputeMaxStackConditionalBranch() { var methodBody = CreateDummyMethodBody(); var importer = new ReferenceImporter(methodBody.Method.Image); var writeLine = importer.ImportMethod(typeof(Console).GetMethod("WriteLine", new[] { typeof(int) })); var instructions = methodBody.Instructions; var elseInstr = CilInstruction.Create(CilOpCodes.Sub); var endInstr = CilInstruction.Create(CilOpCodes.Call, writeLine); instructions.AddRange(new[] { CilInstruction.Create(CilOpCodes.Ldc_I4_1), CilInstruction.Create(CilOpCodes.Ldc_I4_2), CilInstruction.Create(CilOpCodes.Ldc_I4_0), CilInstruction.Create(CilOpCodes.Brtrue, elseInstr), CilInstruction.Create(CilOpCodes.Add), CilInstruction.Create(CilOpCodes.Br, endInstr), elseInstr, endInstr, CilInstruction.Create(CilOpCodes.Ret) }); Assert.Equal(3, methodBody.ComputeMaxStack()); }
public void StackInbalanceLoop() { var methodBody = CreateDummyMethodBody(); var importer = new ReferenceImporter(methodBody.Method.Image); var writeLine = importer.ImportMethod(typeof(Console).GetMethod("WriteLine", new[] { typeof(int) })); var instructions = methodBody.Instructions; var loopHead = CilInstruction.Create(CilOpCodes.Nop); instructions.AddRange(new[] { loopHead, CilInstruction.Create(CilOpCodes.Ldc_I4_1), CilInstruction.Create(CilOpCodes.Ldc_I4_2), CilInstruction.Create(CilOpCodes.Add), CilInstruction.Create(CilOpCodes.Call, writeLine), CilInstruction.Create(CilOpCodes.Ldc_I4_0), CilInstruction.Create(CilOpCodes.Ldc_I4_1), CilInstruction.Create(CilOpCodes.Brtrue, loopHead), CilInstruction.Create(CilOpCodes.Ret), }); Assert.Throws <StackInbalanceException>(() => methodBody.ComputeMaxStack()); }
/// <inheritdoc /> public override DispatchResult Execute(ExecutionContext context, CilInstruction instruction) { var stack = context.ProgramState.Stack; // Pop arguments. var lengthValue = (ICliValue)stack.Pop(); var sourceAddress = (ICliValue)stack.Pop(); var destinationAddress = (ICliValue)stack.Pop(); // Interpret arguments. if (!(destinationAddress is IPointerValue destinationPointer) || !(sourceAddress is IPointerValue sourcePointer)) { return(DispatchResult.InvalidProgram()); } if (!lengthValue.IsKnown) { throw new DispatchException("Number of bytes to copy is unknown."); } int length = lengthValue.InterpretAsI4().I32; // Copy data. Span <byte> data = stackalloc byte[length]; Span <byte> bitmask = stackalloc byte[length]; sourcePointer.ReadBytes(0, data, bitmask); destinationPointer.WriteBytes(0, data, bitmask); return(base.Execute(context, instruction)); }
/// <summary> /// When this instruction is using a variant of the ldarg or starg opcodes, gets the parameter that is /// referenced by the instruction. /// </summary> /// <param name="instruction">The instruction.</param> /// <param name="parameters">The parameters defined in the enclosing method body.</param> /// <returns>The parameter.</returns> /// <exception cref="ArgumentException">Occurs when the instruction is not using a variant of the ldarg or starg opcodes.</exception> public static Parameter GetParameter(this CilInstruction instruction, ParameterCollection parameters) { switch (instruction.OpCode.Code) { case CilCode.Ldarg: case CilCode.Ldarg_S: case CilCode.Ldarga: case CilCode.Ldarga_S: case CilCode.Starg: case CilCode.Starg_S: return((Parameter)instruction.Operand); case CilCode.Ldarg_0: return(parameters.GetBySignatureIndex(0)); case CilCode.Ldarg_1: return(parameters.GetBySignatureIndex(1)); case CilCode.Ldarg_2: return(parameters.GetBySignatureIndex(2)); case CilCode.Ldarg_3: return(parameters.GetBySignatureIndex(3)); default: throw new ArgumentException("Instruction is not a ldarg or starg instruction."); } }
/// <summary> /// When this instruction is using a variant of the ldloc or stloc opcodes, gets the local variable that is /// referenced by the instruction. /// </summary> /// <param name="instruction">The instruction.</param> /// <param name="variables">The local variables defined in the enclosing method body.</param> /// <returns>The variable.</returns> /// <exception cref="ArgumentException">Occurs when the instruction is not using a variant of the ldloc or stloc opcodes.</exception> public static CilLocalVariable GetLocalVariable(this CilInstruction instruction, IReadOnlyList <CilLocalVariable> variables) { switch (instruction.OpCode.Code) { case CilCode.Ldloc: case CilCode.Ldloc_S: case CilCode.Stloc: case CilCode.Stloc_S: case CilCode.Ldloca: case CilCode.Ldloca_S: return((CilLocalVariable)instruction.Operand); case CilCode.Ldloc_0: case CilCode.Stloc_0: return(variables[0]); case CilCode.Ldloc_1: case CilCode.Stloc_1: return(variables[1]); case CilCode.Ldloc_2: case CilCode.Stloc_2: return(variables[2]); case CilCode.Ldloc_3: case CilCode.Stloc_3: return(variables[3]); default: throw new ArgumentException("Instruction is not a ldloc or stloc instruction."); } }
public void OperandTypeField() { var methodBody = CreateDummyMethodBody(); var image = methodBody.Method.Image; var importer = new ReferenceImporter(image); var instructions = methodBody.Instructions; var simpleField = importer.ImportField(typeof(Type).GetField("EmptyTypes", BindingFlags.Public | BindingFlags.Static)); instructions.AddRange(new[] { CilInstruction.Create(CilOpCodes.Ldsfld, simpleField), CilInstruction.Create(CilOpCodes.Pop), CilInstruction.Create(CilOpCodes.Ret), }); var mapping = image.Header.UnlockMetadata(); image = image.Header.LockMetadata(); var newMethod = (MethodDefinition)image.ResolveMember(mapping[methodBody.Method]); instructions = newMethod.CilMethodBody.Instructions; Assert.Equal(simpleField, instructions[0].Operand as IMemberReference, _comparer); }
public void OperandTypeReals() { const float shortOperand = 0.1234F; const double operand = 0.1234; var methodBody = CreateDummyMethodBody(); var image = methodBody.Method.Image; var instructions = methodBody.Instructions; instructions.AddRange(new[] { CilInstruction.Create(CilOpCodes.Ldc_R4, shortOperand), CilInstruction.Create(CilOpCodes.Ldc_R8, operand), CilInstruction.Create(CilOpCodes.Pop), CilInstruction.Create(CilOpCodes.Pop), CilInstruction.Create(CilOpCodes.Ret), }); var mapping = image.Header.UnlockMetadata(); image = image.Header.LockMetadata(); var newMethod = (MethodDefinition)image.ResolveMember(mapping[methodBody.Method]); instructions = newMethod.CilMethodBody.Instructions; Assert.Equal(shortOperand, instructions[0].Operand); Assert.Equal(operand, instructions[1].Operand); }
public void OperandTypeSig() { var methodBody = CreateDummyMethodBody(); var image = methodBody.Method.Image; var importer = new ReferenceImporter(image); var instructions = methodBody.Instructions; var signature = importer.ImportStandAloneSignature( new StandAloneSignature(new MethodSignature(image.TypeSystem.Void) { HasThis = false })); instructions.AddRange(new[] { CilInstruction.Create(CilOpCodes.Calli, signature), CilInstruction.Create(CilOpCodes.Ret) }); var mapping = image.Header.UnlockMetadata(); image = image.Header.LockMetadata(); var newMethod = (MethodDefinition)image.ResolveMember(mapping[methodBody.Method]); instructions = newMethod.CilMethodBody.Instructions; var newSignature = (StandAloneSignature)instructions[0].Operand; Assert.Equal(signature.Signature as MethodSignature, newSignature.Signature as MethodSignature, _comparer); }
public void OperandTypeBranchTarget() { var methodBody = CreateDummyMethodBody(); var image = methodBody.Method.Image; var instructions = methodBody.Instructions; var target1 = CilInstruction.Create(CilOpCodes.Nop); var target2 = CilInstruction.Create(CilOpCodes.Nop); instructions.AddRange(new[] { CilInstruction.Create(CilOpCodes.Br, target1), target2, CilInstruction.Create(CilOpCodes.Ret), target1, CilInstruction.Create(CilOpCodes.Br, target2), }); methodBody.Instructions.CalculateOffsets(); var mapping = image.Header.UnlockMetadata(); image = image.Header.LockMetadata(); var newMethod = (MethodDefinition)image.ResolveMember(mapping[methodBody.Method]); instructions = newMethod.CilMethodBody.Instructions; Assert.Equal(target1.Offset, ((CilInstruction)instructions[0].Operand).Offset); Assert.Equal(target2.Offset, ((CilInstruction)instructions[4].Operand).Offset); }
/// <inheritdoc /> protected override DispatchResult Execute(ExecutionContext context, CilInstruction instruction, FValue left, FValue right) { bool result = left.IsLessThan(right, instruction.OpCode.Code == CilCode.Clt_Un); return(ConvertToI4AndReturnSuccess(context, result)); }
public void OperandTypeSwitch() { var methodBody = CreateDummyMethodBody(); var image = methodBody.Method.Image; var instructions = methodBody.Instructions; var target1 = CilInstruction.Create(CilOpCodes.Nop); var target2 = CilInstruction.Create(CilOpCodes.Nop); var target3 = CilInstruction.Create(CilOpCodes.Nop); instructions.AddRange(new[] { CilInstruction.Create(CilOpCodes.Ldc_I4_1), CilInstruction.Create(CilOpCodes.Switch, new[] { target1, target2, target3 }), target2, CilInstruction.Create(CilOpCodes.Ret), target1, CilInstruction.Create(CilOpCodes.Ret), target3, CilInstruction.Create(CilOpCodes.Ret), }); methodBody.Instructions.CalculateOffsets(); var mapping = image.Header.UnlockMetadata(); image = image.Header.LockMetadata(); var newMethod = (MethodDefinition)image.ResolveMember(mapping[methodBody.Method]); var targets = (IList <CilInstruction>)newMethod.CilMethodBody.Instructions[1].Operand; Assert.Equal(target1.Offset, targets[0].Offset); Assert.Equal(target2.Offset, targets[1].Offset); Assert.Equal(target3.Offset, targets[2].Offset); }
public void EntrypointNotAdded() { // Create new assembly. var assembly = NetAssemblyFactory.CreateAssembly(DummyAssemblyName, false); var image = assembly.NetDirectory.MetadataHeader.LockMetadata(); var importer = new ReferenceImporter(image); var writeLine = importer.ImportMethod(typeof(Console).GetMethod("WriteLine", new[] { typeof(string) })); // Create but don't add main method. var main = new MethodDefinition("Main", MethodAttributes.Public | MethodAttributes.Static, new MethodSignature(image.TypeSystem.Void)); main.CilMethodBody = new CilMethodBody(main); main.CilMethodBody.Instructions.AddRange(new[] { CilInstruction.Create(CilOpCodes.Ldstr, "Hello world!"), CilInstruction.Create(CilOpCodes.Call, writeLine), CilInstruction.Create(CilOpCodes.Ret), }); image.ManagedEntrypoint = main; Assert.Throws <MemberNotImportedException>(() => image.Header.UnlockMetadata()); }
public void OperandTypeVar() { var methodBody = CreateDummyMethodBody(); var image = methodBody.Method.Image; var instructions = methodBody.Instructions; var var1 = new VariableSignature(image.TypeSystem.Boolean); var var2 = new VariableSignature(image.TypeSystem.Int32); methodBody.Signature = new StandAloneSignature(new LocalVariableSignature(new[] { var1, var2 })); instructions.AddRange(new[] { CilInstruction.Create(CilOpCodes.Ldloc, var1), CilInstruction.Create(CilOpCodes.Stloc, var1), CilInstruction.Create(CilOpCodes.Ldloc, var2), CilInstruction.Create(CilOpCodes.Stloc, var2), CilInstruction.Create(CilOpCodes.Ret) }); var mapping = image.Header.UnlockMetadata(); image = image.Header.LockMetadata(); var newMethod = (MethodDefinition)image.ResolveMember(mapping[methodBody.Method]); instructions = newMethod.CilMethodBody.Instructions; Assert.Equal(var1.VariableType, ((VariableSignature)instructions[0].Operand).VariableType, _comparer); Assert.Equal(var1.VariableType, ((VariableSignature)instructions[1].Operand).VariableType, _comparer); Assert.Equal(var2.VariableType, ((VariableSignature)instructions[2].Operand).VariableType, _comparer); Assert.Equal(var2.VariableType, ((VariableSignature)instructions[3].Operand).VariableType, _comparer); }
/// <inheritdoc /> protected override DispatchResult Execute(CilExecutionContext context, CilInstruction instruction, OValue left, OValue right) { var result = left.IsEqualTo(right); return(ConvertToI4AndReturnSuccess(context, result)); }
public void OperandTypeArgument() { var methodBody = CreateDummyMethodBody(); var image = methodBody.Method.Image; var instructions = methodBody.Instructions; var param1 = new ParameterSignature(image.TypeSystem.Boolean); var param2 = new ParameterSignature(image.TypeSystem.Int32); methodBody.Method.Signature = new MethodSignature(new[] { param1, param2 }, image.TypeSystem.Void); instructions.AddRange(new[] { CilInstruction.Create(CilOpCodes.Ldarg, param1), CilInstruction.Create(CilOpCodes.Starg, param1), CilInstruction.Create(CilOpCodes.Ldarg, param2), CilInstruction.Create(CilOpCodes.Starg, param2), CilInstruction.Create(CilOpCodes.Ret), }); var mapping = image.Header.UnlockMetadata(); image = image.Header.LockMetadata(); var newMethod = (MethodDefinition)image.ResolveMember(mapping[methodBody.Method]); instructions = newMethod.CilMethodBody.Instructions; Assert.Equal(param1.ParameterType, ((ParameterSignature)instructions[0].Operand).ParameterType, _comparer); Assert.Equal(param1.ParameterType, ((ParameterSignature)instructions[1].Operand).ParameterType, _comparer); Assert.Equal(param2.ParameterType, ((ParameterSignature)instructions[2].Operand).ParameterType, _comparer); Assert.Equal(param2.ParameterType, ((ParameterSignature)instructions[3].Operand).ParameterType, _comparer); }
/// <inheritdoc /> public override DispatchResult Execute(CilExecutionContext context, CilInstruction instruction) { var environment = context.GetService <ICilRuntimeEnvironment>(); var variables = new IVariable[1]; if (environment.Architecture.GetReadVariables(instruction, variables) != 1) { throw new DispatchException( $"Architecture returned an incorrect number of variables being read from instruction {instruction}."); } switch (variables[0]) { case CilParameter parameter: var value = environment.CliMarshaller.ToCliValue( context.ProgramState.Variables[variables[0]], parameter.Parameter.ParameterType); context.ProgramState.Stack.Push(value); return(base.Execute(context, instruction)); default: return(DispatchResult.InvalidProgram()); } }
public void OperandTypeString() { var methodBody = CreateDummyMethodBody(); var image = methodBody.Method.Image; var instructions = methodBody.Instructions; const string operand = "Lorem Ipsum Dolor Sit Amet"; instructions.AddRange(new[] { CilInstruction.Create(CilOpCodes.Ldstr, operand), CilInstruction.Create(CilOpCodes.Pop), CilInstruction.Create(CilOpCodes.Ret), }); var mapping = image.Header.UnlockMetadata(); image = image.Header.LockMetadata(); var newMethod = (MethodDefinition)image.ResolveMember(mapping[methodBody.Method]); instructions = newMethod.CilMethodBody.Instructions; Assert.Equal(operand, instructions[0].Operand); }
public void OptimizeMacrosThisParameter() { var instructions = CreateDummyCollection(false); var method = instructions.Owner.Method; for (int i = 0; i < 2; i++) { method.Signature.Parameters.Add(new ParameterSignature(method.Image.TypeSystem.Object)); } instructions.AddRange(new[] { CilInstruction.Create(CilOpCodes.Ldarg, method.CilMethodBody.ThisParameter), CilInstruction.Create(CilOpCodes.Ldarg, method.Signature.Parameters[0]), CilInstruction.Create(CilOpCodes.Ldarg, method.Signature.Parameters[1]), }); instructions.OptimizeMacros(); Assert.Equal(CilCode.Ldarg_0, instructions[0].OpCode.Code); Assert.Null(instructions[0].Operand); Assert.Equal(CilCode.Ldarg_1, instructions[1].OpCode.Code); Assert.Null(instructions[1].Operand); Assert.Equal(CilCode.Ldarg_2, instructions[2].OpCode.Code); Assert.Null(instructions[2].Operand); }
public void OperandTypeType() { var methodBody = CreateDummyMethodBody(); var image = methodBody.Method.Image; var importer = new ReferenceImporter(image); var instructions = methodBody.Instructions; var simpleType = importer.ImportType(typeof(Form)); instructions.Add(CilInstruction.Create(CilOpCodes.Ldtoken, simpleType)); instructions.Add(CilInstruction.Create(CilOpCodes.Pop)); var genericType = importer.ImportType(typeof(List <Form>)); instructions.Add(CilInstruction.Create(CilOpCodes.Ldtoken, genericType)); instructions.Add(CilInstruction.Create(CilOpCodes.Pop)); instructions.Add(CilInstruction.Create(CilOpCodes.Ret)); var mapping = image.Header.UnlockMetadata(); image = image.Header.LockMetadata(); var newMethod = (MethodDefinition)image.ResolveMember(mapping[methodBody.Method]); instructions = newMethod.CilMethodBody.Instructions; Assert.Equal(simpleType, instructions[0].Operand as ITypeDescriptor, _comparer); Assert.Equal(genericType, instructions[2].Operand as ITypeDescriptor, _comparer); }
/// <inheritdoc /> public override DispatchResult Execute(CilExecutionContext context, CilInstruction instruction) { var environment = context.GetService <ICilRuntimeEnvironment>(); var field = ((IFieldDescriptor)instruction.Operand).Resolve(); var stack = context.ProgramState.Stack; var objectValue = stack.Pop(); IConcreteValue fieldValue; if (field.IsStatic) { // Undocumented: The runtime does allow access of static fields through the ldfld opcode. // In this case, the object instance that is pushed is ignored, allowing constructs like: // // ldnull // ldfld <some_static_field> // // without the runtime throwing a NullReferenceException. var staticField = environment.StaticFieldFactory.Get(field); fieldValue = environment.CliMarshaller.ToCliValue(staticField.Value, field.Signature.FieldType); } else { // Attempt to dereference the object instance. switch (objectValue) { case { IsKnown: false } :
/// <inheritdoc /> public override DispatchResult Execute(ExecutionContext context, CilInstruction instruction) { var stack = context.ProgramState.Stack; stack.Push((ICliValue)stack.Top.Copy()); return(base.Execute(context, instruction)); }