🎉 Conservative PHI Box理論による完全SSA構築 **Phase 7-B: Conservative PHI実装** - 片方branchのみ定義変数に対応(emit_void使用) - 全変数にPHI生成(Conservative Box理論) - Stage-1 resolver全テスト緑化(3/3 PASS) **Phase 25.1f: ControlForm観測レイヤー** - LoopShape/IfShape/ControlForm構造定義 - Loop/If統一インターフェース実装 - debug_dump/debug_validate機能追加 - NYASH_CONTROL_FORM_TRACE環境変数対応 **主な変更**: - src/mir/builder/phi.rs: Conservative PHI実装 - src/mir/control_form.rs: ControlForm構造(NEW) - src/mir/loop_builder.rs: LoopForm v2デフォルト化 **テスト結果**: ✅ mir_stage1_using_resolver_min_fragment_verifies ✅ mir_stage1_using_resolver_full_collect_entries_verifies ✅ mir_parserbox_parse_program2_harness_parses_minimal_source 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: ChatGPT <chatgpt@openai.com>
119 lines
6.6 KiB
Markdown
119 lines
6.6 KiB
Markdown
# Phase 25.1g — Conservative PHI ↔ ControlForm 統合(設計+小さな導線)
|
||
|
||
Status: planning(設計・導線追加/既存挙動は変えない)
|
||
|
||
## ゴール
|
||
|
||
- 25.1f で整えた **ControlForm 観測レイヤー**(LoopShape / IfShape + ControlForm)を、
|
||
Conservative PHI Box(If/Loop 用 SSA/PHI ロジック)の入口として使えるようにする。
|
||
- いきなりすべてを書き換えるのではなく、
|
||
1. If 用 Conservative PHI → ControlForm 対応
|
||
2. LoopForm v2 Exit PHI → ControlForm 対応
|
||
の順に、小さく段階的に寄せる。
|
||
- 各ステップごとに Rust テストと `tools/test_stageb_min.sh` を流しつつ、
|
||
SSA/PHI の赤ログが増えていないことを確認して進む。
|
||
|
||
## 前提(25.1f までで揃ったもの)
|
||
|
||
- Rust:
|
||
- `src/mir/control_form.rs`:
|
||
- `LoopShape` / `IfShape` / `ControlKind` / `ControlForm` / `CfgLike` / `is_control_form_trace_on()` が定義済み。
|
||
- `src/mir/loop_builder.rs`:
|
||
- LoopForm v2 経路(`build_loop_with_loopform`)の出口で `LoopShape` → `ControlForm::Loop` を生成・トレース。
|
||
- `lower_if_in_loop` の merge 部分で `IfShape` → `ControlForm::If` を生成・トレース。
|
||
- `NYASH_CONTROL_FORM_TRACE`(未設定=ON, 0/false=OFF)でトレース ON/OFF 切り替え可能。
|
||
- Conservative PHI:
|
||
- If 用: `src/mir/builder/phi.rs` / `src/mir/phi_core/if_phi.rs`(Conservative PHI Box 実装)。
|
||
- Loop 用: `src/mir/phi_core/loopform_builder.rs`(LoopForm v2 の Exit PHI / Carrier/Pinned 対応)。
|
||
- .hako:
|
||
- `lang/src/shared/mir/control_form_box.hako`:
|
||
- `static box ControlFormBox`(kind_name + loop_* / if_* + entry/exits)だけ実装済み(まだ未使用)。
|
||
|
||
## 方針(Option B の範囲)
|
||
|
||
- **このフェーズでは**:
|
||
- Conservative PHI の「インターフェースと呼び出し位置」に ControlForm の導線を用意する。
|
||
- ただし既存のロジック(引数で BlockId を受け取る形)は残し、ControlForm 導線は **観測+補助的な入口** として扱う。
|
||
- 影響範囲は If / Loop の PHI 部分に限定し、他の MIR 降下には触れない。
|
||
- 実装方針:
|
||
- 新しい API を「足す」→ 既存コードから段階的に使い始める、という形で進める。
|
||
- 例:
|
||
- If 用: `merge_modified_at_merge_with_control(form: &ControlForm, ...)` を追加。
|
||
- Loop 用: `build_exit_phis_for_control(form: &ControlForm, ...)` を追加。
|
||
- 最初のステップでは「ControlForm から必要な BlockId を取り出して、既存の関数に委譲するだけ」の薄いラッパにする。
|
||
|
||
## タスク粒度
|
||
|
||
### G‑1: If 用 Conservative PHI への ControlForm 導線
|
||
|
||
- 目的:
|
||
- `loop_builder.rs::lower_if_in_loop` から、`ControlForm::If` を PHI ロジックに渡せるようにする。
|
||
- ステップ:
|
||
1. `src/mir/phi_core/if_phi.rs` に薄いラッパ関数を追加:
|
||
```rust
|
||
pub fn merge_modified_with_control<O: PhiMergeOps>(
|
||
ops: &mut O,
|
||
form: &crate::mir::control_form::ControlForm,
|
||
pre_if_snapshot: &HashMap<String, ValueId>,
|
||
then_map_end: &HashMap<String, ValueId>,
|
||
else_map_end_opt: &Option<HashMap<String, ValueId>>,
|
||
skip_var: Option<&str>,
|
||
) -> Result<(), String> {
|
||
// ControlForm::If から cond/then/else/merge を取り出し、
|
||
// 既存の merge_modified_at_merge_with に橋渡しするだけ(ロジックは変えない)。
|
||
}
|
||
```
|
||
2. `lower_if_in_loop` 側で:
|
||
- 既存の `merge_modified_at_merge_with` 呼び出しの直前/直後にコメントを付け、
|
||
- 将来的に `merge_modified_with_control` に置き換えられるように位置を明示する(25.1g ではまだ呼び替えない or dev フラグで限定)。
|
||
3. テスト:
|
||
- `cargo test -q mir_stage1_using_resolver_min_fragment_verifies -- --nocapture`
|
||
- `cargo test -q mir_stage1_using_resolver_full_collect_entries_verifies -- --nocapture`
|
||
- 必要なら `NYASH_CONTROL_FORM_TRACE=1` で IfShape ログを確認し、BlockId 対応が設計どおりかを確認。
|
||
|
||
### G‑2: LoopForm v2 Exit PHI への ControlForm 導線
|
||
|
||
- 目的:
|
||
- LoopForm v2 Exit PHI(`loopform_builder.rs::build_exit_phis`)にも ControlForm ベースの入口を用意する。
|
||
- ステップ:
|
||
1. `src/mir/phi_core/loopform_builder.rs` にラッパ関数追加:
|
||
```rust
|
||
pub fn build_exit_phis_for_control<O: LoopFormOps>(
|
||
loopform: &LoopFormBuilder,
|
||
ops: &mut O,
|
||
form: &crate::mir::control_form::ControlForm,
|
||
exit_snapshots: &[(BasicBlockId, HashMap<String, ValueId>)],
|
||
) -> Result<(), String> {
|
||
// form.kind が Loop の場合に限り、
|
||
// shape.preheader/header/body/latch/exit から exit_id/branch_source_block を決めて
|
||
// 既存の build_exit_phis に委譲するだけ。
|
||
}
|
||
```
|
||
2. `LoopBuilder::build_loop_with_loopform` からは:
|
||
- 現在どおり `loopform.build_exit_phis(self, exit_id, branch_source_block, &exit_snaps)` を呼び続ける。
|
||
- コメントで「ControlForm 経由の入口」があることを明示し、将来の切り替えポイントを固定する。
|
||
3. テスト:
|
||
- `cargo test -q mir_loopform_exit_phi -- --nocapture`
|
||
- `cargo test -q mir_stageb_loop_break_continue -- --nocapture`
|
||
- `./tools/test_stageb_min.sh` を流して、Exit PHI 誘発系の赤ログが増えていないことを確認。
|
||
|
||
### G‑3: ControlForm ↔ Conservative PHI の設計メモ更新
|
||
|
||
- 目的:
|
||
- 25.1d/e/f/g の成果をまとめ、「If/Loop の PHI が最終的にどのレイヤで SSOT を持つか」を文書で固定する。
|
||
- ステップ:
|
||
- `phase-25.1d/README.md` と `phase-25.1f/README.md` をリンクしつつ、
|
||
- Conservative PHI Box の責務(If/Loop 両方)
|
||
- ControlForm レイヤの責務
|
||
- .hako 側 `ControlFormBox` / `LoopSSA` の予定
|
||
を Phase 25 全体の流れの中に整理して追記する。
|
||
- `CURRENT_TASK.md` に 25.1g の短いサマリを追加して、今どこまで進めたかをいつでも追えるようにする。
|
||
|
||
## このフェーズで「しない」こと
|
||
|
||
- 既存の Conservative PHI 実装を一気に ControlForm 専用に書き換えること:
|
||
- 25.1g は「導線追加+ラッパ」「設計固め」まで。
|
||
- 実際の置き換え(Option B の本体)は、さらに小さなステップに分けて後続フェーズで行う。
|
||
- LoopBuilder/If 降下の大規模リファクタ(Option C 相当):
|
||
- これは Phase 25.2 以降の仕事として残しておく。
|