예제 #1
0
        bool Scan()
        {
            LogDebug(1, $"SCAN: {Method}");

            BasicBlock bb = null;

            if (DebugLevel > 0)
            {
                Context.Debug();
            }

            if (!BlockList.Initialize())
            {
                return(false);
            }

            for (int i = 0; i < Method.Body.Instructions.Count; i++)
            {
                var instruction = Method.Body.Instructions [i];

                if (BlockList.TryGetBlock(instruction, out var newBB))
                {
                    if (bb != null && bb.BranchType != BranchType.None)
                    {
                        throw DebugHelpers.AssertFail(Method, bb, $"Found known basic block with unexpected branch type `{bb.BranchType}`");
                    }
                    LogDebug(2, $"  KNOWN BB: {newBB}");
                    bb = newBB;
                }
                else if (bb == null)
                {
                    bb = BlockList.NewBlock(instruction);
                    LogDebug(2, $"  NEW BB: {bb}");
                }
                else
                {
                    bb.AddInstruction(instruction);
                }

                var type = CecilHelper.GetBranchType(instruction);
                LogDebug(2, $"    {type}: {CecilHelper.Format (instruction)}");

                if (instruction.OpCode.OperandType == OperandType.InlineMethod)
                {
                    if (LinkerConditional.Scan(this, ref bb, ref i, instruction))
                    {
                        FoundConditionals = true;
                    }
                    continue;
                }

                switch (type)
                {
                case BranchType.None:
                    break;

                case BranchType.Conditional:
                case BranchType.False:
                case BranchType.True:
                case BranchType.Jump:
                    BlockList.AddJumpOrigin(bb, instruction, (Instruction)instruction.Operand);
                    bb = null;
                    break;

                case BranchType.Exit:
                case BranchType.Return:
                case BranchType.EndFinally:
                    bb = null;
                    break;

                case BranchType.Switch:
                    foreach (var label in (Instruction [])bb.LastInstruction.Operand)
                    {
                        BlockList.AddJumpOrigin(bb, instruction, label);
                    }
                    bb = null;
                    break;

                default:
                    throw new OptimizerAssertionException();
                }
            }

            BlockList.ComputeOffsets();

            DumpBlocks();

            if (Context.Options.AnalyzeAll || FoundConditionals || DebugLevel > 3)
            {
                EliminateDeadBlocks();
                DumpBlocks();
                return(true);
            }

            return(true);
        }