fix(phi): if-block PHI reassignment のSSA違反を解消
**問題**: If-block PHI nodes がグローバルValueIdアロケーター使用 → 関数ローカルIDと衝突
- insert_phi() が value_gen.next() 使用
- 関数内で後から割り当てられるValueIdと重複 → SSA違反
**根本原因**:
```rust
// ❌ Before: グローバルアロケーター
let phi_val = self.value_gen.next();
// ✅ After: 関数ローカルアロケーター
let phi_val = if let Some(ref mut f) = self.current_function {
f.next_value_id() // 関数コンテキスト
} else {
self.value_gen.next() // モジュールコンテキスト
};
```
**修正内容**:
1. **insert_phi() 修正** (src/mir/utils/phi_helpers.rs:63-70)
- 関数コンテキストでは f.next_value_id() 使用
- pin_to_slot() / loop builder (e2d061d1) と同じパターン
2. **insert_phi_with_dst() ドキュメント強化** (lines 94-114)
- 正しいValueId割り当て方法を例示
- ❌ 間違い: 常に value_gen.next() 使用
- ✅ 正しい: 関数コンテキスト判定
**テスト結果**:
✅ Simple if-param-method: PASS (SSA違反なし)
✅ Test1/Test3: PASS (regression なし)
⚠️ Test2 (Stage-B): ValueId(22) 残存(別問題: receiver materialization)
**残存問題** (別issue):
- ValueId(22) = receiver materialization 問題
- pin_to_slot / emit_guard / BlockScheduleBox が分散
- 責務の集約が必要(次タスク)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -60,7 +60,14 @@ impl MirBuilder {
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn insert_phi(&mut self, inputs: Vec<(BasicBlockId, ValueId)>) -> Result<ValueId, String> {
|
||||
let phi_val = self.value_gen.next();
|
||||
// Phase 25.1b fix: Use function-local ID allocator to avoid SSA verification failures
|
||||
// This prevents PHI dst ValueIds from colliding with function-local IDs allocated later.
|
||||
// Same pattern as pin_to_slot() and the loop builder fix in e2d061d1.
|
||||
let phi_val = if let Some(ref mut f) = self.current_function {
|
||||
f.next_value_id() // Function context: use local ID allocator
|
||||
} else {
|
||||
self.value_gen.next() // Module context: use global ID allocator
|
||||
};
|
||||
|
||||
// 統一された挿入ロジック(既存パターンと完全互換)
|
||||
if let (Some(func), Some(cur_bb)) = (self.current_function.as_mut(), self.current_block) {
|
||||
@ -84,9 +91,28 @@ impl MirBuilder {
|
||||
/// - 複雑なif式で結果ValueIdを先に確保している場合
|
||||
/// - PHI命令の結果を複数箇所で参照する必要がある場合
|
||||
///
|
||||
/// ## 重要: ValueId割り当てルール
|
||||
/// `dst`は必ず関数コンテキストに適したアロケーターで確保すること:
|
||||
/// ```rust
|
||||
/// // ✅ 正しい: 関数ローカルアロケーター使用
|
||||
/// let result_val = if let Some(ref mut f) = self.current_function {
|
||||
/// f.next_value_id()
|
||||
/// } else {
|
||||
/// self.value_gen.next()
|
||||
/// };
|
||||
/// self.insert_phi_with_dst(result_val, vec![...])?;
|
||||
///
|
||||
/// // ❌ 間違い: 常にグローバルアロケーター使用(SSA違反の原因)
|
||||
/// let result_val = self.value_gen.next();
|
||||
/// ```
|
||||
///
|
||||
/// ## 例
|
||||
/// ```rust
|
||||
/// let result_val = self.value_gen.next();
|
||||
/// let result_val = if let Some(ref mut f) = self.current_function {
|
||||
/// f.next_value_id() // 関数コンテキスト: ローカルID
|
||||
/// } else {
|
||||
/// self.value_gen.next() // モジュールコンテキスト: グローバルID
|
||||
/// };
|
||||
/// // ... 複雑なロジック ...
|
||||
/// self.insert_phi_with_dst(result_val, vec![
|
||||
/// (then_block, then_value),
|
||||
|
||||
Reference in New Issue
Block a user