diff --git a/src/mir/builder/control_flow.rs b/src/mir/builder/control_flow.rs index 4e8540b3..3c06d701 100644 --- a/src/mir/builder/control_flow.rs +++ b/src/mir/builder/control_flow.rs @@ -514,6 +514,9 @@ impl super::MirBuilder { // Remap instructions (Phase 189: Convert inter-function Calls to control flow) let mut found_tail_call = false; + let mut tail_call_target: Option<(BasicBlockId, Vec)> = None; + + // First pass: Process all instructions, identify tail calls for inst in &old_block.instructions { // Phase 189: Skip Const String instructions that define function names if let MirInstruction::Const { dst, value } = inst { @@ -527,26 +530,30 @@ impl super::MirBuilder { } } - // Phase 189: Convert Call to Jump terminator - if let MirInstruction::Call { func, .. } = inst { + // Phase 189: Detect tail calls and save parameters + if let MirInstruction::Call { func, args, .. } = inst { if let Some(func_name) = value_to_func_name.get(func) { if let Some(&target_block) = function_entry_map.get(func_name) { + // This is a tail call - save info and skip the Call instruction itself + let remapped_args: Vec = args + .iter() + .map(|&v| value_map.get(&v).copied().unwrap_or(v)) + .collect(); + tail_call_target = Some((target_block, remapped_args)); + found_tail_call = true; + if debug { eprintln!( - "[cf_loop/joinir] Call(name='{}') → Jump terminator to {:?}", - func_name, target_block + "[cf_loop/joinir] Detected tail call to '{}' (args={:?}), will convert to Jump", + func_name, args ); } - // Set the terminator to Jump and stop processing this block - new_block.terminator = Some(MirInstruction::Jump { - target: target_block, - }); - found_tail_call = true; - break; // Don't process further instructions + continue; // Skip the Call instruction itself } } } + // Process regular instructions let remapped = Self::remap_joinir_instruction( inst, &value_map, @@ -555,8 +562,51 @@ impl super::MirBuilder { &value_to_func_name, debug, ); + + if debug { + match inst { + MirInstruction::BoxCall { .. } => { + eprintln!("[cf_loop/joinir] Adding BoxCall to block {:?}: {:?}", new_block_id, inst); + } + _ => {} + } + } + new_block.instructions.push(remapped); } + + // Second pass: Insert parameter bindings for tail calls + if let Some((target_block, args)) = tail_call_target { + if debug { + eprintln!( + "[cf_loop/joinir] Inserting param bindings for tail call to {:?}", + target_block + ); + } + + // Insert Copy instructions for parameter binding + for (i, arg_val_remapped) in args.iter().enumerate() { + let param_val_original = ValueId(i as u32); + if let Some(¶m_val_remapped) = value_map.get(¶m_val_original) { + new_block.instructions.push(MirInstruction::Copy { + dst: param_val_remapped, + src: *arg_val_remapped, + }); + + if debug { + eprintln!( + "[cf_loop/joinir] Param binding: arg {:?} → param {:?}", + arg_val_remapped, param_val_remapped + ); + } + } + } + + // Set terminator to Jump + new_block.terminator = Some(MirInstruction::Jump { + target: target_block, + }); + } new_block.instruction_spans = old_block.instruction_spans.clone(); // Remap terminator (convert Return → Jump to exit) if not already set by tail call