fix(joinir): Phase 132-P2 - Exit PHI ValueId collision fix
Root cause: exit_phi_builder.rs used builder.value_gen.next() (module-level counter) instead of func.next_value_id() (function-level counter) for allocating exit PHI dst. This caused ValueId collisions in functions like: - bb0: %1 = const 0 (initial counter value) - bb3: %1 = phi ... (exit PHI - collision!) The LLVM backend then failed with: "Cannot overwrite PHI dst=1. ValueId namespace collision detected." Fix: Use func.next_value_id() to allocate from the function's local counter, ensuring unique ValueIds within each function. Verified: - Pattern 1 (simple while): VM RC:3, LLVM RC:3 ✅ - Case C (Pattern 5): VM returns 3, LLVM Result: 3 ✅ 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@ -32,8 +32,10 @@ pub(super) fn build_exit_phi(
|
|||||||
// Phase 189-Fix: If we collected return values, create a PHI in exit block
|
// Phase 189-Fix: If we collected return values, create a PHI in exit block
|
||||||
// This merges all return values from JoinIR functions into a single value
|
// This merges all return values from JoinIR functions into a single value
|
||||||
let phi_result = if !exit_phi_inputs.is_empty() {
|
let phi_result = if !exit_phi_inputs.is_empty() {
|
||||||
// Allocate a new ValueId for the PHI result
|
// Phase 132-P2: Use function-level next_value_id() to allocate
|
||||||
let phi_dst = builder.value_gen.next();
|
// Previously used builder.value_gen.next() which is module-level, causing ValueId collisions
|
||||||
|
// Note: We use func.next_value_id() directly since builder.current_function is already borrowed
|
||||||
|
let phi_dst = func.next_value_id();
|
||||||
exit_block.instructions.push(MirInstruction::Phi {
|
exit_block.instructions.push(MirInstruction::Phi {
|
||||||
dst: phi_dst,
|
dst: phi_dst,
|
||||||
inputs: exit_phi_inputs.to_vec(),
|
inputs: exit_phi_inputs.to_vec(),
|
||||||
@ -61,8 +63,10 @@ pub(super) fn build_exit_phi(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate a new ValueId for this carrier's PHI
|
// Phase 132-P2: Use function-level next_value_id() to allocate
|
||||||
let phi_dst = builder.value_gen.next();
|
// Previously used builder.value_gen.next() which is module-level, causing ValueId collisions
|
||||||
|
// Note: We use func.next_value_id() directly since builder.current_function is already borrowed
|
||||||
|
let phi_dst = func.next_value_id();
|
||||||
exit_block.instructions.push(MirInstruction::Phi {
|
exit_block.instructions.push(MirInstruction::Phi {
|
||||||
dst: phi_dst,
|
dst: phi_dst,
|
||||||
inputs: inputs.clone(),
|
inputs: inputs.clone(),
|
||||||
|
|||||||
Reference in New Issue
Block a user