コード例 #1
0
        public static void Run(DecompilerContext context, ILBlock method)
        {
            if (!context.Settings.YieldReturn)
            {
                return;                 // abort if enumerator decompilation is disabled
            }
            var yrd = new YieldReturnDecompiler();

            yrd.context = context;
            if (!yrd.MatchEnumeratorCreationPattern(method))
            {
                return;
            }
            yrd.enumeratorType = yrd.enumeratorCtor.DeclaringType;
                        #if DEBUG
            if (Debugger.IsAttached)
            {
                yrd.Run();
            }
            else
            {
                                #endif
            try {
                yrd.Run();
            } catch (SymbolicAnalysisFailedException) {
                return;
            }
                                #if DEBUG
        }
                        #endif
            method.Body.Clear();
            method.EntryGoto = null;
            method.Body.AddRange(yrd.newBody);

            // Repeat the inlining/copy propagation optimization because the conversion of field access
            // to local variables can open up additional inlining possibilities.
            ILInlining inlining = new ILInlining(method);
            inlining.InlineAllVariables();
            inlining.CopyPropagation();
        }
コード例 #2
0
ファイル: ILAstOptimizer.cs プロジェクト: ropean/Usable
        public void Optimize(DecompilerContext context, ILBlock method, ILAstOptimizationStep abortBeforeStep = ILAstOptimizationStep.None)
        {
            this.context    = context;
            this.typeSystem = context.CurrentMethod.Module.TypeSystem;
            this.method     = method;

            if (abortBeforeStep == ILAstOptimizationStep.RemoveRedundantCode)
            {
                return;
            }
            RemoveRedundantCode(method);

            if (abortBeforeStep == ILAstOptimizationStep.ReduceBranchInstructionSet)
            {
                return;
            }
            foreach (ILBlock block in method.GetSelfAndChildrenRecursive <ILBlock>())
            {
                ReduceBranchInstructionSet(block);
            }
            // ReduceBranchInstructionSet runs before inlining because the non-aggressive inlining heuristic
            // looks at which type of instruction consumes the inlined variable.

            if (abortBeforeStep == ILAstOptimizationStep.InlineVariables)
            {
                return;
            }
            // Works better after simple goto removal because of the following debug pattern: stloc X; br Next; Next:; ldloc X
            ILInlining inlining1 = new ILInlining(method);

            inlining1.InlineAllVariables();

            if (abortBeforeStep == ILAstOptimizationStep.CopyPropagation)
            {
                return;
            }
            inlining1.CopyPropagation();

            if (abortBeforeStep == ILAstOptimizationStep.YieldReturn)
            {
                return;
            }
            YieldReturnDecompiler.Run(context, method);
            AsyncDecompiler.RunStep1(context, method);

            if (abortBeforeStep == ILAstOptimizationStep.AsyncAwait)
            {
                return;
            }
            AsyncDecompiler.RunStep2(context, method);

            if (abortBeforeStep == ILAstOptimizationStep.PropertyAccessInstructions)
            {
                return;
            }
            IntroducePropertyAccessInstructions(method);

            if (abortBeforeStep == ILAstOptimizationStep.SplitToMovableBlocks)
            {
                return;
            }
            foreach (ILBlock block in method.GetSelfAndChildrenRecursive <ILBlock>())
            {
                SplitToBasicBlocks(block);
            }

            if (abortBeforeStep == ILAstOptimizationStep.TypeInference)
            {
                return;
            }
            // Types are needed for the ternary operator optimization
            TypeAnalysis.Run(context, method);

            foreach (ILBlock block in method.GetSelfAndChildrenRecursive <ILBlock>())
            {
                bool modified;
                do
                {
                    modified = false;

                    if (abortBeforeStep == ILAstOptimizationStep.SimplifyShortCircuit)
                    {
                        return;
                    }
                    modified |= block.RunOptimization(new SimpleControlFlow(context, method).SimplifyShortCircuit);

                    if (abortBeforeStep == ILAstOptimizationStep.SimplifyTernaryOperator)
                    {
                        return;
                    }
                    modified |= block.RunOptimization(new SimpleControlFlow(context, method).SimplifyTernaryOperator);

                    if (abortBeforeStep == ILAstOptimizationStep.SimplifyNullCoalescing)
                    {
                        return;
                    }
                    modified |= block.RunOptimization(new SimpleControlFlow(context, method).SimplifyNullCoalescing);

                    if (abortBeforeStep == ILAstOptimizationStep.JoinBasicBlocks)
                    {
                        return;
                    }
                    modified |= block.RunOptimization(new SimpleControlFlow(context, method).JoinBasicBlocks);

                    if (abortBeforeStep == ILAstOptimizationStep.SimplifyLogicNot)
                    {
                        return;
                    }
                    modified |= block.RunOptimization(SimplifyLogicNot);

                    if (abortBeforeStep == ILAstOptimizationStep.SimplifyShiftOperators)
                    {
                        return;
                    }
                    modified |= block.RunOptimization(SimplifyShiftOperators);

                    if (abortBeforeStep == ILAstOptimizationStep.TypeConversionSimplifications)
                    {
                        return;
                    }
                    modified |= block.RunOptimization(TypeConversionSimplifications);

                    if (abortBeforeStep == ILAstOptimizationStep.SimplifyLdObjAndStObj)
                    {
                        return;
                    }
                    modified |= block.RunOptimization(SimplifyLdObjAndStObj);

                    if (abortBeforeStep == ILAstOptimizationStep.SimplifyCustomShortCircuit)
                    {
                        return;
                    }
                    modified |= block.RunOptimization(new SimpleControlFlow(context, method).SimplifyCustomShortCircuit);

                    if (abortBeforeStep == ILAstOptimizationStep.SimplifyLiftedOperators)
                    {
                        return;
                    }
                    modified |= block.RunOptimization(SimplifyLiftedOperators);

                    if (abortBeforeStep == ILAstOptimizationStep.TransformArrayInitializers)
                    {
                        return;
                    }
                    modified |= block.RunOptimization(TransformArrayInitializers);

                    if (abortBeforeStep == ILAstOptimizationStep.TransformMultidimensionalArrayInitializers)
                    {
                        return;
                    }
                    modified |= block.RunOptimization(TransformMultidimensionalArrayInitializers);

                    if (abortBeforeStep == ILAstOptimizationStep.TransformObjectInitializers)
                    {
                        return;
                    }
                    modified |= block.RunOptimization(TransformObjectInitializers);

                    if (abortBeforeStep == ILAstOptimizationStep.MakeAssignmentExpression)
                    {
                        return;
                    }
                    if (context.Settings.MakeAssignmentExpressions)
                    {
                        modified |= block.RunOptimization(MakeAssignmentExpression);
                    }
                    modified |= block.RunOptimization(MakeCompoundAssignments);

                    if (abortBeforeStep == ILAstOptimizationStep.IntroducePostIncrement)
                    {
                        return;
                    }
                    if (context.Settings.IntroduceIncrementAndDecrement)
                    {
                        modified |= block.RunOptimization(IntroducePostIncrement);
                    }

                    if (abortBeforeStep == ILAstOptimizationStep.InlineExpressionTreeParameterDeclarations)
                    {
                        return;
                    }
                    if (context.Settings.ExpressionTrees)
                    {
                        modified |= block.RunOptimization(InlineExpressionTreeParameterDeclarations);
                    }

                    if (abortBeforeStep == ILAstOptimizationStep.InlineVariables2)
                    {
                        return;
                    }
                    modified |= new ILInlining(method).InlineAllInBlock(block);
                    new ILInlining(method).CopyPropagation();
                } while(modified);
            }

            if (abortBeforeStep == ILAstOptimizationStep.FindLoops)
            {
                return;
            }
            foreach (ILBlock block in method.GetSelfAndChildrenRecursive <ILBlock>())
            {
                new LoopsAndConditions(context).FindLoops(block);
            }

            if (abortBeforeStep == ILAstOptimizationStep.FindConditions)
            {
                return;
            }
            foreach (ILBlock block in method.GetSelfAndChildrenRecursive <ILBlock>())
            {
                new LoopsAndConditions(context).FindConditions(block);
            }

            if (abortBeforeStep == ILAstOptimizationStep.FlattenNestedMovableBlocks)
            {
                return;
            }
            FlattenBasicBlocks(method);

            if (abortBeforeStep == ILAstOptimizationStep.RemoveEndFinally)
            {
                return;
            }
            RemoveEndFinally(method);

            if (abortBeforeStep == ILAstOptimizationStep.RemoveRedundantCode2)
            {
                return;
            }
            RemoveRedundantCode(method);

            if (abortBeforeStep == ILAstOptimizationStep.GotoRemoval)
            {
                return;
            }
            new GotoRemoval().RemoveGotos(method);

            if (abortBeforeStep == ILAstOptimizationStep.DuplicateReturns)
            {
                return;
            }
            DuplicateReturnStatements(method);

            if (abortBeforeStep == ILAstOptimizationStep.GotoRemoval2)
            {
                return;
            }
            new GotoRemoval().RemoveGotos(method);

            if (abortBeforeStep == ILAstOptimizationStep.ReduceIfNesting)
            {
                return;
            }
            ReduceIfNesting(method);

            if (abortBeforeStep == ILAstOptimizationStep.InlineVariables3)
            {
                return;
            }
            // The 2nd inlining pass is necessary because DuplicateReturns and the introduction of ternary operators
            // open up additional inlining possibilities.
            new ILInlining(method).InlineAllVariables();

            if (abortBeforeStep == ILAstOptimizationStep.CachedDelegateInitialization)
            {
                return;
            }
            if (context.Settings.AnonymousMethods)
            {
                foreach (ILBlock block in method.GetSelfAndChildrenRecursive <ILBlock>())
                {
                    for (int i = 0; i < block.Body.Count; i++)
                    {
                        // TODO: Move before loops
                        CachedDelegateInitializationWithField(block, ref i);
                        CachedDelegateInitializationWithLocal(block, ref i);
                    }
                }
            }

            if (abortBeforeStep == ILAstOptimizationStep.IntroduceFixedStatements)
            {
                return;
            }
            // we need post-order traversal, not pre-order, for "fixed" to work correctly
            foreach (ILBlock block in TreeTraversal.PostOrder <ILNode>(method, n => n.GetChildren()).OfType <ILBlock>())
            {
                for (int i = block.Body.Count - 1; i >= 0; i--)
                {
                    // TODO: Move before loops
                    if (i < block.Body.Count)
                    {
                        IntroduceFixedStatements(block.Body, i);
                    }
                }
            }

            if (abortBeforeStep == ILAstOptimizationStep.RecombineVariables)
            {
                return;
            }
            RecombineVariables(method);

            if (abortBeforeStep == ILAstOptimizationStep.TypeInference2)
            {
                return;
            }
            TypeAnalysis.Reset(method);
            TypeAnalysis.Run(context, method);

            if (abortBeforeStep == ILAstOptimizationStep.RemoveRedundantCode3)
            {
                return;
            }
            GotoRemoval.RemoveRedundantCode(method);

            // ReportUnassignedILRanges(method);
        }
コード例 #3
0
        public static void Run(DecompilerContext context, ILBlock method)
        {
            if (!context.Settings.YieldReturn)
                return; // abort if enumerator decompilation is disabled
            var yrd = new YieldReturnDecompiler();
            yrd.context = context;
            if (!yrd.MatchEnumeratorCreationPattern(method))
                return;
            yrd.enumeratorType = yrd.enumeratorCtor.DeclaringType;
            #if DEBUG
            if (Debugger.IsAttached) {
                yrd.Run();
            } else {
                #endif
                try {
                    yrd.Run();
                } catch (SymbolicAnalysisFailedException) {
                    return;
                }
                #if DEBUG
            }
            #endif
            method.Body.Clear();
            method.EntryGoto = null;
            method.Body.AddRange(yrd.newBody);

            // Repeat the inlining/copy propagation optimization because the conversion of field access
            // to local variables can open up additional inlining possibilities.
            ILInlining inlining = new ILInlining(method);
            inlining.InlineAllVariables();
            inlining.CopyPropagation();
        }