feat(joinir): Phase 33-14 JoinFragmentMeta for expr/carrier separation
Introduces JoinFragmentMeta to distinguish between loop expression results and carrier variable updates, fixing SSA correctness issues. ## Changes ### New: JoinFragmentMeta struct (carrier_info.rs) - `expr_result: Option<ValueId>` - Loop as expression (return loop(...)) - `exit_meta: ExitMeta` - Carrier updates for variable_map - Helper methods: with_expr_result(), carrier_only(), empty() ### Pattern 2 Lowerer Updates - loop_with_break_minimal.rs: Returns (JoinModule, JoinFragmentMeta) - pattern2_with_break.rs: Sets boundary.expr_result from fragment_meta ### instruction_rewriter.rs - Phase 33-14: Only add to exit_phi_inputs when boundary.expr_result is Some - Phase 33-13: MergeResult struct with carrier_inputs map ### JoinInlineBoundary (inline_boundary.rs) - New field: expr_result: Option<ValueId> - All constructors updated with expr_result: None default ## Design Philosophy Previously, exit_phi_inputs mixed expr results with carrier updates, causing: - PHI inputs referencing undefined remapped values - SSA-undef errors in VM execution With JoinFragmentMeta: - expr_result → exit_phi_inputs (generates PHI for expr value) - exit_meta → carrier_inputs (updates variable_map via carrier PHIs) ## Test Results - Pattern 1 (carrier-only): Works correctly (no exit_phi_inputs) - Pattern 2 (expr result): Design complete, SSA-undef fix deferred to Phase 33-15 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -106,7 +106,7 @@ pub(in crate::mir::builder) fn merge_joinir_mir_blocks(
|
||||
remap_values(builder, &used_values, &mut remapper, debug)?;
|
||||
|
||||
// Phase 4: Merge blocks and rewrite instructions
|
||||
let (exit_block_id, exit_phi_inputs) = instruction_rewriter::merge_and_rewrite(
|
||||
let merge_result = instruction_rewriter::merge_and_rewrite(
|
||||
builder,
|
||||
mir_module,
|
||||
&mut remapper,
|
||||
@ -116,21 +116,26 @@ pub(in crate::mir::builder) fn merge_joinir_mir_blocks(
|
||||
debug,
|
||||
)?;
|
||||
|
||||
// Phase 5: Build exit PHI
|
||||
let exit_phi_result_id = exit_phi_builder::build_exit_phi(
|
||||
// Phase 5: Build exit PHI (expr result and carrier PHIs)
|
||||
// Phase 33-13: Now also builds carrier PHIs and returns their mapping
|
||||
let (exit_phi_result_id, carrier_phis) = exit_phi_builder::build_exit_phi(
|
||||
builder,
|
||||
exit_block_id,
|
||||
&exit_phi_inputs,
|
||||
merge_result.exit_block_id,
|
||||
&merge_result.exit_phi_inputs,
|
||||
&merge_result.carrier_inputs,
|
||||
debug,
|
||||
)?;
|
||||
|
||||
// Phase 6: Reconnect boundary (if specified)
|
||||
// Phase 197-B: Pass remapper to enable per-carrier exit value lookup
|
||||
// Phase 33-10-Refactor-P3: Delegate to ExitLineOrchestrator
|
||||
// Phase 33-13: Pass carrier_phis for proper variable_map update
|
||||
if let Some(boundary) = boundary {
|
||||
exit_line::ExitLineOrchestrator::execute(builder, boundary, &remapper, debug)?;
|
||||
exit_line::ExitLineOrchestrator::execute(builder, boundary, &carrier_phis, debug)?;
|
||||
}
|
||||
|
||||
let exit_block_id = merge_result.exit_block_id;
|
||||
|
||||
// Jump from current block to entry function's entry block
|
||||
let (entry_func_name, entry_func) = mir_module
|
||||
.functions
|
||||
|
||||
Reference in New Issue
Block a user