示例#1
0
        public ILBlock Build(ILBlock method, Dictionary <string, ILVariable> locals, ErrorContext error)
        {
            if (method == null)
            {
                throw new ArgumentNullException("method");
            }
            if (error == null)
            {
                throw new ArgumentNullException("error");
            }
            if (locals == null)
            {
                throw new ArgumentNullException("locals");
            }
            this.error  = error;
            this.locals = locals;
            error.CheckDebugThenSave(method, "raw.txt", true);
            // Not sure I need this pass now
            // WE doo now, This converts popenv to either breaks or branchs.   This is needed
            // as if you return from a pushenv, a popenv break is called
            FixAllPushesAndPopenv(method.Body); // makes sure all pushes have no operands and are all expressions for latter matches


            Optimize.RemoveRedundantCode(method);

            foreach (var block in method.GetSelfAndChildrenRecursive <ILBlock>())
            {
                Optimize.SplitToBasicBlocks(block, true);
            }
            error.CheckDebugThenSave(method, "basic_blocks.txt");

            bool modified   = false;
            bool debug_once = true;

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

                    do     // Does all the internal things to a blocks for other passes to be easyer
                    {
                        modified  = false;
                        modified |= block.RunOptimization(MatchVariablePush);      // checks pushes for instance or indexs for vars
                        modified |= block.RunOptimization(SimpleAssignments);
                        modified |= block.RunOptimization(AssignValueTo);
                        modified |= block.RunOptimization(ComplexAssignments);    // basicly self increment, this SHOULDN'T cross block boundrys
                        modified |= block.RunOptimization(SimplifyBranches);      // Any resolved pushes are put into a branch argument
                        modified |= block.RunOptimization(CombineCall);           // Any resolved pushes are put into a branch argument
                        modified |= block.RunOptimization(CombineExpressions);
                        modified |= block.RunOptimization(FixTempReturnValues);
                    } while (modified);
                    if (Context.Debug)
                    {
                        if (debug_once)
                        {
                            error.CheckDebugThenSave(method, "basic_blocks_resolved.txt"); debug_once = false;
                        }
                    }



                    //  modified |= block.RunOptimization(new SimpleControlFlow(method,error).DetectSwitch);
                    //       modified |= block.RunOptimization(new SimpleControlFlow(method, error).DetectSwitchAndConvertToBranches);
                    modified |= block.RunOptimization(new SimpleControlFlow(method, error).DetectSwitch_GenerateSwitch);

                    modified |= block.RunOptimization(MultiDimenionArray);

                    modified |= block.RunOptimization(Optimize.SimplifyBoolTypes);
                    modified |= block.RunOptimization(Optimize.SimplifyLogicNot);

                    modified |= block.RunOptimization(PushEnviromentFix); // match all with's with expressions
                    modified |= block.RunOptimization(new SimpleControlFlow(method, error).SimplifyShortCircuit);
                    modified |= block.RunOptimization(new SimpleControlFlow(method, error).SimplifyTernaryOperator);
                    modified |= block.RunOptimization(new SimpleControlFlow(method, error).MatchRepeatStructure);



                    modified |= block.RunOptimization(new SimpleControlFlow(method, error).JoinBasicBlocks);
                    // somewhere, so bug, is leaving an empty block, I think because of switches
                    // It screws up the flatten block check for some reason
                    modified |= block.RunOptimization(new SimpleControlFlow(method, error).RemoveRedundentBlocks);
                    // want to run this at the end to fix return stuff
                } while (modified);
            }
            error.CheckDebugThenSave(method, "before_loops.txt");
            if (BeforeConditionsDebugSainityCheck(method))
            {
                return(null);                                           // sainity check, evething must be ready for this
            }
            foreach (ILBlock block in method.GetSelfAndChildrenRecursive <ILBlock>())
            {
                new LoopsAndConditions(error).FindLoops(block);
            }

            error.CheckDebugThenSave(method, "before_conditions.txt");

            foreach (ILBlock block in method.GetSelfAndChildrenRecursive <ILBlock>())
            {
                new LoopsAndConditions(error).FindConditions(block);
            }

            error.CheckDebugThenSave(method, "before_flatten.txt");
            FlattenBasicBlocks(method);
            error.CheckDebugThenSave(method, "before_gotos.txt");

            Optimize.RemoveRedundantCode(method);
            new GotoRemoval().RemoveGotos(method);

            error.CheckDebugThenSave(method, "before_if.txt");

            // This is cleaned up in ILSpy latter when its converted to another ast structure, but I clean it up here
            // cause I don't convert it and mabye not converting all bt's to bf's dosn't
            //   FixIfStatements(method);



            Optimize.RemoveRedundantCode(method);
            new GotoRemoval().RemoveGotos(method);

            error.CheckDebugThenSave(method, "final.txt");
            if (AfterLoopsAndConditions(method))
            {
                return(null);                                 // another sanity check
            }
            return(method);
        }