diff --git a/src/mir/builder/control_flow/joinir/merge/instruction_rewriter.rs b/src/mir/builder/control_flow/joinir/merge/instruction_rewriter.rs index 4a1eb29e..4bdcdaac 100644 --- a/src/mir/builder/control_flow/joinir/merge/instruction_rewriter.rs +++ b/src/mir/builder/control_flow/joinir/merge/instruction_rewriter.rs @@ -27,6 +27,8 @@ use std::collections::BTreeSet; use super::rewriter::helpers::is_skippable_continuation; // Phase 260 P0.1 Step 4: Import from type_propagation module use super::rewriter::type_propagation::propagate_value_type_for_inst; +// Phase 260 P0.1 Step 5: Import from terminator module +use super::rewriter::terminator::{apply_remapped_terminator, remap_branch, remap_jump}; /// Phase 4: Merge ALL functions and rewrite instructions /// @@ -899,16 +901,7 @@ pub(super) fn merge_and_rewrite( // Remap terminator (convert Return → Jump to exit) if not already set by tail call if !found_tail_call { if let Some(ref term) = old_block.terminator { - let remap_edge_args = |edge_args: &Option| { - edge_args.as_ref().map(|args| crate::mir::EdgeArgs { - layout: args.layout, - values: args - .values - .iter() - .map(|&v| remapper.remap_value(v)) - .collect(), - }) - }; + // Phase 260 P0.1 Step 5: Use terminator module for Jump/Branch remapping let mut remapped_term: Option = None; match term { MirInstruction::Return { value } => { @@ -1054,17 +1047,14 @@ pub(super) fn merge_and_rewrite( } } MirInstruction::Jump { target, edge_args } => { - // Phase 189 FIX: Remap block ID for Jump - // Phase 259 P0 FIX: Check skipped_entry_redirects first (for k_exit blocks) - let remapped_target = skipped_entry_redirects - .get(target) - .or_else(|| local_block_map.get(target)) - .copied() - .unwrap_or(*target); - remapped_term = Some(MirInstruction::Jump { - target: remapped_target, - edge_args: remap_edge_args(edge_args), - }); + // Phase 260 P0.1 Step 5: Use terminator::remap_jump() + remapped_term = Some(remap_jump( + &remapper, + *target, + edge_args, + &skipped_entry_redirects, + &local_block_map, + )); } MirInstruction::Branch { condition, @@ -1073,57 +1063,23 @@ pub(super) fn merge_and_rewrite( then_edge_args, else_edge_args, } => { - // Phase 189 FIX: Remap block IDs AND condition ValueId for Branch - // Phase 259 P0 FIX: Check skipped_entry_redirects first (for k_exit blocks) - let remapped_then = skipped_entry_redirects - .get(then_bb) - .or_else(|| local_block_map.get(then_bb)) - .copied() - .unwrap_or(*then_bb); - let remapped_else = skipped_entry_redirects - .get(else_bb) - .or_else(|| local_block_map.get(else_bb)) - .copied() - .unwrap_or(*else_bb); - remapped_term = Some(MirInstruction::Branch { - condition: remapper.remap_value(*condition), - then_bb: remapped_then, - else_bb: remapped_else, - then_edge_args: remap_edge_args(then_edge_args), - else_edge_args: remap_edge_args(else_edge_args), - }); + // Phase 260 P0.1 Step 5: Use terminator::remap_branch() + remapped_term = Some(remap_branch( + &remapper, + *condition, + *then_bb, + *else_bb, + then_edge_args, + else_edge_args, + &skipped_entry_redirects, + &local_block_map, + )); } _ => remapped_term = Some(remapper.remap_instruction(term)), } + // Phase 260 P0.1 Step 5: Use terminator::apply_remapped_terminator() if let Some(term) = remapped_term { - match term { - MirInstruction::Jump { target, edge_args } => { - if edge_args.is_some() { - new_block.set_jump_with_edge_args(target, edge_args); - } else { - new_block.set_terminator(MirInstruction::Jump { - target, - edge_args: None, - }); - } - } - MirInstruction::Branch { - condition, - then_bb, - then_edge_args, - else_bb, - else_edge_args, - } => { - new_block.set_branch_with_edge_args( - condition, - then_bb, - then_edge_args, - else_bb, - else_edge_args, - ); - } - _ => new_block.set_terminator(term), - } + apply_remapped_terminator(&mut new_block, term); } } } diff --git a/src/mir/builder/control_flow/joinir/merge/rewriter/mod.rs b/src/mir/builder/control_flow/joinir/merge/rewriter/mod.rs index 04100521..372a38a1 100644 --- a/src/mir/builder/control_flow/joinir/merge/rewriter/mod.rs +++ b/src/mir/builder/control_flow/joinir/merge/rewriter/mod.rs @@ -22,16 +22,18 @@ // - logging: DEBUG-177 style verbose logs ✅ // - helpers: Small pure functions (is_skippable_continuation) ✅ // - type_propagation: Type propagation (propagate_value_type_for_inst) ✅ +// - terminator: Jump/Branch remapping ✅ // Future modules (pending): -// - terminator: Branch/Jump/Return remapping -// - exit_line: ExitLine/exit-phi wiring -// - carriers: loop_invariants, exit_bindings +// - exit_collection: Return→Jump conversion + exit value collection +// - k_exit_handling: k_exit special handling +// - tail_call: Parameter binding + latch incoming // // For now, re-export from parent to maintain compatibility. pub(super) mod helpers; // Phase 260 P0.1 Step 3: Helpers extracted ✅ pub(super) mod logging; // Phase 260 P0.1 Step 2: Logging extracted ✅ +pub(super) mod terminator; // Phase 260 P0.1 Step 5: Terminator remapping extracted ✅ pub(super) mod type_propagation; // Phase 260 P0.1 Step 4: Type propagation extracted ✅ // Re-export public API diff --git a/src/mir/builder/control_flow/joinir/merge/rewriter/terminator.rs b/src/mir/builder/control_flow/joinir/merge/rewriter/terminator.rs new file mode 100644 index 00000000..ee0fb3cb --- /dev/null +++ b/src/mir/builder/control_flow/joinir/merge/rewriter/terminator.rs @@ -0,0 +1,136 @@ +//! Terminator remapping utilities +//! +//! Phase 260 P0.1 Step 5: Extracted from instruction_rewriter.rs +//! Handles Jump/Branch block ID and ValueId remapping. + +use crate::mir::builder::joinir_id_remapper::JoinIrIdRemapper; +use crate::mir::{BasicBlockId, MirInstruction, ValueId}; +use std::collections::BTreeMap; + +/// Remap edge_args ValueIds using remapper +/// +/// Helper function used by Jump/Branch remapping to remap edge argument values +/// from JoinIR value space to HOST value space. +fn remap_edge_args( + remapper: &JoinIrIdRemapper, + edge_args: &Option, +) -> Option { + edge_args.as_ref().map(|args| crate::mir::EdgeArgs { + layout: args.layout, + values: args + .values + .iter() + .map(|&v| remapper.remap_value(v)) + .collect(), + }) +} + +/// Remap Jump instruction +/// +/// Applies block ID remapping (skipped_entry_redirects + local_block_map) and +/// edge_args ValueId remapping. +/// +/// # Phase 259 P0 FIX +/// +/// Checks skipped_entry_redirects FIRST (for k_exit blocks that were skipped +/// during merge). Fallback to local_block_map if not found. +pub(in crate::mir::builder::control_flow::joinir::merge) fn remap_jump( + remapper: &JoinIrIdRemapper, + target: BasicBlockId, + edge_args: &Option, + skipped_entry_redirects: &BTreeMap, + local_block_map: &BTreeMap, +) -> MirInstruction { + let remapped_target = skipped_entry_redirects + .get(&target) + .or_else(|| local_block_map.get(&target)) + .copied() + .unwrap_or(target); + + MirInstruction::Jump { + target: remapped_target, + edge_args: remap_edge_args(remapper, edge_args), + } +} + +/// Remap Branch instruction +/// +/// Applies block ID remapping (skipped_entry_redirects + local_block_map) for +/// both then/else branches, condition ValueId remapping, and edge_args remapping. +/// +/// # Phase 259 P0 FIX +/// +/// Checks skipped_entry_redirects FIRST (for k_exit blocks). +pub(in crate::mir::builder::control_flow::joinir::merge) fn remap_branch( + remapper: &JoinIrIdRemapper, + condition: ValueId, + then_bb: BasicBlockId, + else_bb: BasicBlockId, + then_edge_args: &Option, + else_edge_args: &Option, + skipped_entry_redirects: &BTreeMap, + local_block_map: &BTreeMap, +) -> MirInstruction { + let remapped_then = skipped_entry_redirects + .get(&then_bb) + .or_else(|| local_block_map.get(&then_bb)) + .copied() + .unwrap_or(then_bb); + + let remapped_else = skipped_entry_redirects + .get(&else_bb) + .or_else(|| local_block_map.get(&else_bb)) + .copied() + .unwrap_or(else_bb); + + MirInstruction::Branch { + condition: remapper.remap_value(condition), + then_bb: remapped_then, + else_bb: remapped_else, + then_edge_args: remap_edge_args(remapper, then_edge_args), + else_edge_args: remap_edge_args(remapper, else_edge_args), + } +} + +/// Apply remapped terminator to block +/// +/// Handles special cases for Jump/Branch (set_jump_with_edge_args / +/// set_branch_with_edge_args) vs other terminators (set_terminator). +/// +/// # Why Special Handling? +/// +/// Jump/Branch with edge_args need special setters to maintain invariants +/// (successors, predecessors, jump_args synchronization). +pub(in crate::mir::builder::control_flow::joinir::merge) fn apply_remapped_terminator( + block: &mut crate::mir::BasicBlock, + term: MirInstruction, +) { + match term { + MirInstruction::Jump { target, edge_args } => { + if edge_args.is_some() { + block.set_jump_with_edge_args(target, edge_args); + } else { + block.set_terminator(MirInstruction::Jump { + target, + edge_args: None, + }); + } + } + MirInstruction::Branch { + condition, + then_bb, + then_edge_args, + else_bb, + else_edge_args, + } => { + block.set_branch_with_edge_args( + condition, + then_bb, + then_edge_args, + else_bb, + else_edge_args, + ); + } + _ => block.set_terminator(term), + } +}