Exemplo n.º 1
0
        void RewriteBody(MethodDefinition method)
        {
            var reducer = new BodyReducer(method.Body, Context);

            //
            // Temporary inlines any calls which return contant expression
            //
            if (!TryInlineBodyDependencies(ref reducer))
            {
                return;
            }

            //
            // This is the main step which evaluates if inlined calls can
            // produce folded branches. When it finds them the unreachable
            // branch is replaced with nops.
            //
            if (!reducer.RewriteBody())
            {
                return;
            }

            Context.LogMessage(MessageContainer.CreateInfoMessage($"Reduced '{reducer.InstructionsReplaced}' instructions in conditional branches for [{method.DeclaringType.Module.Assembly.Name}] method {method.FullName}"));

            if (method.ReturnType.MetadataType == MetadataType.Void)
            {
                return;
            }

            //
            // Re-run the analyzer in case body change rewrote it to constant expression
            //
            var analyzer = new ConstantExpressionMethodAnalyzer(method, reducer.FoldedInstructions);

            if (analyzer.Analyze())
            {
                constExprMethods[method] = analyzer.Result;
            }
        }
Exemplo n.º 2
0
        bool TryInlineBodyDependencies(ref BodyReducer reducer)
        {
            bool        changed      = false;
            var         instructions = reducer.Body.Instructions;
            Instruction targetResult;

            for (int i = 0; i < instructions.Count; ++i)
            {
                var instr = instructions[i];
                switch (instr.OpCode.Code)
                {
                case Code.Call:
                    var target = (MethodReference)instr.Operand;
                    var md     = target.Resolve();
                    if (md == null)
                    {
                        break;
                    }

                    if (!md.IsStatic)
                    {
                        break;
                    }

                    if (!constExprMethods.TryGetValue(md, out targetResult))
                    {
                        break;
                    }

                    if (md.HasParameters)
                    {
                        break;
                    }

                    reducer.Rewrite(i, targetResult);
                    changed = true;
                    break;

                case Code.Ldsfld:
                    var ftarget = (FieldReference)instr.Operand;
                    var field   = ftarget.Resolve();
                    if (field == null)
                    {
                        break;
                    }

                    if (Context.Annotations.TryGetFieldUserValue(field, out object value))
                    {
                        targetResult = CodeRewriterStep.CreateConstantResultInstruction(field.FieldType, value);
                        if (targetResult == null)
                        {
                            break;
                        }
                        reducer.Rewrite(i, targetResult);
                        changed = true;
                    }
                    break;

                case Code.Sizeof:
                    //
                    // sizeof (IntPtr) and sizeof (UIntPtr) are just aliases for IntPtr.Size and UIntPtr.Size
                    // which are simple static properties commonly overwritten. Instead of forcing C# code style
                    // we handle both via static Size property
                    //
                    MethodDefinition sizeOfImpl = null;

                    var operand = (TypeReference)instr.Operand;
                    if (operand.MetadataType == MetadataType.UIntPtr)
                    {
                        sizeOfImpl = UIntPtrSize ?? (UIntPtrSize = FindSizeMethod(operand.Resolve()));
                    }

                    if (operand.MetadataType == MetadataType.IntPtr)
                    {
                        sizeOfImpl = IntPtrSize ?? (IntPtrSize = FindSizeMethod(operand.Resolve()));
                    }

                    if (sizeOfImpl != null && constExprMethods.TryGetValue(sizeOfImpl, out targetResult))
                    {
                        reducer.Rewrite(i, targetResult);
                        changed = true;
                    }

                    break;
                }
            }

            return(changed);
        }