Exemple #1
0
        static bool IsCallMethod(MethodDef method)
        {
            int loadIndex       = 0;
            int methodArgsCount = DotNetUtils.GetArgsCount(method);
            var instrs          = method.Body.Instructions;
            int i = 0;

            for (; i < instrs.Count && i < methodArgsCount; i++)
            {
                var instr = instrs[i];
                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:
                case Code.Ldarga:
                case Code.Ldarga_S:
                    if (instr.GetParameterIndex() != loadIndex)
                    {
                        return(false);
                    }
                    loadIndex++;
                    continue;
                }
                break;
            }
            if (loadIndex != methodArgsCount)
            {
                return(false);
            }
            if (i + 1 >= instrs.Count)
            {
                return(false);
            }

            switch (instrs[i].OpCode.Code)
            {
            case Code.Call:
            case Code.Callvirt:
            case Code.Newobj:
            case Code.Ldfld:
            case Code.Ldflda:
            case Code.Ldftn:
            case Code.Ldvirtftn:
                break;

            default:
                return(false);
            }
            if (instrs[i + 1].OpCode.Code != Code.Ret)
            {
                return(false);
            }

            return(true);
        }
        protected bool InlineLoadMethod(int patchIndex, MethodDef methodToInline, Instruction loadInstr, int instrIndex)
        {
            if (!IsReturn(methodToInline, instrIndex))
            {
                return(false);
            }

            int methodArgsCount = DotNetUtils.GetArgsCount(methodToInline);

            for (int i = 0; i < methodArgsCount; i++)
            {
                block.Insert(patchIndex++, OpCodes.Pop.ToInstruction());
            }

            block.Instructions[patchIndex] = new Instr(loadInstr.Clone());
            return(true);
        }
 public UpdatedMethod(MethodDef method)
 {
     token       = method.MDToken.ToInt32();
     newArgTypes = new TypeSig[DotNetUtils.GetArgsCount(method)];
 }
        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);
            }

            switch (instr.OpCode.Code)
            {
            case Code.Call:
            case 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));

            case 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));

            case Code.Ldfld:
            case Code.Ldflda:
            case Code.Ldftn:
            case Code.Ldvirtftn:
            case Code.Ldlen:
            case Code.Initobj:
            case Code.Isinst:
            case Code.Castclass:
            case Code.Newarr:
            case Code.Ldtoken:
            case Code.Unbox_Any:
                var ldInstr = instr;
                if (methodArgsCount != 1)
                {
                    return(null);
                }

                if (instr.OpCode.OperandType != OperandType.InlineNone && !HasAccessTo(instr.Operand))
                {
                    return(null);
                }

                return(new InstructionPatcher(patchIndex, instrIndex, ldInstr));

            default:
                return(null);
            }
        }