/// <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; } } }
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); }