private static void EmitILForConstructor(ILGenerator ilGenerator, OperandInstruction <MethodBase> instruction, ConstructorInfo constructorInfo, int contextParamIndex) { /*if (PoseContext.StubCache.TryGetValue(constructorInfo, out DynamicMethod stub)) * { * ilGenerator.Emit(OpCodes.Ldtoken, constructorInfo); * ilGenerator.Emit(OpCodes.Ldtoken, constructorInfo.DeclaringType); * ilGenerator.Emit(OpCodes.Call, stub); * return; * }*/ var methodBody = constructorInfo.GetMethodBody(); if (methodBody == null) { ilGenerator.Emit(instruction.OpCode, constructorInfo); return; } if (instruction.OpCode != OpCodes.Newobj && instruction.OpCode != OpCodes.Call) { ilGenerator.Emit(instruction.OpCode, constructorInfo); return; } var stub = StubGenerator.GenerateStub(constructorInfo, instruction.OpCode == OpCodes.Newobj); ilGenerator.Emit(OpCodes.Ldarg, contextParamIndex); ilGenerator.Emit(OpCodes.Call, stub); //PoseContext.StubCache.TryAdd(constructorInfo, stub); }
private static void EmitILForMethod(ILGenerator ilGenerator, OperandInstruction <MethodBase> instruction, MethodInfo methodInfo, ShimContext context, int contextParamIndex) { /*if (context.StubCache.TryGetValue(methodInfo, out DynamicMethod stub)) * { * ilGenerator.Emit(OpCodes.Ldtoken, methodInfo); * ilGenerator.Emit(OpCodes.Ldtoken, methodInfo.DeclaringType); * ilGenerator.Emit(OpCodes.Call, stub); * return; * }*/ var methodBody = methodInfo.GetMethodBody(); if (methodBody == null) { ilGenerator.Emit(instruction.OpCode, methodInfo); return; } MethodInfo stub; if (instruction.OpCode == OpCodes.Call) { stub = StubGenerator.GenerateStubForMethod(methodInfo); } else if (instruction.OpCode == OpCodes.Callvirt) { stub = StubGenerator.GenerateStubForVirtualMethod(methodInfo); } /*else if (instruction.OpCode == OpCodes.Ldftn) * { * stub = StubGenerator.GenerateStubForMethodPointer(methodInfo); * } * else if (instruction.OpCode == OpCodes.Ldvirtftn) * { * stub = StubGenerator.GenerateStubForMethodPointer(methodInfo); * }*/ else { ilGenerator.Emit(instruction.OpCode, methodInfo); return; } ilGenerator.Emit(OpCodes.Ldarg, contextParamIndex); ilGenerator.Emit(OpCodes.Call, stub); //PoseContext.StubCache.TryAdd(methodInfo, stub); }
private static List <ILProcessorInstruction> TranslateInstructions(IReadOnlyList <ILInstruction> instructions) { //Convert all instructions into processor instructions var offsetMap = new Dictionary <int, ILProcessorInstruction>(); var newInstructions = new List <ILProcessorInstruction>(); ILProcessorInstruction lastInstruction = null; foreach (var instruction in instructions) { var processorInstruction = TranslateInstruction(instruction); newInstructions.Add(processorInstruction); offsetMap.Add(instruction.Offset, processorInstruction); if (lastInstruction != null) { lastInstruction.Next = processorInstruction; } processorInstruction.Prev = lastInstruction; lastInstruction = processorInstruction; } //Set the correct TargetInstruction for Branch and Switches foreach (var(instruction, oldInstruction) in newInstructions.Zip(instructions, (i, oi) => (Instruction: i, OldInstruction:oi))) { switch (instruction) { case OperandInstruction <ILProcessorInstruction> branchInstruction: var targetOffset = (oldInstruction as InlineBrTargetInstruction)?.TargetOffset ?? (oldInstruction as ShortInlineBrTargetInstruction)?.TargetOffset ?? throw new ArgumentException(); branchInstruction.Operand = offsetMap[targetOffset]; break; case OperandInstruction <IReadOnlyList <ILProcessorInstruction> > switchInstruction: var targetOffsets = (oldInstruction as InlineSwitchInstruction)?.TargetOffsets ?? throw new ArgumentException(); switchInstruction.Operand = targetOffsets.Select(o => offsetMap[o]).ToList(); break; } } return(newInstructions); ILProcessorInstruction TranslateInstruction(ILInstruction instruction) { var opCode = instruction.OpCode; switch (instruction) { case InlineNoneInstruction _: return(new NoneInstruction(opCode)); case ShortInlineBrTargetInstruction _: case InlineBrTargetInstruction _: return(OperandInstruction.Create(opCode, (ILProcessorInstruction)null)); case InlineSwitchInstruction _: return(OperandInstruction.Create(opCode, (IReadOnlyList <ILProcessorInstruction>)null)); case InlineFieldInstruction matched: return(OperandInstruction.Create(opCode, matched.Operand)); case InlineI8Instruction matched: return(OperandInstruction.Create(opCode, matched.Operand)); case InlineIInstruction matched: return(OperandInstruction.Create(opCode, matched.Operand)); case InlineMethodInstruction matched: return(OperandInstruction.Create(opCode, matched.Method)); case InlineRInstruction matched: return(OperandInstruction.Create(opCode, matched.Operand)); case InlineSigInstruction matched: return(OperandInstruction.Create(opCode, matched.Signature)); case InlineStringInstruction matched: return(OperandInstruction.Create(opCode, matched.Operand)); case InlineTokInstruction matched: return(OperandInstruction.Create(opCode, matched.Member)); case InlineTypeInstruction matched: return(OperandInstruction.Create(opCode, matched.Operand)); case ShortInlineVarInstruction matched: return(OperandInstruction.Create(opCode, matched.Ordinal)); case InlineVarInstruction matched: return(OperandInstruction.Create(opCode, matched.Ordinal)); case ShortInlineIInstruction matched: return(OperandInstruction.Create(opCode, matched.Operand)); case ShortInlineRInstruction matched: return(OperandInstruction.Create(opCode, matched.Operand)); default: throw new ArgumentException("Unknown instruction!", nameof(instruction)); } } }