Files
hakorune/docs/development/current/main/design/join-explicit-cfg-construction.md

3.6 KiB
Raw Blame History

Join-Explicit CFG Construction

Status: SSOTdesign goal
Scope: JoinIR→MIR の「暗黙 ABI」を消し、Join を第一級に扱う CFG へ収束させる北極星north star
Related:

  • Navigation SSOT: docs/development/current/main/design/joinir-design-map.md
  • Investigation (Phase 256): docs/development/current/main/investigations/phase-256-joinir-contract-questions.md
  • Decisions: docs/development/current/main/20-Decisions.md

Goal最終形

“Join-Explicit CFG Construction” を目指す。

  • Jump/continuation/params/edge-args を **第一級explicit**として扱う
  • JoinIR↔MIR 間の 暗黙 ABI順序/長さ/名前/役割) をなくすSSOT を 1 箇所に封印)
  • 変換は「意味の解釈」ではなく「写像mapping」に縮退する

Non-Goalsいまはやらない

  • JoinIR を即座に削除する(まずは ABI/Contract で SSOT を固める)
  • PHI を全面廃止して block params に置換する一括リファクタ(段階導入)

現状の問題Phase 256 で露出した型)

  • jump_args / exit_bindings / entry.params / boundary.join_inputs が “だいたい同じ順序” を前提にしており、ズレると SSA/dominance が破綻する
  • expr_result と LoopState carrier が同一 ValueId になり得るが、legacy “expr_result slot” 推測で offset がずれて誤配線になる
  • jump_args が IR の外側メタ扱いだと、DCE/最適化が “use” を見落としやすい
  • spans が並行 Vec だと、パスが 1 箇所でも取りこぼすと SPAN MISMATCH になる

移行戦略(段階導入 / Strangler

原則:

  • 移行を先に固定し、機能追加は「新契約に乗るものだけ」併走する(旧経路に新機能を足さない)
  • 既定挙動を変えない(必要なら dev-only の診断ガードで観測)

Stage 1短期: JoinIR を “ABI/Contract 付き Normalized SSOT” にする

狙い: 推測をなくし、順序/役割の SSOT を 1 箇所へ寄せる。

  • boundary に jump_args_layout のような layout SSOT を持たせ、collector/rewriter が推測しない
  • JoinInst::Jump を terminator 語彙として正規化cond 付きは Branch へ寄せる)
  • continuation の識別は ID SSOTString は debug/serialize のみに縮退)

受け入れ:

  • --verify が PASSSSA/dominance/PHI/ExitLine の契約違反が消える)
  • 直撃回帰テスト(expr_result == carrier 等)が固定される

Stage 2中期: MIR を “edge-args を terminator operand に持つ CFG” に寄せる

狙い: jump_args を “意味データ” として IR に埋め込み、DCE/CFG が自然に追える形へ収束する。

  • jump_args を BasicBlock 外メタから terminator operand へ寄せる(段階導入: 互換フィールド併存→移行)
  • spans は Vec<Spanned<_>>API で不変条件を守る)

受け入れ:

  • jump_args 由来の use が最適化で消えない(テストで固定)
  • SPAN MISMATCH が構造的に起きない

Stage 3長期: JoinIR と MIR の境界を薄くし、必要なら JoinIR を builder へ降格

狙い: “bridge/merge が意味解釈する余地” を最小化し、一本の CFG 語彙に収束させる。

  • JoinIR を SSOT IR として残すか、builder DSL として降格するかは、この段階で再判断する

実務ルールPhase 中の運用)

  • 新パターン/新機能は「新しい Contract で記述できる場合のみ」追加する
  • Contract の導入中は “機能追加より SSOT 固め” を優先する(泥沼デバッグの再発防止)