// tools/hako_check/rules/rule_dead_blocks.hako — HC020: Unreachable Basic Block Detection // Block-level dead code analyzer using MIR CFG information. // Phase 154: MIR CFG integration for fine-grained unreachable code detection. static box DeadBlockAnalyzerBox { // Main entry point for unreachable block analysis // Input: ir (Analysis IR with CFG), path (file path), out (diagnostics array) // Returns: void (like other rules) method apply_ir(ir, path, out) { if ir == null { return } if out == null { return } // Phase 154: Requires CFG information from MIR local cfg = ir.get("cfg") if cfg == null { // CFG info not available - skip analysis return } local functions = cfg.get("functions") if functions == null || functions.size() == 0 { return } // Analyze each function's blocks local i = 0 while i < functions.size() { me._analyze_function_blocks(functions.get(i), path, out) i = i + 1 } return } // Analyze blocks within a single function _analyze_function_blocks(func, path, out) { if func == null { return } local func_name = func.get("name") local blocks = func.get("blocks") if blocks == null || blocks.size() == 0 { return } // Scan for unreachable blocks local bi = 0 while bi < blocks.size() { local block = blocks.get(bi) if block == null { bi = bi + 1; continue } local block_id = block.get("id") local reachable = block.get("reachable") // Report unreachable blocks (HC020) if reachable == 0 { local terminator = block.get("terminator") local reason = me._infer_unreachable_reason(terminator) local msg = "[HC020] Unreachable basic block: fn=" + func_name + " bb=" + me._itoa(block_id) if reason != null && reason != "" { msg = msg + " (" + reason + ")" } out.push(msg + " :: " + path) } bi = bi + 1 } return } // Infer reason for unreachability based on terminator type _infer_unreachable_reason(terminator) { if terminator == null { return "no terminator" } // Common patterns if terminator == "Return" { return "after early return" } if terminator == "Jump" { return "unreachable branch" } if terminator == "Branch" { return "dead conditional" } return "" } // Helper: integer to string _itoa(n) { local v = 0 + n if v == 0 { return "0" } local out = "" local digits = "0123456789" local tmp = "" while v > 0 { local d = v % 10 tmp = digits.substring(d, d+1) + tmp v = v / 10 } out = tmp return out } } static box RuleDeadBlocksMain { method main(args) { return 0 } }