Beispiel #1
0
        /// <summary>
        /// Convert the given method into optimized Ast format.
        /// </summary>
        internal protected static AstNode CreateOptimizedAst(AssemblyCompiler compiler, MethodSource source,
            bool generateSetNextInstructionCode, 
            StopAstConversion debugStop = StopAstConversion.None,
            AstOptimizationStep debugStopOptimizing = AstOptimizationStep.None
            )
        {
            // Build AST
            DecompilerContext context;
            AstBlock ast;
            if (source.IsDotNet)
            {
                context = new DecompilerContext(source.Method);
                var astBuilder = new IL2Ast.AstBuilder(source.ILMethod, true, context);
                var children = astBuilder.Build();
                ast = new AstBlock(children.Select(x => x.SourceLocation).FirstOrDefault(), children);
                if ((source.ILMethod.IsConstructor) && (source.Method.DeclaringType.Fields.Any(x => x.FieldType.IsEnum() || x.Name.EndsWith(NameConstants.Atomic.FieldUpdaterPostfix))))
                {
                    // Ensure all fields are initialized
                    AddFieldInitializationCode(compiler, source, ast);
                }
                if (source.Method.NeedsGenericInstanceTypeParameter && (source.Name == ".ctor"))
                {
                    // Add code to save the generic instance type parameter into the generic instance field.
                    AddGenericInstanceFieldInitializationCode(source, ast, compiler.Module.TypeSystem);
                }
            }
            else if (source.IsJava)
            {
                var astBuilder = new Java2Ast.AstBuilder(compiler.Module, source.JavaMethod, source.Method.DeclaringType, true);
                context = new DecompilerContext(source.Method);
                ast = astBuilder.Build();
            }
            else if (source.IsAst)
            {
                context = new DecompilerContext(source.Method);
                ast = source.Ast;
            }
            else
            {
                throw new NotSupportedException("Unknown source");
            }

            if (debugStop == StopAstConversion.AfterILConversion) return ast;

            // Optimize AST
            var astOptimizer = new AstOptimizer(context, ast);
            astOptimizer.Optimize(debugStopOptimizing);

            if (debugStop == StopAstConversion.AfterOptimizing) return ast;

            // Optimize AST towards the target
            TargetConverters.Convert(context, ast, source, compiler, debugStop);

            if(generateSetNextInstructionCode)
                SetNextInstructionGenerator.Convert(ast, source, compiler);

            // Return return
            return ast;
        }
 public StopOptimizeMenuCommandAttribute(AstOptimizationStep code)
 {
     Menu = "Dot42 DexInput/_Optimization";
     MenuCategory = "Stop";
     Header = code == AstOptimizationStep.None
         ? "Full Pocessing" : "Stop before " + code.ToString().Replace("Before", "");
     MenuOrder = (code == AstOptimizationStep.None)? -1 : (int) code;
     StopCode = code;
 }
 public StopOptimizeMenuCommandAttribute(AstOptimizationStep code)
 {
     Menu         = "Dot42 DexInput/_Optimization";
     MenuCategory = "Stop";
     Header       = code == AstOptimizationStep.None
         ? "Full Pocessing" : "Stop before " + code.ToString().Replace("Before", "");
     MenuOrder = (code == AstOptimizationStep.None)? -1 : (int)code;
     StopCode  = code;
 }
 private static void UpdateCheckedState(AstOptimizationStep stopCode)
 {
     foreach (MenuItem mainItem in MainWindow.Instance.GetMainMenuItems())
     foreach (object itemObj in mainItem.Items)
     {
         var item = itemObj as MenuItem;
         if(item == null || !(item.Command is StopOptimizeMenuCommand))
             continue;
         item.IsCheckable = true;
         var attr = GetAttribute(item.Command);
         item.IsChecked = attr.StopCode == stopCode;
     }
 }
 private static void UpdateCheckedState(AstOptimizationStep stopCode)
 {
     foreach (MenuItem mainItem in MainWindow.Instance.GetMainMenuItems())
     {
         foreach (object itemObj in mainItem.Items)
         {
             var item = itemObj as MenuItem;
             if (item == null || !(item.Command is StopOptimizeMenuCommand))
             {
                 continue;
             }
             item.IsCheckable = true;
             var attr = GetAttribute(item.Command);
             item.IsChecked = attr.StopCode == stopCode;
         }
     }
 }
Beispiel #6
0
        public void Optimize(AstOptimizationStep abortBeforeStep = AstOptimizationStep.None)
        {
            if (abortBeforeStep == AstOptimizationStep.RemoveRedundantCode)
            {
                return;
            }
            RemoveRedundantCode(method);

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

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

            inlining1.InlineAllVariables();

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

            if (abortBeforeStep == AstOptimizationStep.SplitToMovableBlocks)
            {
                return;
            }
            foreach (var block in method.GetSelfAndChildrenRecursive <AstBlock>())
            {
                SplitToBasicBlocks(block);
            }

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

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

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

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

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

                    if (abortBeforeStep == AstOptimizationStep.TransformDecimalCtorToConstant)
                    {
                        return;
                    }
                    modified |= block.RunOptimization(TransformDecimalCtorToConstant);
                    modified |= block.RunOptimization(SimplifyLdcI4ConvI8);

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

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

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

                    if (abortBeforeStep == AstOptimizationStep.MakeAssignmentExpression)
                    {
                        return;
                    }
                    modified |= block.RunOptimization(MakeAssignmentExpression);
#if COMPOUNDASSIGNMENT
                    modified |= block.RunOptimization(MakeCompoundAssignments);
#endif

#if POSTINCREMENT
                    if (abortBeforeStep == AstOptimizationStep.IntroducePostIncrement)
                    {
                        return;
                    }
                    modified |= block.RunOptimization(IntroducePostIncrement);
#endif

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

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

            /*if (abortBeforeStep == AstOptimizationStep.FindLoops) return;
             * foreach (AstBlock block in method.GetSelfAndChildrenRecursive<AstBlock>())
             * {
             *  new LoopsAndConditions(context).FindLoops(block);
             * }
             */

            /*if (abortBeforeStep == AstOptimizationStep.FindConditions) return;
             * foreach (AstBlock block in method.GetSelfAndChildrenRecursive<AstBlock>())
             * {
             *  new LoopsAndConditions(context).FindConditions(block);
             * }*/

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

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

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

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

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

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

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

            if (abortBeforeStep == AstOptimizationStep.RecombineVariables)
            {
                return;
            }
            //RecombineVariables(method); // We do not recombine variables because the RL code depends on it.

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

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

            // ReportUnassignedILRanges(method);
        }
        /// <summary>
        /// Convert the given method into optimized Ast format.
        /// </summary>
        internal protected static AstNode CreateOptimizedAst(AssemblyCompiler compiler, MethodSource source,
                                                             bool generateSetNextInstructionCode,
                                                             StopAstConversion debugStop             = StopAstConversion.None,
                                                             AstOptimizationStep debugStopOptimizing = AstOptimizationStep.None
                                                             )
        {
            // Build AST
            DecompilerContext context;
            AstBlock          ast;

            if (source.IsDotNet)
            {
                context = new DecompilerContext(source.Method);
                var astBuilder = new IL2Ast.AstBuilder(source.ILMethod, true, context);
                var children   = astBuilder.Build();
                ast = new AstBlock(children.Select(x => x.SourceLocation).FirstOrDefault(), children);
                if ((source.ILMethod.IsConstructor) && (source.Method.DeclaringType.Fields.Any(x => x.FieldType.IsEnum() || x.Name.EndsWith(NameConstants.Atomic.FieldUpdaterPostfix))))
                {
                    // Ensure all fields are initialized
                    AddFieldInitializationCode(compiler, source, ast);
                }
                if (source.Method.NeedsGenericInstanceTypeParameter && (source.Name == ".ctor"))
                {
                    // Add code to save the generic instance type parameter into the generic instance field.
                    AddGenericInstanceFieldInitializationCode(source, ast, compiler.Module.TypeSystem);
                }
            }
            else if (source.IsJava)
            {
                var astBuilder = new Java2Ast.AstBuilder(compiler.Module, source.JavaMethod, source.Method.DeclaringType, true);
                context = new DecompilerContext(source.Method);
                ast     = astBuilder.Build();
            }
            else if (source.IsAst)
            {
                context = new DecompilerContext(source.Method);
                ast     = source.Ast;
            }
            else
            {
                throw new NotSupportedException("Unknown source");
            }

            if (debugStop == StopAstConversion.AfterILConversion)
            {
                return(ast);
            }

            // Optimize AST
            var astOptimizer = new AstOptimizer(context, ast);

            astOptimizer.Optimize(debugStopOptimizing);

            if (debugStop == StopAstConversion.AfterOptimizing)
            {
                return(ast);
            }

            // Optimize AST towards the target
            TargetConverters.Convert(context, ast, source, compiler, debugStop);

            if (generateSetNextInstructionCode)
            {
                SetNextInstructionGenerator.Convert(ast, source, compiler);
            }

            // Return return
            return(ast);
        }