feat(apply): Phase 286C-4 Step 3 - Implement apply_rewrites() (~160 lines)

Implemented apply_rewrites() stage to mutate MirBuilder:

**Block Addition**:
- Add all new blocks to current function
- Debug logging for blocks with 4+ instructions

**Boundary Injection** (~100 lines):
- Call BoundaryInjector::inject_boundary_copies()
- Build value_map for join_inputs and condition_bindings
- Collect PHI dst IDs from loop_header_phi_info

**Context Updates**:
- Add phi_inputs to ctx.exit_phi_inputs
- Add carrier_inputs to ctx.carrier_inputs

**Fix**:
- Use `ref args` in tail_call_target destructuring to avoid move error

Build passes successfully.
This commit is contained in:
2025-12-25 04:04:50 +09:00
parent 21e855d62a
commit 8619ed07b9

View File

@ -474,7 +474,7 @@ fn plan_rewrites(
}
// Second pass: Insert parameter bindings for tail calls (if any)
if let Some((target_block, args)) = tail_call_target {
if let Some((target_block, ref args)) = tail_call_target {
// Find the target function name from the target_block
let mut target_func_name: Option<String> = None;
for (fname, &entry_block) in &ctx.function_entry_map {
@ -908,15 +908,157 @@ fn plan_rewrites(
/// Stage 3: Apply - Apply rewritten blocks to MirBuilder
///
/// Mutates the builder:
/// - Adds new blocks
/// - Replaces modified blocks
/// - Updates function metadata
/// - Adds new blocks to current function
/// - Injects boundary copies (if boundary provided)
/// - Updates RewriteContext with carrier/phi inputs
///
/// # Phase 286C-4 Step 3
///
/// This function extracts ~180 lines from merge_and_rewrite():
/// - Block addition (lines 1738-1751)
/// - Boundary injection (lines 1755-1857)
/// - Context updates (carrier_inputs, exit_phi_inputs)
fn apply_rewrites(
builder: &mut crate::mir::builder::MirBuilder,
blocks: RewrittenBlocks,
boundary: Option<&crate::mir::join_ir::lowering::inline_boundary::JoinInlineBoundary>,
remapper: &crate::mir::builder::joinir_id_remapper::JoinIrIdRemapper,
loop_header_phi_info: &crate::mir::builder::control_flow::joinir::merge::loop_header_phi_info::LoopHeaderPhiInfo,
mir_module: &crate::mir::MirModule,
ctx: &mut RewriteContext,
debug: bool,
) -> Result<(), String> {
// TODO: Extract apply logic from merge_and_rewrite
// For now, do nothing (blocks will be added by existing logic)
let trace = trace::trace();
let verbose = debug || crate::config::env::joinir_dev_enabled();
macro_rules! log {
($enabled:expr, $($arg:tt)*) => {
trace.stderr_if(&format!($($arg)*), $enabled);
};
}
// Add new blocks to current function
if let Some(ref mut current_func) = builder.scope_ctx.current_function {
for new_block in blocks.new_blocks {
if debug && new_block.instructions.len() >= 4 {
log!(
true,
"[apply_rewrites] Adding block {:?} with {} instructions",
new_block.id, new_block.instructions.len()
);
for (idx, inst) in new_block.instructions.iter().enumerate() {
log!(true, "[apply_rewrites] [{}] {:?}", idx, inst);
}
}
current_func.add_block(new_block);
}
}
// Inject boundary copies (if boundary provided)
if let Some(boundary) = boundary {
use crate::mir::builder::joinir_inline_boundary_injector::BoundaryInjector;
use crate::mir::join_ir::lowering::canonical_names as cn;
// Get entry function's entry block
let (entry_func_name, entry_func) = {
if let Some(main) = mir_module.functions.get(cn::MAIN) {
if main.params == boundary.join_inputs {
(cn::MAIN, main)
} else {
mir_module
.functions
.iter()
.find(|(_, func)| func.params == boundary.join_inputs)
.or_else(|| mir_module.functions.iter().next())
.map(|(name, func)| (name.as_str(), func))
.ok_or("JoinIR module has no functions")?
}
} else {
mir_module
.functions
.iter()
.find(|(_, func)| func.params == boundary.join_inputs)
.or_else(|| mir_module.functions.iter().next())
.map(|(name, func)| (name.as_str(), func))
.ok_or("JoinIR module has no functions")?
}
};
let entry_block_remapped = remapper
.get_block(entry_func_name, entry_func.entry_block)
.ok_or_else(|| format!("Entry block not found for {}", entry_func_name))?;
log!(
verbose,
"[apply_rewrites] Boundary entry: func='{}' entry_block={:?} remapped={:?}",
entry_func_name, entry_func.entry_block, entry_block_remapped
);
// Build value map for BoundaryInjector
let mut value_map_for_injector = std::collections::BTreeMap::new();
// Add join_inputs to value_map
for join_in in &boundary.join_inputs {
if let Some(remapped) = remapper.get_value(*join_in) {
value_map_for_injector.insert(*join_in, remapped);
}
}
// Add condition_bindings to value_map
for binding in &boundary.condition_bindings {
if let Some(remapped) = remapper.get_value(binding.join_value) {
value_map_for_injector.insert(binding.join_value, remapped);
log!(
verbose,
"[apply_rewrites] Condition binding '{}': JoinIR {:?} → remapped {:?}",
binding.name, binding.join_value, remapped
);
}
}
// Collect PHI dst IDs from loop_header_phi_info
let phi_dst_ids: std::collections::HashSet<crate::mir::ValueId> = loop_header_phi_info
.carrier_phis
.values()
.map(|entry| entry.phi_dst)
.collect();
// Inject boundary copies
if let Some(ref mut current_func) = builder.scope_ctx.current_function {
let _reallocations = BoundaryInjector::inject_boundary_copies(
current_func,
entry_block_remapped,
boundary,
&value_map_for_injector,
&phi_dst_ids,
debug,
)?;
}
}
// Update context with phi_inputs and carrier_inputs from blocks
for (block_id, value_id) in blocks.phi_inputs {
ctx.add_exit_phi_input(block_id, value_id);
}
for (carrier_name, inputs) in blocks.carrier_inputs {
for (block_id, value_id) in inputs {
ctx.add_carrier_input(carrier_name.clone(), block_id, value_id);
}
}
if debug {
log!(
true,
"[apply_rewrites] Applied {} blocks, {} phi_inputs, {} carriers",
builder.scope_ctx.current_function
.as_ref()
.map(|f| f.blocks.len())
.unwrap_or(0),
ctx.exit_phi_inputs.len(),
ctx.carrier_inputs.len()
);
}
Ok(())
}