# Phase 268: if_form.rs への Frag 適用 + Entry Edge-args SSOT化 Status: ✅ 完了(P0 + P1) Date: 2025-12-21 ## 目的 **EdgeCFG Fragment を "層を跨がずに" 実戦投入** - **P0**: `if_form.rs` の emit_conditional + emit_jump を Frag+emit_frag に置換(1箇所のみ) - **P1**: compose::if_() の then/else entry edge-args を SSOT 化(TODO 解消) ## 実装結果 ### P0: 最小適用(emission 層経由) **アーキテクチャ戦略**: - `if_form.rs` に直接 Frag 構築コードを書かず、`emission/branch.rs` に薄い入口関数 `emit_conditional_edgecfg()` を追加 - **理由**: 層が綺麗(Frag 構築は emission 層に閉じる)、差分が小さい(if_form.rs は API 呼び出し差し替えのみ)、デバッグ容易(層境界が明確) **アーキテクチャ図**: ``` if_form.rs (MirBuilder 層) ↓ 呼び出し emission/branch.rs::emit_conditional_edgecfg() (emission 層: 薄ラッパー) ↓ 内部で使用 Frag 構築 + compose::if_() + emit_frag() (EdgeCFG Fragment API) ↓ 最終的に呼び出し set_branch_with_edge_args() / set_jump_with_edge_args() (Phase 260 SSOT) ``` **変更内容**: 1. **emission/branch.rs** に `emit_conditional_edgecfg()` 関数追加(~50行) - 責務: Frag 構築 + compose::if_() + emit_frag() の薄いラッパー - Then/Else Frag 構築(then_exit_block/else_exit_block から Normal exit 作成) - Join Frag 構築 - compose::if_() で合成 - emit_frag() で MIR terminator に変換 2. **if_form.rs** API 呼び出し差し替え - Lines 109-114: 削除(emit_conditional 呼び出し) - Line 147: 削除(emit_jump 呼び出し) - Line 202: 削除(emit_jump 呼び出し) - Line 206: 追加(emit_conditional_edgecfg 呼び出し、~10行) - **差分**: 削除3箇所 + 追加1箇所のみ(層が綺麗) **テスト結果**: - ✅ cargo build --release: 成功 - ✅ cargo test --lib --release: 1395 tests PASS - ✅ quick smoke: 45/46 PASS(既存状態維持) ### P1: compose::if_() Entry Edge-args SSOT化 **目的**: compose::if_() 内部で then/else entry edge-args を "勝手に空 Vec で生成" しない → 呼び出し側が明示的に渡す(SSOT 原則) **変更内容**: 1. **compose.rs** (Lines 106-127): compose::if_() シグネチャ変更 - Before: `if_(header, cond, t, e, join_frag)` - After: `if_(header, cond, t, then_entry_args, e, else_entry_args, join_frag)` - TODO コメント削除完了(Phase 267 P2+ TODO 解消) 2. **emission/branch.rs** (Lines 110-125): emit_conditional_edgecfg() から空 EdgeArgs を渡す ```rust compose::if_( pre_branch_bb, condition_val, then_frag, EdgeArgs { layout: CarriersOnly, values: vec![] }, // then entry args else_frag, EdgeArgs { layout: CarriersOnly, values: vec![] }, // else entry args join_frag, ) ``` 3. **テスト更新**(3箇所): - compose.rs: Lines 638-652, 720-734(2箇所) - emit.rs: Lines 555-569(1箇所) - 全て新シグネチャに更新、空 EdgeArgs を渡す **テスト結果**: - ✅ cargo build --release: 成功(0エラー) - ✅ cargo test --lib --release: **1444/1444 PASS** - ✅ quick smoke: **45/46 PASS**(既存状態維持) ## 核心的な設計判断 ### P0: なぜ emission 層経由か 1. **層が綺麗**: Frag 構築ロジックを emission 層に閉じ込め、MirBuilder 層から分離 2. **差分が小さい**: if_form.rs は API 呼び出し差し替えのみ(3箇所削除 + 1箇所追加) 3. **デバッグ容易**: 層境界が明確で問題切り分けが簡単 4. **拡張性**: 将来他の箇所(loop_form.rs 等)も同じパターンで統一可能 ### P1: なぜ SSOT 化か 1. **推測禁止**: compose::if_() 内部で then/else entry edge-args を "勝手に空 Vec で生成" しない 2. **呼び出し側 SSOT**: P0 で emission/branch.rs に薄いラッパーを作ったので、edge-args も同じ層で SSOT として渡す 3. **P0 との整合性**: Frag 構築と edge-args 提供を同じ層(emission)に集約 ## 重要な発見 ### Frag "from" ブロックの厳密性 - then_exit_block/else_exit_block は「実際に merge へ飛ぶブロック」と一致必須 - ✅ 正しい: if_form.rs Line 141, 197 で取得済みの値を使用 - ❌ 誤り: "それっぽい" ブロックから Normal exit を作成(ズレる) ### JoinIR Fallback との非交差 - JoinIR 経路は PHI のみ処理(terminator 非依存、Line 287-298) - terminator 生成(emit_conditional_edgecfg)と PHI 生成(JoinIR)は完全に分離されている - 競合可能性なし ## 次フェーズへの橋渡し **Phase 269**: Pattern への展開 - Pattern6/7/8 を Frag 化 - NormalizedShadow/JoinIR への適用 - pattern番号分岐削減 - fixture + smoke test ## 関連ドキュメント - **設計図**: `docs/development/current/main/design/edgecfg-fragments.md` - **現在のタスク**: `docs/development/current/main/10-Now.md` - **バックログ**: `docs/development/current/main/30-Backlog.md` - **Phase 267**: `docs/development/current/main/phases/phase-267/README.md` ## 受け入れ基準(全達成) ### P0 成功条件 - ✅ `cargo build --release` 成功 - ✅ `cargo test --lib --release` で 1395 tests PASS - ✅ `tools/smokes/v2/run.sh --profile quick` で 45/46 PASS - ✅ MIR dump で Branch/Jump terminator 正常生成確認 - ✅ JoinIR fallback 経路動作確認 ### P1 成功条件 - ✅ `cargo build --release` 成功 - ✅ `cargo test --lib --release` で 1444 tests PASS - ✅ compose.rs/emit.rs unit tests 全 PASS - ✅ `tools/smokes/v2/run.sh --profile quick` で 45/46 PASS 維持 - ✅ TODO コメント削除完了(Phase 267 P2+ TODO 解消) - ✅ Edge-args パラメータ SSOT 化完了 - ✅ ドキュメント更新完了(4ファイル): - ✅ 10-Now.md 追記 - ✅ 30-Backlog.md 更新 - ✅ edgecfg-fragments.md 追記 - ✅ phases/phase-268/README.md 新規作成 ## まとめ **Phase 268 P0-P1 完全成功!** - ✅ EdgeCFG Fragment の最初の実戦投入(if_form.rs) - ✅ emission 層経由で層境界を綺麗に保つアーキテクチャ確立 - ✅ compose::if_() の entry edge-args SSOT 化完了 - ✅ 全テスト PASS(1444 tests + 45/46 smoke) - ✅ TODO 削除完了 **次のステップ**: Phase 269 で Pattern6/7/8 への Frag 適用 + fixture/smoke test