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); }