From 79b9d2b32c69add43a30c5b69970d9f6840f861c Mon Sep 17 00:00:00 2001 From: nyash-codex Date: Sat, 1 Nov 2025 14:37:54 +0900 Subject: [PATCH] fix(mir): edge-copy insertion before terminator - resolve ValueId undefined errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 【問題】 Stage-B(JSON v0 Bridge)で「use of undefined value ValueId(...)」エラー発生 - 原因: merge.rs:38-42でedge-copyを終端命令**後**に追加していた - 結果: Copy命令が到達不能となり、ValueIdが未定義のまま参照される 【根本原因分析】 1. if_else.rs:34で`set_terminator(Jump)`を設定 2. if_else.rs:62で`merge_var_maps()`呼び出し 3. merge.rs:39で`add_instruction(Copy)` ← **ここで終端後に追加!** 4. BasicBlock構造上、terminator設定後のadd_instruction()は到達不能 【修正内容】 1. BasicBlock::add_instruction_before_terminator()メソッド追加 - 終端命令の有無に関わらず、instructions vecに追加 - terminator自体の追加は許可しない(panic) 2. merge_values()でedge-copy挿入方法を変更 - add_instruction() → add_instruction_before_terminator() - これによりCopyが終端の**前**に配置される 【修正箇所】 - src/mir/basic_block.rs: add_instruction_before_terminator()追加(12行) - src/runner/json_v0_bridge/lowering/merge.rs: 呼び出し変更(2行) 【テスト結果】 ✅ if文PHIテスト: /tmp/phi_simple_if2.nyash → 出力 1 ✅ loop文PHIテスト: /tmp/phi_loop_test.nyash → 出力 10 ✅ userbox_*スモークテスト: 全6テストPASS ⚠️ Stage-B: namespace conflict未解決のため未確認 (apps/selfhost.vm.* と lang/hakorune.vm.* の競合) 【影響範囲】 - JSON v0 Bridge経路のif/else合流処理 - edge-copy(PHI-off mode)の正しい配置保証 - Builder経路は元々正常動作(影響なし) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/mir/basic_block.rs | 14 ++++++++++++++ src/runner/json_v0_bridge/lowering/merge.rs | 5 +++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/mir/basic_block.rs b/src/mir/basic_block.rs index 37d5040e..88953c72 100644 --- a/src/mir/basic_block.rs +++ b/src/mir/basic_block.rs @@ -102,6 +102,20 @@ impl BasicBlock { } } + /// Add instruction before terminator (for edge-copy in PHI-off mode) + /// If no terminator exists, behaves like add_instruction() + pub fn add_instruction_before_terminator(&mut self, instruction: MirInstruction) { + // Update effect mask + self.effects = self.effects | instruction.effects(); + + // Non-terminator instructions always go into instructions vec + if !self.is_terminator(&instruction) { + self.instructions.push(instruction); + } else { + panic!("Cannot add terminator via add_instruction_before_terminator"); + } + } + /// Check if an instruction is a terminator fn is_terminator(&self, instruction: &MirInstruction) -> bool { matches!( diff --git a/src/runner/json_v0_bridge/lowering/merge.rs b/src/runner/json_v0_bridge/lowering/merge.rs index 3a20a312..9628dae0 100644 --- a/src/runner/json_v0_bridge/lowering/merge.rs +++ b/src/runner/json_v0_bridge/lowering/merge.rs @@ -35,11 +35,12 @@ pub(super) fn merge_values( } let dst = f.next_value_id(); if no_phi { + // Insert edge-copy BEFORE terminator (critical fix for ValueId undefined errors) if let Some(bb) = f.get_block_mut(pred_a) { - bb.add_instruction(MirInstruction::Copy { dst, src: val_a }); + bb.add_instruction_before_terminator(MirInstruction::Copy { dst, src: val_a }); } if let Some(bb) = f.get_block_mut(pred_b) { - bb.add_instruction(MirInstruction::Copy { dst, src: val_b }); + bb.add_instruction_before_terminator(MirInstruction::Copy { dst, src: val_b }); } } else if let Some(bb) = f.get_block_mut(merge_bb) { bb.insert_instruction_after_phis(MirInstruction::Phi {