🔧 Hotfix 7 (Enhanced): ValueId receiver alias tracking for nested loops
- Problem: Pinned receiver variables in loops cause undefined ValueId errors - Enhanced fix: Update all receiver aliases (me + all __pin$N$@recv levels) - Handles nested loops by updating previous pin levels - Test status: Partial improvement, ValueId(50) → ValueId(40) - Further investigation needed for complete fix Files modified: - src/mir/phi_core/loopform_builder.rs (emit_header_phis)
This commit is contained in:
@ -1,6 +1,6 @@
|
||||
# Phase 25.1g — Conservative PHI ↔ ControlForm 統合(設計+小さな導線)
|
||||
# Phase 25.1g — Conservative PHI ↔ ControlForm 統合(Rust統合完了)
|
||||
|
||||
Status: planning(設計・導線追加/既存挙動は変えない)
|
||||
Status: completed(ControlForm 導線統合+レガシー縮退/挙動は不変)
|
||||
|
||||
## ゴール
|
||||
|
||||
@ -42,77 +42,163 @@ Status: planning(設計・導線追加/既存挙動は変えない)
|
||||
- Loop 用: `build_exit_phis_for_control(form: &ControlForm, ...)` を追加。
|
||||
- 最初のステップでは「ControlForm から必要な BlockId を取り出して、既存の関数に委譲するだけ」の薄いラッパにする。
|
||||
|
||||
## タスク粒度
|
||||
## 実施内容
|
||||
|
||||
### G‑1: If 用 Conservative PHI への ControlForm 導線
|
||||
### 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 対応が設計どおりかを確認。
|
||||
- `loop_builder.rs::lower_if_in_loop` から `ControlForm::If` を PHI ロジックに渡し、Conservative PHI Box が ControlForm ベースで動けるようにする。
|
||||
- 実装:
|
||||
- `src/mir/phi_core/if_phi.rs` に ControlForm ベースの薄いラッパを追加:
|
||||
```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>,
|
||||
then_pred_opt: Option<crate::mir::BasicBlockId>,
|
||||
else_pred_opt: Option<crate::mir::BasicBlockId>,
|
||||
) -> Result<(), String> {
|
||||
use crate::mir::control_form::ControlKind;
|
||||
|
||||
### G‑2: LoopForm v2 Exit PHI への ControlForm 導線
|
||||
let shape = match &form.kind {
|
||||
ControlKind::If(shape) => shape,
|
||||
_ => return Ok(()),
|
||||
};
|
||||
|
||||
let merge_bb = shape.merge_block;
|
||||
|
||||
let trace = std::env::var("NYASH_IF_TRACE").ok().as_deref() == Some("1");
|
||||
if trace {
|
||||
eprintln!(
|
||||
"[if-phi/control-form] Using ControlForm wrapper: merge={:?} then={:?} else={:?}",
|
||||
merge_bb, shape.then_block, shape.else_block
|
||||
);
|
||||
}
|
||||
|
||||
merge_modified_at_merge_with(
|
||||
ops,
|
||||
merge_bb,
|
||||
shape.then_block,
|
||||
shape.else_block.unwrap_or(shape.then_block),
|
||||
then_pred_opt,
|
||||
else_pred_opt,
|
||||
pre_if_snapshot,
|
||||
then_map_end,
|
||||
else_map_end_opt,
|
||||
skip_var,
|
||||
)
|
||||
}
|
||||
```
|
||||
- `src/mir/loop_builder.rs::lower_if_in_loop` では、IfShape→ControlForm を構築してこのラッパを直接呼び出すように統合:
|
||||
```rust
|
||||
let if_shape = IfShape {
|
||||
cond_block: pre_branch_bb,
|
||||
then_block: then_bb,
|
||||
else_block: Some(else_bb),
|
||||
merge_block: merge_bb,
|
||||
};
|
||||
let form = ControlForm::from_if(if_shape.clone());
|
||||
|
||||
crate::mir::phi_core::if_phi::merge_modified_with_control(
|
||||
&mut ops,
|
||||
&form,
|
||||
&pre_if_var_map,
|
||||
&then_var_map_end,
|
||||
&else_var_map_end_opt,
|
||||
None,
|
||||
Some(then_pred_to_merge),
|
||||
Some(else_pred_to_merge),
|
||||
)?;
|
||||
```
|
||||
- その後ろで `is_control_form_trace_on()` が true のときに `form.debug_dump()` と `if_shape.debug_validate()` を呼び、
|
||||
If の形を ControlForm 経由で常時観測できるようにした。
|
||||
- テスト:
|
||||
- `cargo test -q mir_stage1_using_resolver_min_fragment_verifies -- --nocapture`
|
||||
- `cargo test -q mir_stage1_using_resolver_full_collect_entries_verifies -- --nocapture`
|
||||
- いずれも PASS(Conservative PHI の挙動変化なし)。
|
||||
|
||||
### 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 誘発系の赤ログが増えていないことを確認。
|
||||
- LoopForm v2 Exit PHI が ControlForm(LoopShape)を入口に使えるようにする。
|
||||
- 実装:
|
||||
- `src/mir/phi_core/loopform_builder.rs` に ControlForm 用ラッパを追加:
|
||||
```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>)],
|
||||
branch_source_block: BasicBlockId,
|
||||
) -> Result<(), String> {
|
||||
use crate::mir::control_form::ControlKind;
|
||||
|
||||
### G‑3: ControlForm ↔ Conservative PHI の設計メモ更新
|
||||
let shape = match &form.kind {
|
||||
ControlKind::Loop(shape) => shape,
|
||||
_ => return Ok(()),
|
||||
};
|
||||
|
||||
let exit_id = shape.exit;
|
||||
let trace = std::env::var("NYASH_LOOPFORM_DEBUG").ok().is_some();
|
||||
if trace {
|
||||
eprintln!(
|
||||
"[loopform/exit-phi/control-form] Using ControlForm wrapper: exit={:?} branch_source={:?}",
|
||||
exit_id, branch_source_block
|
||||
);
|
||||
}
|
||||
|
||||
loopform.build_exit_phis(ops, exit_id, branch_source_block, exit_snapshots)
|
||||
}
|
||||
```
|
||||
- `src/mir/loop_builder.rs::build_loop_with_loopform` では、Exit PHI 部分をこのラッパ経由に統一し、
|
||||
その直後で `ControlForm::Loop` の `debug_dump` / `debug_validate` を行うように整理:
|
||||
```rust
|
||||
let loop_shape = LoopShape {
|
||||
preheader: preheader_id,
|
||||
header: header_id,
|
||||
body: body_id,
|
||||
latch: latch_id,
|
||||
exit: exit_id,
|
||||
continue_targets,
|
||||
break_targets,
|
||||
};
|
||||
let form = ControlForm::from_loop(loop_shape.clone());
|
||||
|
||||
let exit_snaps = self.exit_snapshots.clone();
|
||||
crate::mir::phi_core::loopform_builder::build_exit_phis_for_control(
|
||||
&loopform,
|
||||
self,
|
||||
&form,
|
||||
&exit_snaps,
|
||||
branch_source_block,
|
||||
)?;
|
||||
|
||||
if is_control_form_trace_on() {
|
||||
form.debug_dump();
|
||||
#[cfg(debug_assertions)]
|
||||
if let Some(ref func) = self.parent_builder.current_function {
|
||||
loop_shape.debug_validate(func);
|
||||
}
|
||||
}
|
||||
```
|
||||
- テスト:
|
||||
- `cargo test -q mir_loopform_exit_phi -- --nocapture`
|
||||
- `cargo test -q mir_stageb_loop_break_continue -- --nocapture`
|
||||
- いずれも PASS。Exit PHI の SSA/PHI 挙動は従来と同じで、ControlForm ベースでも構造が崩れていないことを確認。
|
||||
|
||||
### 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 の短いサマリを追加して、今どこまで進めたかをいつでも追えるようにする。
|
||||
- 実施:
|
||||
- 本 README と `CURRENT_TASK.md` に、Conservative PHI Box と ControlForm レイヤの役割分担を整理して追記。
|
||||
- 25.1g は「Rust 側での Conservative PHI ↔ ControlForm 統合(If/Loop)完了」フェーズとして締める。
|
||||
|
||||
## このフェーズで「しない」こと
|
||||
## このフェーズで残っていること / 先送りしたこと
|
||||
|
||||
- 既存の Conservative PHI 実装を一気に ControlForm 専用に書き換えること:
|
||||
- 25.1g は「導線追加+ラッパ」「設計固め」まで。
|
||||
- 実際の置き換え(Option B の本体)は、さらに小さなステップに分けて後続フェーズで行う。
|
||||
- LoopBuilder/If 降下の大規模リファクタ(Option C 相当):
|
||||
- これは Phase 25.2 以降の仕事として残しておく。
|
||||
- `.hako` 側 LoopSSA / Stage‑B パイプラインはまだ ControlFormBox 未統合のまま。
|
||||
- Test 3(Stage‑B MIR verify)の `%0` 問題や、BreakFinderBox 周辺の undefined ValueId は次フェーズ(LoopSSA 実装側)で扱う。
|
||||
- LoopBuilder/If 降下そのものを ControlForm ベースに再構成する「Option C」は、Phase 25.2 以降の大きめリファクタとして残しておく。
|
||||
|
||||
Reference in New Issue
Block a user