Example #1
0
        // See also: InteropManager::IsInlinable
        private bool PrimIsInlinable(CST.AssemblyDef assemblyDef, CST.TypeDef typeDef, CST.MethodDef methodDef)
        {
            if (!CouldBeInlinableBasedOnHeaderAlone(assemblyDef, typeDef, methodDef))
                return false;

            if (methodDef.IsRecursive)
                // No recursive methods
                return false;

            if (methodDef.IsConstructor)
                // No instance constructors (since we can't enline NewExpressions yet), and
                // no static constructors (since we can't inline calls emitted in assembly Initialize)
                return false;

            if (env.InteropManager.IsImported(assemblyDef, typeDef, methodDef) ||
                env.InteropManager.IsExported(assemblyDef, typeDef, methodDef))
                // No imported methods (we inline separately), and
                // no exported methods (we need the definition around to be able to export it)
                return false;

            if (methodDef.MethodBody == null || methodDef.MethodBody.Instructions.Length == 0)
                // No empty methods or imported methods
                return false;

            var numReturns = 0;
            var instructions = methodDef.Instructions(env.Global);
            if (!instructions.IsInlinable(ref numReturns) || numReturns != 1)
                // Non-inlinable instructions
                return false;

            var code = instructions.Body[instructions.Body.Count - 1].Code;
            if (code != CST.InstructionCode.Ret && code != CST.InstructionCode.RetVal)
                // Last instruction is not return
                return false;

            // NOTE: Even though instructions have a single return, it is still possible the translated statatements
            //       won't have a unique result, so unfortunately we need to check that below

            var isInline = default(bool);
            var overrideInline = env.AttributeHelper.GetValueFromMethod
                (assemblyDef,
                 typeDef,
                 methodDef,
                 env.AttributeHelper.InlineAttributeRef,
                 env.AttributeHelper.TheIsInlinedProperty,
                 true,
                 false,
                 ref isInline);

            if (overrideInline && !isInline)
                // User has supressed inlining
                return false;

            if (!overrideInline && instructions.Size > env.InlineThreshold)
                // Method too large
                return false;

            var methEnv =
                env.Global.Environment().AddAssembly(assemblyDef).AddType(typeDef).AddSelfTypeBoundArguments().
                    AddMethod(methodDef).AddSelfMethodBoundArguments();
            var cstmethod = CST.CSTMethod.Translate(methEnv, new JST.NameSupply(), null);
            var body = new Seq<CST.Statement>();
            var retres = cstmethod.Body.ToReturnResult(body);
            if (retres.Status != CST.ReturnStatus.One)
                // More than one return
                return false;

            return true;
        }