private bool ProcessOpCall_retval2(MethodDefinition currentMethod, Instruction callInstruction, MethodReference callMethodRef, string methodOpName) { var ILprocessorEx = new ILProcessorEx(currentMethod); if (Match_Stloc(callInstruction.Next)) { Instruction StlocInstruction = callInstruction.Next; int n; Instruction newLdlocaInstruction = Stloc2Ldloca(ILprocessorEx, StlocInstruction, out n); Instruction op_outInstruction = GetMethodRefOp2(ILprocessorEx, callMethodRef, methodOpName); if (op_outInstruction == null) { return(false); } Console.WriteLine(@"Patching " + callMethodRef.FullName + @" (0x" + callInstruction.Offset.ToString("X") + ")"); Console.WriteLine(@" ...into " + ((MethodReference)op_outInstruction.Operand).FullName); ILprocessorEx.Remove(StlocInstruction); ILprocessorEx.InsertBefore(callInstruction, newLdlocaInstruction); // replace 'valuetype Op(...)' with 'void Op(..., out valuetype)' ILprocessorEx.Replace(callInstruction, op_outInstruction); return(true); } return(false); }
private bool ProcessOpCall_retval(MethodDefinition currentMethod, Instruction callInstruction, MethodReference callMethodRef, string methodOpName) { var ILprocessorEx = new ILProcessorEx(currentMethod); int currentParamIdx = callMethodRef.Parameters.Count - 1; // for now we support only operators (with two arguments). currentParamIdx has to be #1. if (currentParamIdx != 1) { throw new InvalidOperationException(); } var currentParam = callMethodRef.Parameters[currentParamIdx]; var isCurrentParamByRef = currentParam.ParameterType.IsByReference; for (var instruction = callInstruction.Previous; instruction != null; instruction = instruction.Previous) { //TODO: check if there is a branch target between instruction and callInstruction and quit // break; if (isCurrentParamByRef == false) { if (Match_Ldloc(instruction)) { Instruction LdlocInstruction = instruction; int n; Instruction newLdlocaInstruction = Ldloc2Ldloca(ILprocessorEx, LdlocInstruction, out n); Instruction op_refInstruction = GetMethodRefOp(ILprocessorEx, callMethodRef, methodOpName, currentParamIdx); if (op_refInstruction == null) { return(false); } Console.WriteLine(@"Patching " + callMethodRef.FullName + @" (0x" + callInstruction.Offset.ToString("X") + ")"); Console.WriteLine(@" ...into " + ((MethodReference)op_refInstruction.Operand).FullName); // replace 'Ldloc' with 'Ldloca' ILprocessorEx.Replace(LdlocInstruction, newLdlocaInstruction); // replace 'vector2 Add(vector2,vector2)' with 'vector2 Add(vector2,vector2)' ILprocessorEx.Replace(callInstruction, op_refInstruction); return(true); } else if (Match_Ldarg(instruction)) { Instruction LdargInstruction = instruction; int n; Instruction newLdargaInstruction = Ldarg2Ldarga(ILprocessorEx, LdargInstruction, out n); // check validity of parameter n var targParam = currentMethod.Parameters[n]; if (targParam.ParameterType.IsByReference == true) { throw new InvalidOperationException(); } Instruction op_refInstruction = GetMethodRefOp(ILprocessorEx, callMethodRef, methodOpName, currentParamIdx); if (op_refInstruction == null) { return(false); } Console.WriteLine(@"Patching " + callMethodRef.FullName + @" (0x" + callInstruction.Offset.ToString("X") + ")"); Console.WriteLine(@" ...into " + ((MethodReference)op_refInstruction.Operand).FullName); // replace 'Ldarg' with 'Ldarga' ILprocessorEx.Replace(LdargInstruction, newLdargaInstruction); // replace 'vector2 Add(vector2,vector2)' with 'vector2 Add(vector2, ref vector2)' ILprocessorEx.Replace(callInstruction, op_refInstruction); return(true); } else if (Match_Ldobj(instruction)) { Instruction LdobjInstruction = instruction; var ldtype = LdobjInstruction.Operand; var type = callMethodRef.Parameters[1]; if (Match_Ldarg(LdobjInstruction.Previous)) { Instruction LdargInstruction = LdobjInstruction.Previous; int n; Instruction newLdargaInstruction = Ldarg2Ldarga(ILprocessorEx, LdargInstruction, out n); // check validity of parameter n var targParam = currentMethod.Parameters[n]; if (targParam.ParameterType.IsByReference == false) { throw new InvalidOperationException(); } Instruction op_refInstruction = GetMethodRefOp(ILprocessorEx, callMethodRef, methodOpName, currentParamIdx); if (op_refInstruction == null) { return(false); } var callOffset = callInstruction.Offset; Console.WriteLine(@"Patching " + callMethodRef.FullName + @" (0x" + callInstruction.Offset.ToString("X") + ")"); Console.WriteLine(@" ...into " + ((MethodReference)op_refInstruction.Operand).FullName); ILprocessorEx.Remove(LdobjInstruction); // replace 'vector2 Add(vector2,vector2)' with 'vector2 Add(vector2, ref vector2)' ILprocessorEx.Replace(callInstruction, op_refInstruction); return(true); } } return(false); } else // (isCurrentParamByRef == true) { if (Match_Ldloca(instruction)) { Instruction LdlocaInstruction = instruction; // argument sucesfully matched. Move to next argument. if (currentParamIdx == 0) { // no more arguments to match. return(false); } else { // Move to next argument. currentParamIdx--; currentParam = callMethodRef.Parameters[currentParamIdx]; isCurrentParamByRef = currentParam.ParameterType.IsByReference; continue; } } return(false); } if (Match_Nop(instruction)) { continue; } if (Match_Break(instruction)) { continue; } // Unkwown instruction. quit break; } return(false); }