Files
hakorune/docs/archive/phases/phase-150-167/phase154_mir_cfg_deadblocks.md

390 lines
9.7 KiB
Markdown
Raw Normal View History

feat(hako_check): Phase 154 MIR CFG integration & HC020 dead block detection Implements block-level unreachable code detection using MIR CFG information. Complements Phase 153's method-level HC019 with fine-grained analysis. Core Infrastructure (Complete): - CFG Extractor: Extract block reachability from MirModule - DeadBlockAnalyzerBox: HC020 rule for unreachable blocks - CLI Integration: --dead-blocks flag and rule execution - Test Cases: 4 comprehensive patterns (early return, constant false, infinite loop, break) - Smoke Test: Validation script for all test cases Implementation Details: - src/mir/cfg_extractor.rs: New module for CFG→JSON extraction - tools/hako_check/rules/rule_dead_blocks.hako: HC020 analyzer box - tools/hako_check/cli.hako: Added --dead-blocks flag and HC020 integration - apps/tests/hako_check/test_dead_blocks_*.hako: 4 test cases Architecture: - Follows Phase 153 boxed modular pattern (DeadCodeAnalyzerBox) - Optional CFG field in Analysis IR (backward compatible) - Uses MIR's built-in reachability computation - Gracefully skips if CFG unavailable Known Limitation: - CFG data bridge pending (Phase 155): analysis_consumer.hako needs MIR access - Current: DeadBlockAnalyzerBox implemented, but CFG not yet in Analysis IR - Estimated 2-3 hours to complete bridge in Phase 155 Test Coverage: - Unit tests: cfg_extractor (simple CFG, unreachable blocks) - Integration tests: 4 test cases ready (will activate with bridge) - Smoke test: tools/hako_check_deadblocks_smoke.sh Documentation: - phase154_mir_cfg_inventory.md: CFG structure investigation - phase154_implementation_summary.md: Complete implementation guide - hako_check_design.md: HC020 rule documentation Next Phase 155: - Implement CFG data bridge (extract_mir_cfg builtin) - Update analysis_consumer.hako to call bridge - Activate HC020 end-to-end testing 🤖 Generated with Claude Code (https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 15:00:45 +09:00
# Phase 154: MIR CFG 統合 & ブロックレベル unreachable 検出
## 0. ゴール
**hako_check に MIR CFG 情報を取り込み、「到達不能な basic block」を検出する HC020 ルールを追加する。**
目的:
- Phase 153 で復活した dead code 検出メソッド・Box 単位)を、ブロック単位まで細粒度化
- JoinIR/MIR の CFG 情報を hako_check の Analysis IR に統合
- 「unreachable basic block」を検出し、コード品質向上に寄与
---
## 1. Scope / Non-scope
### ✅ やること
1. **MIR/CFG 情報のインベントリ**
- 現在の MIR JSON v0 に含まれる CFG 情報blocks, terminatorsを確認
- hako_check の Analysis IR に追加すべきフィールドを特定
2. **DeadBlockAnalyzerBox の設計(箱化モジュール化)**
- Phase 153 の DeadCodeAnalyzerBox パターンを踏襲
- 入力: Analysis IRCFG 情報付き)
- 出力: 未到達ブロックのリスト
3. **hako_check パイプラインへの統合設計**
- Analysis IR 生成時に CFG 情報を含める方法を決定
- HC020 ルールの位置付けHC019 の後に実行)
4. **テストケース設計(ブロックレベル)**
- 到達不能な if/else 分岐
- 早期 return 後のコード
- 常に false のループ条件
5. **実装 & テスト**
- DeadBlockAnalyzerBox 実装
- HC020 ルール実装
- スモークテスト作成
6. **ドキュメント & CURRENT_TASK 更新**
### ❌ やらないこと
- JoinIR/MIR の意味論を変えない(解析は「読むだけ」)
- 新しい Stage-3 構文を追加しない
- 環境変数を増やさないCLI フラグ `--dead-blocks` のみ)
---
## 2. Task 1: MIR/CFG 情報のインベントリ
### 対象ファイル
- `src/mir/join_ir/json.rs` - JoinIR JSON シリアライズ
- `src/mir/join_ir_runner.rs` - JoinIR 実行
- `src/mir/` - MIR 構造定義
- `tools/hako_check/analysis_ir.hako` - 現在の Analysis IR 定義
### やること
1. **MIR JSON v0 の CFG 情報を確認**
- blocks 配列の構造
- terminator の種類Jump, Branch, Return
- predecessors / successors の有無
2. **Analysis IR に追加すべきフィールドを特定**
- `blocks: Array<BlockInfo>` ?
- `cfg_edges: Array<Edge>` ?
- `entry_block: BlockId` ?
3. **JoinIR Strict モードでの動作確認**
- `NYASH_JOINIR_STRICT=1` で MIR が正しく生成されているか
- Phase 150 の代表ケースで CFG 情報が取れるか
### 成果物
- CFG 情報インベントリ結果の記録
---
## 3. Task 2: DeadBlockAnalyzerBox の設計(箱化モジュール化)
### 目的
Phase 153 の DeadCodeAnalyzerBox パターンを踏襲し、ブロックレベル解析を箱化
### 方針
- エントリブロックからの到達可能性を DFS/BFS で計算
- 到達しなかったブロックを列挙
- 各ブロックがどの関数に属するかも記録
### 箱単位の設計
**DeadBlockAnalyzerBox** として:
- 入力: Analysis IRCFG 情報付き)
- 出力: 「未到達ブロック」のリスト
### API シグネチャ案
```hako
static box DeadBlockAnalyzerBox {
method apply_ir(ir, path, out) {
// CFG 情報を取得
local blocks = ir.get("blocks")
local edges = ir.get("cfg_edges")
local entry = ir.get("entry_block")
// 到達可能性解析
local reachable = me._compute_reachability(entry, edges)
// 未到達ブロックを検出
me._report_unreachable_blocks(blocks, reachable, path, out)
}
method _compute_reachability(entry, edges) {
// DFS/BFS で到達可能なブロックを収集
// return: Set<BlockId>
}
method _report_unreachable_blocks(blocks, reachable, path, out) {
// 到達不能なブロックを HC020 として報告
}
}
```
### 出力フォーマット
```
[HC020] Unreachable basic block: fn=Main.main bb=10 (after early return)
[HC020] Unreachable basic block: fn=Foo.bar bb=15 (if false branch never taken)
```
### 成果物
- DeadBlockAnalyzerBox の設計API シグネチャ)
- Analysis IR 拡張フィールド決定
---
## 4. Task 3: hako_check パイプラインへの統合設計
### 目的
HC020 ルールを既存の hako_check パイプラインに統合
### やること
1. **Analysis IR 生成の拡張**
- `tools/hako_check/analysis_ir.hako` を拡張
- CFG 情報blocks, edges, entry_blockを含める
2. **CLI フラグ追加**
- `--dead-blocks` フラグで HC020 を有効化
- または `--dead-code` に統合(ブロックレベルも含む)
3. **ルール実行順序**
- HC019dead codeの後に HC020dead blocksを実行
- または `--rules dead_blocks` で個別指定可能に
### 設計方針
**Option A**: `--dead-code` に統合
```bash
# HC019 + HC020 を両方実行
./tools/hako_check.sh --dead-code target.hako
```
**Option B**: 別フラグ
```bash
# HC019 のみ
./tools/hako_check.sh --dead-code target.hako
# HC020 のみ
./tools/hako_check.sh --dead-blocks target.hako
# 両方
./tools/hako_check.sh --dead-code --dead-blocks target.hako
```
**推奨**: Option Aユーザーは「dead code」を広義に捉えるため
### 成果物
- パイプライン統合設計
- CLI フラグ仕様確定
---
## 5. Task 4: テストケース設計(ブロックレベル)
### テストケース一覧
#### Case 1: 早期 return 後のコード
```hako
static box TestEarlyReturn {
test(x) {
if x > 0 {
return 1
}
// ここに到達不能コード
local unreachable = 42 // HC020 検出対象
return unreachable
}
}
```
#### Case 2: 常に false の条件
```hako
static box TestAlwaysFalse {
test() {
if false {
// このブロック全体が到達不能
return 999 // HC020 検出対象
}
return 0
}
}
```
#### Case 3: 無限ループ後のコード
```hako
static box TestInfiniteLoop {
test() {
loop(true) {
// 無限ループ
}
// ここに到達不能
return 0 // HC020 検出対象
}
}
```
#### Case 4: break 後のコード(ループ内)
```hako
static box TestAfterBreak {
test() {
loop(true) {
break
// break 後のコード
local x = 1 // HC020 検出対象
}
return 0
}
}
```
### 成果物
- テスト .hako ファイル 4 本
- 期待される HC020 出力の定義
---
## 6. Task 5: 実装 & テスト
### 実装ファイル
1. **`tools/hako_check/rules/rule_dead_blocks.hako`** - 新規作成
- DeadBlockAnalyzerBox 実装
- HC020 ルール実装
2. **`tools/hako_check/analysis_ir.hako`** - 拡張
- CFG 情報フィールド追加
3. **`tools/hako_check/cli.hako`** - 修正
- `--dead-blocks` または `--dead-code` 拡張
- HC020 実行統合
### テストファイル
1. **`apps/tests/hako_check/test_dead_blocks_early_return.hako`**
2. **`apps/tests/hako_check/test_dead_blocks_always_false.hako`**
3. **`apps/tests/hako_check/test_dead_blocks_infinite_loop.hako`**
4. **`apps/tests/hako_check/test_dead_blocks_after_break.hako`**
### スモークスクリプト
- `tools/hako_check_deadblocks_smoke.sh` - HC020 スモークテスト
### 成果物
- DeadBlockAnalyzerBox 実装
- HC020 ルール実装
- テストケース 4 本
- スモークスクリプト
---
## 7. Task 6: ドキュメント & CURRENT_TASK 更新
### ドキュメント更新
1. **phase154_mir_cfg_deadblocks.md** に:
- 実装結果を記録
- CFG 統合の最終設計
2. **hako_check_design.md** を更新:
- HC020 ルールの説明
- CFG 解析機能の説明
3. **CURRENT_TASK.md**
- Phase 154 セクションを追加
4. **CLAUDE.md**
- hako_check ワークフローに `--dead-blocks` 追記(必要なら)
### 成果物
- 各種ドキュメント更新
- git commit
---
## ✅ 完成チェックリストPhase 154
- [ ] Task 1: MIR/CFG 情報インベントリ完了
- [ ] CFG 構造確認
- [ ] Analysis IR 拡張フィールド決定
- [ ] Task 2: DeadBlockAnalyzerBox 設計
- [ ] API シグネチャ決定
- [ ] 到達可能性アルゴリズム決定
- [ ] Task 3: パイプライン統合設計
- [ ] CLI フラグ仕様確定
- [ ] ルール実行順序確定
- [ ] Task 4: テストケース設計
- [ ] テスト .hako 4 本設計
- [ ] Task 5: 実装 & テスト
- [ ] DeadBlockAnalyzerBox 実装
- [ ] HC020 ルール実装
- [ ] テストケース実装
- [ ] スモークスクリプト作成
- [ ] Task 6: ドキュメント更新
- [ ] phase154_mir_cfg_deadblocks.md 確定版
- [ ] hako_check_design.md 更新
- [ ] CURRENT_TASK.md 更新
- [ ] git commit
---
## 技術的考慮事項
### JoinIR Strict モードとの整合性
Phase 150 で確認済みの代表ケースで CFG 情報が取れることを確認:
- `peek_expr_block.hako` - match 式、ブロック式
- `loop_min_while.hako` - ループ変数、Entry/Exit PHI
- `joinir_min_loop.hako` - break 制御
- `joinir_if_select_simple.hako` - 早期 return
### Analysis IR の CFG 拡張案
```json
{
"methods": [...],
"calls": [...],
"boxes": [...],
"entrypoints": [...],
"cfg": {
"functions": [
{
"name": "Main.main",
"entry_block": 0,
"blocks": [
{"id": 0, "successors": [1, 2], "terminator": "Branch"},
{"id": 1, "successors": [3], "terminator": "Jump"},
{"id": 2, "successors": [3], "terminator": "Jump"},
{"id": 3, "successors": [], "terminator": "Return"}
]
}
]
}
}
```
---
## 次のステップ
Phase 154 完了後:
- **Phase 155+**: より高度な解析(定数畳み込み、型推論など)
- **Phase 160+**: .hako JoinIR/MIR 移植章
---
**作成日**: 2025-12-04
**Phase**: 154MIR CFG 統合 & ブロックレベル unreachable 検出)
Status: Historical