feat(joinir): Phase 33-16 Loop Header PHI SSOT with TailCallKind refactoring
## Problem - joinir_min_loop.hako returned 0 instead of expected 2 - Entry block's tail call was redirected to itself (bb4 → bb4 self-loop) - JoinIR function parameters lack SSA definition when inlined ## Solution - Distinguish entry calls from back edges using TailCallKind enum - Entry block (LoopEntry) stays at target, back edges redirect to header PHI - Added explicit classification: LoopEntry, BackEdge, ExitJump ## Key Changes - instruction_rewriter.rs: TailCallKind enum + classify_tail_call() - Renamed is_entry_func_entry_block → is_loop_entry_point (clearer intent) - loop_header_phi_builder.rs: New module for header PHI generation - joinir_inline_boundary_injector.rs: Skip loop var Copy when header PHI handles it ## Verified - joinir_min_loop.hako: returns 2 ✅ - NYASH_SSA_UNDEF_DEBUG: no undefined errors ✅ 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -232,6 +232,12 @@ pub struct JoinInlineBoundary {
|
||||
///
|
||||
/// Here, `expr_result = None` because the loop doesn't return a value.
|
||||
pub expr_result: Option<crate::mir::ValueId>,
|
||||
|
||||
/// Phase 33-16: Loop variable name (for LoopHeaderPhiBuilder)
|
||||
///
|
||||
/// The name of the loop control variable (e.g., "i" in `loop(i < 3)`).
|
||||
/// Used to track which PHI corresponds to the loop variable.
|
||||
pub loop_var_name: Option<String>,
|
||||
}
|
||||
|
||||
impl JoinInlineBoundary {
|
||||
@ -257,6 +263,7 @@ impl JoinInlineBoundary {
|
||||
condition_inputs: vec![], // Phase 171: Default to empty (deprecated)
|
||||
condition_bindings: vec![], // Phase 171-fix: Default to empty
|
||||
expr_result: None, // Phase 33-14: Default to carrier-only pattern
|
||||
loop_var_name: None, // Phase 33-16
|
||||
}
|
||||
}
|
||||
|
||||
@ -297,6 +304,7 @@ impl JoinInlineBoundary {
|
||||
condition_inputs: vec![], // Phase 171: Default to empty (deprecated)
|
||||
condition_bindings: vec![], // Phase 171-fix: Default to empty
|
||||
expr_result: None, // Phase 33-14
|
||||
loop_var_name: None, // Phase 33-16
|
||||
}
|
||||
}
|
||||
|
||||
@ -333,6 +341,7 @@ impl JoinInlineBoundary {
|
||||
condition_inputs: vec![], // Phase 171: Default to empty (deprecated)
|
||||
condition_bindings: vec![], // Phase 171-fix: Default to empty
|
||||
expr_result: None, // Phase 33-14
|
||||
loop_var_name: None, // Phase 33-16
|
||||
}
|
||||
}
|
||||
|
||||
@ -391,6 +400,7 @@ impl JoinInlineBoundary {
|
||||
condition_inputs: vec![], // Phase 171: Default to empty (deprecated)
|
||||
condition_bindings: vec![], // Phase 171-fix: Default to empty
|
||||
expr_result: None, // Phase 33-14
|
||||
loop_var_name: None, // Phase 33-16
|
||||
}
|
||||
}
|
||||
|
||||
@ -435,6 +445,7 @@ impl JoinInlineBoundary {
|
||||
condition_inputs,
|
||||
condition_bindings: vec![], // Phase 171-fix: Will be populated by new constructor
|
||||
expr_result: None, // Phase 33-14
|
||||
loop_var_name: None, // Phase 33-16
|
||||
}
|
||||
}
|
||||
|
||||
@ -483,6 +494,7 @@ impl JoinInlineBoundary {
|
||||
condition_inputs,
|
||||
condition_bindings: vec![], // Phase 171-fix: Will be populated by new constructor
|
||||
expr_result: None, // Phase 33-14
|
||||
loop_var_name: None, // Phase 33-16
|
||||
}
|
||||
}
|
||||
|
||||
@ -538,6 +550,7 @@ impl JoinInlineBoundary {
|
||||
condition_inputs: vec![], // Deprecated, use condition_bindings instead
|
||||
condition_bindings,
|
||||
expr_result: None, // Phase 33-14
|
||||
loop_var_name: None, // Phase 33-16
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user