Example #1
0
        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);
        }
Example #2
0
        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);
            }
        }