# Phase 260: Block-Parameterized CFG(edge-args)段階導入 Status: In progress Last updated: 2025-12-20 ## 進捗(セーブポイント) - P0(併存導入の芯): 完了(読む側 SSOT を `out_edges()`/`edge_args_to()` に寄せた) - Commit: `4dfe3349b` - P0.1(hardening): 完了(legacy layout 無し禁止 + DCE/verify の参照点整理) - Commit: `1fe5be347` ## 目的(P0) JoinIR→MIR の暗黙 ABI(jump_args / carriers / expr_result slot / successors)を減らし、将来的な **block-parameterized CFG**(edge-args を第一級に持つCFG)へ収束するための「大工事パート」を開始する。 このフェーズは “一括置換” ではなく、**併存導入(Strangler)**で可逆に進める。 ## 背景(Phase 256-259 で露出した型) - `jump_args` が IR 外メタとして存在すると、DCE/verify/CFG 更新が「忘れると壊れる」になる - spans が並行 Vec だと、最適化や変換で同期漏れが起きやすい - continuation / entry / exit の識別と args 順序が散在すると、推測・補正が増殖する North Star: `docs/development/current/main/design/join-explicit-cfg-construction.md` ## 方針(2段正規化) - **Semantic Normalization(意味SSOT)**: terminator 語彙の固定(例: cond付きJumpを正規形から禁止しBranchへ) - **Plumbing Normalization(配線SSOT)**: edge-args / CFG successor / spans を IR 構造に閉じ込め、写像に縮退 ## スコープ(Phase 260) ### In scope - MIR に「edge-args を持つ terminator 表現」を **併存導入**する(旧 `BasicBlock.jump_args` は残す) - “読む側” を単一APIに寄せる(`Branch` を含むので “複数 edge” 前提で一本化する) - 例: `block.out_edges()` / `block.edge_args_to(target)` - 互換期間は **一致検証を Fail-Fast**(両方ある場合は矛盾で即死) ### Out of scope(P0ではやらない) - `BasicBlock.jump_args` の削除(削除は Phase 261+) - spans の内部表現を `Vec>` に一気に切替(Phase 261+ で段階導入) - JoinIR を削除する(builder DSL 降格は長期) ## 実装タスク(P0) 1. `MirTerminator`(または既存 terminator に edge-args を持てる variant)を追加(併存導入) - `Jump` だけでなく `Branch` を含むため、API は “複数 edge” を前提にする 2. bridge が `Jump/Branch` の edge-args を terminator operand としてもセット(旧jump_argsも併記してよい) 3. merge/ExitLine/DCE/verify/printer が参照する入口を一本化(読む側の Strangler) - 推奨: `block.out_edges()` / `block.edge_args_to(target)` のような API(`edge_args()` 単発は Branch で曖昧) 4. Fail-Fast 契約チェック(`--verify` 時に必須) - “両方ある場合は一致” を verify で保証 - 追加: “terminator から計算した successors” と “block.successors キャッシュ” の一致も verify で保証(同期漏れを即死) ## 受け入れ基準(P0) - `cargo build --release` が通る - `./tools/smokes/v2/run.sh --profile quick` が少なくとも悪化しない(same first FAIL 以上) - `--verify` の既存テストが壊れない(PHI/CFG検証が健全) - legacy 依存の “推測” が増えていない(新規の env var 追加なし) - `rg "jump_args"` を走らせて、移行コードと API 以外に参照が増えていない(読む側の寄せ漏れを検出) - DCE 回帰が 1 本以上あり、「edge-args だけで使われる値」が消されないことを固定できている ## ロードマップ(P0→P3) ### P0(併存導入の芯) - **単一参照API**を作る(Branch を含むので “複数 edge” 前提) - 例: `BasicBlock::out_edges()` / `BasicBlock::edge_args_to(target)` - MIR terminator に edge-args を持てる表現を追加(旧 `jump_args` と **併存**) - 推奨: `EdgeArgs { layout: JumpArgsLayout, values: Vec }` のように “意味(layout)” も同梱する - bridge が edge-args を terminator operand に必ず埋める(旧jump_argsも同内容でセットしてよい) - merge/ExitLine/DCE/verify/printer は参照点を `out_edges()`/`edge_args_to(...)` に寄せる - 両方ある場合の **一致検証を Fail-Fast**(`--verify` で必須) ### P1(切替) - `jump_args` を読む経路を段階的に減らす(参照点は `out_edges()`/`edge_args_to(...)` のみ) - terminator 更新の **API一本化**(successors/preds の同期漏れを構造で潰す) - 読む側だけでなく、書く側(terminator 設定/edge-args 設定)も API 経由に寄せる - DCE/verify が terminator operand から自然に use/pred を追えることを固定する ### P2(削除) - `BasicBlock.jump_args` を削除(併存チェックも撤去) - `jump_args` 特例の DCE/verify コードを削除(terminator operand が SSOT) ### P3(spans 収束) - `instructions` + `instruction_spans` の並行 Vec を段階導入で廃止 - 先に編集APIを一本化 → 最終的に `Vec>` へ ## メモ(設計SSOT) - 相談パケット: `docs/development/current/main/investigations/phase-259-block-parameterized-cfg-consult.md` - decisions: `docs/development/current/main/20-Decisions.md`