Instruction ReplaceCalli(ILProcessor ilProcessor, Instruction instruction, MethodReference calledMethod) { //public static unsafe void Calli( //System.Runtime.InteropServices.CallingConvention callingConvention, Type returnType, Type arg0, ...) var stack = Analysis[instruction.Previous]; Tuple <Instruction, StackAnalyser.StackEntry> entry; var module = ilProcessor.Body.Method.Module; var args = new List <Tuple <Instruction, StackAnalyser.StackEntry> >(); for (int i = 0; i < calledMethod.Parameters.Count - 2; ++i) { entry = stack.Head; stack = stack.Tail; args.Add(entry); } args.Reverse(); entry = stack.Head; stack = stack.Tail; var returnType = entry; entry = stack.Head; stack = stack.Tail; var callingConvention = entry.Item2; Mono.Cecil.MethodCallingConvention methodCallingConvention; if (callingConvention.IsConstant) { switch ((System.Runtime.InteropServices.CallingConvention)callingConvention.Value) { case System.Runtime.InteropServices.CallingConvention.Cdecl: methodCallingConvention = MethodCallingConvention.C; break; case System.Runtime.InteropServices.CallingConvention.FastCall: methodCallingConvention = MethodCallingConvention.FastCall; break; case System.Runtime.InteropServices.CallingConvention.StdCall: methodCallingConvention = MethodCallingConvention.StdCall; break; case System.Runtime.InteropServices.CallingConvention.ThisCall: methodCallingConvention = MethodCallingConvention.ThisCall; break; case System.Runtime.InteropServices.CallingConvention.Winapi: methodCallingConvention = MethodCallingConvention.StdCall; break; default: methodCallingConvention = MethodCallingConvention.Default; break; } } else { Console.WriteLine("Calling convention passed to Calli is not a constant expression."); var next = instruction.Next; StackAnalyser.RemoveInstructionChain(ilProcessor.Body.Method, instruction, Analysis); return(next); } TypeReference returnTypeReference = null; if (returnType.Item2.IsConstant) { Type retTy = returnType.Item2.Value; returnTypeReference = module.Import(retTy); } else if (returnType.Item1.OpCode == OpCodes.Call && returnType.Item1.Operand is MethodReference && (returnType.Item1.Operand as MethodReference).Name == "GetTypeFromHandle") { var ldtoken_stack = Analysis[returnType.Item1.Previous]; var ldtoken = ldtoken_stack.Head; returnTypeReference = ldtoken.Item1.Operand as TypeReference; } if (returnTypeReference == null) { Console.WriteLine("Return type passed to Calli is not a constant expression."); var next = instruction.Next; StackAnalyser.RemoveInstructionChain(ilProcessor.Body.Method, instruction, Analysis); return(next); } TypeReference[] parameterTypesArray = new TypeReference[args.Count]; for (int i = 0; i < args.Count; ++i) { var arg = args[i]; if (arg.Item2.IsConstant) { parameterTypesArray[i] = module.Import((Type)arg.Item2.Value); } else if (arg.Item1.OpCode == OpCodes.Call && arg.Item1.Operand is MethodReference && (arg.Item1.Operand as MethodReference).Name == "GetTypeFromHandle") { var ldtoken_stack = Analysis[arg.Item1.Previous]; var ldtoken = ldtoken_stack.Head; parameterTypesArray[i] = ldtoken.Item1.Operand as TypeReference; } } if (parameterTypesArray.Any(ty => ty == null)) { Console.WriteLine("Type passed to Calli is not a constant expression."); var next = instruction.Next; StackAnalyser.RemoveInstructionChain(ilProcessor.Body.Method, instruction, Analysis); return(next); } var callSite = new CallSite(returnTypeReference); callSite.CallingConvention = methodCallingConvention; foreach (var parameterType in parameterTypesArray) { callSite.Parameters.Add(new ParameterDefinition(parameterType)); } { var calli = Instruction.Create(OpCodes.Calli, callSite); ilProcessor.InsertAfter(instruction, calli); StackAnalyser.RemoveInstructionChain(ilProcessor.Body.Method, instruction, Analysis); return(calli.Next); } }