static bool IsThisOrDup(Instruction instr) { return instr.GetParameterIndex() == 0 || instr.OpCode.Code == Code.Dup; }
protected InstructionPatcher tryInlineOtherMethod(int patchIndex, MethodDef methodToInline, Instruction instr, int instrIndex, int popLastArgs) { int loadIndex = 0; int methodArgsCount = DotNetUtils.getArgsCount(methodToInline); bool foundLdarga = false; while (instr != null && loadIndex < methodArgsCount) { bool isLdarg = true; switch (instr.OpCode.Code) { case Code.Ldarg: case Code.Ldarg_S: case Code.Ldarg_0: case Code.Ldarg_1: case Code.Ldarg_2: case Code.Ldarg_3: break; case Code.Ldarga: case Code.Ldarga_S: foundLdarga = true; break; default: isLdarg = false; break; } if (!isLdarg) break; if (instr.GetParameterIndex() != loadIndex) return null; loadIndex++; instr = DotNetUtils.getInstruction(methodToInline.Body.Instructions, ref instrIndex); instr = onAfterLoadArg(methodToInline, instr, ref instrIndex); } if (instr == null || loadIndex != methodArgsCount - popLastArgs) return null; if (instr.OpCode.Code == Code.Call || instr.OpCode.Code == Code.Callvirt) { if (foundLdarga) return null; var callInstr = instr; var calledMethod = callInstr.Operand as IMethod; if (calledMethod == null) return null; if (!isCompatibleType(-1, calledMethod.MethodSig.RetType, methodToInline.MethodSig.RetType)) return null; if (!checkSameMethods(calledMethod, methodToInline, popLastArgs)) return null; if (!hasAccessTo(instr.Operand)) return null; return new InstructionPatcher(patchIndex, instrIndex, callInstr); } else if (instr.OpCode.Code == Code.Newobj) { if (foundLdarga) return null; var newobjInstr = instr; var ctor = newobjInstr.Operand as IMethod; if (ctor == null) return null; if (!isCompatibleType(-1, ctor.DeclaringType, methodToInline.MethodSig.RetType)) return null; var methodArgs = methodToInline.Parameters; var calledMethodArgs = DotNetUtils.getArgs(ctor); if (methodArgs.Count + 1 - popLastArgs != calledMethodArgs.Count) return null; for (int i = 1; i < calledMethodArgs.Count; i++) { if (!isCompatibleType(i, calledMethodArgs[i], methodArgs[i - 1].Type)) return null; } if (!hasAccessTo(instr.Operand)) return null; return new InstructionPatcher(patchIndex, instrIndex, newobjInstr); } else if (instr.OpCode.Code == Code.Ldfld || instr.OpCode.Code == Code.Ldflda || instr.OpCode.Code == Code.Ldftn || instr.OpCode.Code == Code.Ldvirtftn) { var ldInstr = instr; if (methodArgsCount != 1) return null; if (!hasAccessTo(instr.Operand)) return null; return new InstructionPatcher(patchIndex, instrIndex, ldInstr); } return null; }