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(); }
public static void RunStep2(DecompilerContext context, ILBlock method, List<ILExpression> listExpr, List<ILBlock> listBlock, Dictionary<ILLabel, int> labelRefCount, List<ILNode> list_ILNode, Func<ILBlock, ILInlining> getILInlining) { if (context.CurrentMethodIsAsync) { Step2(method.Body); ILAstOptimizer.RemoveRedundantCode(context, method, listExpr, listBlock, labelRefCount); // Repeat the inlining/copy propagation optimization because the conversion of field access // to local variables can open up additional inlining possibilities. ILInlining inlining = getILInlining(method); inlining.InlineAllVariables(); inlining.CopyPropagation(list_ILNode); } }
public static void RunStep2(DecompilerContext context, ILBlock method) { if (context.CurrentMethodIsAsync) { Step2(method.Body); ILAstOptimizer.RemoveRedundantCode(method); // 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(); } }
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(); }
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); 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.TransformDecimalCtorToConstant) { return; } modified |= block.RunOptimization(TransformDecimalCtorToConstant); modified |= block.RunOptimization(SimplifyLdcI4ConvI8); if (abortBeforeStep == ILAstOptimizationStep.SimplifyLdObjAndStObj) { return; } modified |= block.RunOptimization(SimplifyLdObjAndStObj); if (abortBeforeStep == ILAstOptimizationStep.TransformArrayInitializers) { return; } modified |= block.RunOptimization(TransformArrayInitializers); if (abortBeforeStep == ILAstOptimizationStep.TransformObjectInitializers) { return; } modified |= block.RunOptimization(TransformObjectInitializers); if (abortBeforeStep == ILAstOptimizationStep.MakeAssignmentExpression) { return; } modified |= block.RunOptimization(MakeAssignmentExpression); modified |= block.RunOptimization(MakeCompoundAssignments); if (abortBeforeStep == ILAstOptimizationStep.IntroducePostIncrement) { return; } modified |= block.RunOptimization(IntroducePostIncrement); 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.RemoveRedundantCode2) { return; } RemoveRedundantCode(method); if (abortBeforeStep == ILAstOptimizationStep.GotoRemoval) { return; } new GotoRemoval().RemoveGotos(method); if (abortBeforeStep == ILAstOptimizationStep.DuplicateReturns) { return; } DuplicateReturnStatements(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; } 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); }