From bfe047840be44191e9f672801e492a71bb87347d Mon Sep 17 00:00:00 2001 From: nyash-codex Date: Sun, 14 Dec 2025 08:30:54 +0900 Subject: [PATCH] =?UTF-8?q?fix(mir):=20Phase=20131-9=20-=20PHI=20=E5=9E=8B?= =?UTF-8?q?=E6=8E=A8=E8=AB=96=E4=BF=AE=E6=AD=A3=EF=BC=88String=E2=86=92Int?= =?UTF-8?q?eger=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 131-9: MIR PHI 型推論バグ修正 問題: - PHI が String 型として推論される - 結果: 0,01,011(文字列連結) - 期待: 0,1,2(整数 increment) 根本原因: - PHI emission 時に circular dependency - latch incoming value が PHI 型を継承 - 使用側(print)の型要求で String に 修正: - src/mir/builder/lifecycle.rs (+75 lines): - Global PHI Type Inference Pass 追加 - PHI 型を incoming values から再推論 - PhiTypeResolver を再利用 MIR 変化: - Before: %3: String = phi [%2, bb0], [%12, bb7] - After: %3: Integer = phi [%2, bb0], [%12, bb7] テスト結果: - Rust VM: 0,01,011 → 0,1,2 ✅ 完璧! - LLVM: Segfault(別バグ、Phase 131-10 で対応) 箱化モジュール化: - ✅ PhiTypeResolver 再利用 - ✅ 単一責任: PHI 型補正のみ - ✅ Debug flag: NYASH_PHI_GLOBAL_DEBUG=1 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- src/mir/builder/lifecycle.rs | 77 +++++++++++++++++++++++++++++++++++- 1 file changed, 76 insertions(+), 1 deletion(-) diff --git a/src/mir/builder/lifecycle.rs b/src/mir/builder/lifecycle.rs index 9c931f44..d93a6df7 100644 --- a/src/mir/builder/lifecycle.rs +++ b/src/mir/builder/lifecycle.rs @@ -307,13 +307,88 @@ impl super::MirBuilder { let mut module = self.current_module.take().unwrap(); let mut function = self.current_function.take().unwrap(); - function.metadata.value_types = self.value_types.clone(); // Phase 84-2: Copy命令型伝播(return型推論の前に実行) // // Loop exit や If merge の edge copy で発生する型欠如を解消する。 // Copy チェーン: v1 → v2 → v3 で v1 の型が既知なら v2, v3 にも伝播。 CopyTypePropagator::propagate(&function, &mut self.value_types); + // Phase 131-9: Global PHI type inference + // + // Infer types for ALL PHI nodes, not just return values. + // This fixes loop carrier PHIs that don't get inferred otherwise. + // Uses PhiTypeResolver to infer from incoming values (not usage). + // + // Bug: loop_min_while.hako PHI %3 was typed as String instead of Integer + // Cause: PHI incoming values unavailable at emission time + // Fix: Run PhiTypeResolver after CopyTypePropagator, before return type inference + // + // Collect ALL PHI dsts for re-inference (not just untyped) + // This is necessary because propagate_phi_meta may have assigned incorrect types + // due to circular dependencies (e.g., loop carrier PHIs) + let mut all_phi_dsts: Vec = Vec::new(); + for (_bid, bb) in function.blocks.iter() { + for inst in &bb.instructions { + if let MirInstruction::Phi { dst, .. } = inst { + if std::env::var("NYASH_PHI_GLOBAL_DEBUG").is_ok() { + let existing_type = self.value_types.get(dst); + eprintln!( + "[lifecycle/phi-scan] {} PHI {:?} existing type: {:?}", + function.signature.name, dst, existing_type + ); + } + all_phi_dsts.push(*dst); + } + } + } + + if std::env::var("NYASH_PHI_GLOBAL_DEBUG").is_ok() { + eprintln!( + "[lifecycle/phi-scan] {} found {} total PHIs to re-infer", + function.signature.name, + all_phi_dsts.len() + ); + } + + // Re-infer types for ALL PHI nodes using PhiTypeResolver + // This fixes incorrect types assigned by propagate_phi_meta during circular dependencies + if !all_phi_dsts.is_empty() { + let phi_resolver = PhiTypeResolver::new(&function, &self.value_types); + let mut inferred_types: Vec<(ValueId, MirType)> = Vec::new(); + for dst in all_phi_dsts { + if let Some(mt) = phi_resolver.resolve(dst) { + // Check if type changed + let existing_type = self.value_types.get(&dst); + if existing_type.is_none() || existing_type != Some(&mt) { + inferred_types.push((dst, mt)); + } + } + } + + // Now insert/update all inferred types + for (dst, mt) in inferred_types { + let old_type = self.value_types.get(&dst).cloned(); + self.value_types.insert(dst, mt.clone()); + if std::env::var("NYASH_PHI_GLOBAL_DEBUG").is_ok() { + if let Some(old) = old_type { + eprintln!( + "[lifecycle/phi-global] {} PHI {:?} type corrected: {:?} -> {:?}", + function.signature.name, dst, old, mt + ); + } else { + eprintln!( + "[lifecycle/phi-global] {} PHI {:?} type inferred: {:?}", + function.signature.name, dst, mt + ); + } + } + } + } + + // Phase 131-9: Update function metadata with corrected types + // MUST happen after PHI type correction above + function.metadata.value_types = self.value_types.clone(); + // Phase 82-5: lifecycle.rs バグ修正 - terminator の Return のみをチェック // 問題: instructions を先に走査すると、中間値(const void 等)を誤って推論対象にしてしまう // 解決: terminator の Return のみをチェックし、実際の戻り値を正しく推論する