public ILBlock Build(SortedList <int, Instruction> code, bool optimize, GMContext context) // List<string> StringList, List<string> InstanceList = null) //DecompilerContext context) { if (code.Count == 0) { return(new ILBlock()); } this.context = context; _method = code; this.optimize = optimize; List <ILNode> ast = BuildPreAst(); ILBlock method = new ILBlock(); method.Body = ast; if (context.Debug) { method.DebugSave("raw_body.txt"); } betteribttest.Dissasembler.Optimize.RemoveRedundantCode(method); foreach (var block in method.GetSelfAndChildrenRecursive <ILBlock>()) { Optimize.SplitToBasicBlocks(block); } if (context.Debug) { method.DebugSave("basic_blocks.txt"); } new BuildFullAst(method, context).ProcessAllExpressions(method); if (context.Debug) { method.DebugSave("basic_blocks2.txt"); } foreach (ILBlock block in method.GetSelfAndChildrenRecursive <ILBlock>()) { bool modified; do { modified = false; modified |= block.RunOptimization(new SimpleControlFlow(method, context).PushEnviromentFix); modified |= block.RunOptimization(new SimpleControlFlow(method, context).SimplifyShortCircuit); modified |= block.RunOptimization(new SimpleControlFlow(method, context).SimplifyTernaryOperator); modified |= block.RunOptimization(new SimpleControlFlow(method, context).JoinBasicBlocks); modified |= block.RunOptimization(Optimize.SimplifyLogicNot); } while (modified); } if (context.Debug) { method.DebugSave("before_loop.txt"); } foreach (ILBlock block in method.GetSelfAndChildrenRecursive <ILBlock>()) { new LoopsAndConditions().FindLoops(block); } if (context.Debug) { method.DebugSave("before_conditions.txt"); } foreach (ILBlock block in method.GetSelfAndChildrenRecursive <ILBlock>()) { new LoopsAndConditions().FindConditions(block); } FlattenBasicBlocks(method); if (context.Debug) { method.DebugSave("before_gotos.txt"); } Optimize.RemoveRedundantCode(method); new GotoRemoval().RemoveGotos(method); Optimize.RemoveRedundantCode(method); new GotoRemoval().RemoveGotos(method); GotoRemoval.RemoveRedundantCode(method); new GotoRemoval().RemoveGotos(method); if (context.Debug) { method.DebugSave("final.cpp"); } return(method); }
public static void RemoveRedundantCode(ILBlock method) { // Remove dead lables and nops and any popzs left HashSet <ILLabel> liveLabels = new HashSet <ILLabel>(method.GetSelfAndChildrenRecursive <ILExpression>(e => e.IsBranch()).SelectMany(e => e.GetBranchTargets())); foreach (ILBlock block in method.GetSelfAndChildrenRecursive <ILBlock>()) { block.Body = block.Body.Where(n => !n.Match(GMCode.BadOp) && !n.Match(GMCode.Popz) && !(n is ILLabel && !liveLabels.Contains((ILLabel)n))).ToList(); } // Remove redundant continue foreach (ILWhileLoop loop in method.GetSelfAndChildrenRecursive <ILWhileLoop>()) { var body = loop.BodyBlock.Body; if (body.Count > 0 && body.Last().Match(GMCode.LoopContinue)) { body.RemoveAt(body.Count - 1); } } // Remove redundant continue foreach (ILWithStatement with in method.GetSelfAndChildrenRecursive <ILWithStatement>()) { var body = with.Body.Body; if (body.Count > 0 && body.Last().Match(GMCode.LoopContinue)) { body.RemoveAt(body.Count - 1); } } // Remove redundant break at the end of case // Remove redundant case blocks altogether foreach (ILSwitch ilSwitch in method.GetSelfAndChildrenRecursive <ILSwitch>()) { foreach (ILBlock ilCase in ilSwitch.CaseBlocks) { Debug.Assert(ilCase.EntryGoto == null); int count = ilCase.Body.Count; if (count >= 2) { if (ilCase.Body[count - 2].IsUnconditionalControlFlow() && ilCase.Body[count - 1].Match(GMCode.LoopOrSwitchBreak)) { ilCase.Body.RemoveAt(count - 1); } } } // fix case block var defaultCase = ilSwitch.CaseBlocks.SingleOrDefault(cb => cb.Values == null); // If there is no default block, remove empty case blocks if (defaultCase == null || (defaultCase.Body.Count == 1 && defaultCase.Body.Single().Match(GMCode.LoopOrSwitchBreak))) { ilSwitch.CaseBlocks.RemoveAll(b => b.Body.Count == 1 && b.Body.Single().Match(GMCode.LoopOrSwitchBreak)); } } // Remove redundant return at the end of method if (method.Body.Count > 0 && (method.Body.Last().Match(GMCode.Ret) || method.Body.Last().Match(GMCode.Exit)) && ((ILExpression)method.Body.Last()).Arguments.Count == 0) { method.Body.RemoveAt(method.Body.Count - 1); } // Remove unreachable return statements bool modified = false; foreach (ILBlock block in method.GetSelfAndChildrenRecursive <ILBlock>()) { for (int i = 0; i < block.Body.Count - 1;) { if (block.Body[i].IsUnconditionalControlFlow() && (block.Body[i + 1].Match(GMCode.Ret) || block.Body[i + 1].Match(GMCode.Exit))) { modified = true; block.Body.RemoveAt(i + 1); } else { i++; } } } // Remove empty falseBlocks foreach (ILCondition condition in method.GetSelfAndChildrenRecursive <ILCondition>().Where(x => x.FalseBlock != null && x.FalseBlock.Body.Count == 0)) { condition.FalseBlock = null; modified = true; } if (modified) { // More removals might be possible new GotoRemoval().RemoveGotos(method); } }