refactor(joinir): Extract legacy binding path to routing_legacy_binding.rs
Phase 179-A Step 2: Separate LoopFrontendBinding JSON construction logic into dedicated module for better organization. Changes: - New file: routing_legacy_binding.rs (223 lines) - routing.rs: cf_loop_joinir_impl() simplified to 15 lines (delegates to legacy path) - Routing now clearly separates pattern-based vs. legacy binding paths Benefits: - Clear separation of concerns (pattern router vs. legacy whitelist) - routing.rs reduced from 364 to 146 lines (60% reduction) - Legacy path isolated for future deprecation
This commit is contained in:
@ -79,6 +79,13 @@ impl ExitLineReconnector {
|
||||
carrier_phis: &BTreeMap<String, ValueId>,
|
||||
debug: bool,
|
||||
) -> Result<(), String> {
|
||||
// Phase 177-STRUCT: Always log for debugging
|
||||
eprintln!(
|
||||
"[DEBUG-177/reconnect] ExitLineReconnector: {} exit bindings, {} carrier PHIs",
|
||||
boundary.exit_bindings.len(),
|
||||
carrier_phis.len()
|
||||
);
|
||||
|
||||
// Early return for empty exit_bindings
|
||||
if boundary.exit_bindings.is_empty() {
|
||||
if debug {
|
||||
@ -110,12 +117,11 @@ impl ExitLineReconnector {
|
||||
// Update variable_map with PHI dst
|
||||
if let Some(&phi_value) = phi_dst {
|
||||
if let Some(var_vid) = builder.variable_map.get_mut(&binding.carrier_name) {
|
||||
if debug {
|
||||
eprintln!(
|
||||
"[cf_loop/joinir/exit_line] ExitLineReconnector: Updated variable_map['{}'] {:?} → {:?} (PHI dst)",
|
||||
binding.carrier_name, var_vid, phi_value
|
||||
);
|
||||
}
|
||||
// Phase 177-STRUCT: Always log for debugging
|
||||
eprintln!(
|
||||
"[DEBUG-177/reconnect] Updated variable_map['{}'] {:?} → {:?}",
|
||||
binding.carrier_name, *var_vid, phi_value
|
||||
);
|
||||
*var_vid = phi_value;
|
||||
} else if debug {
|
||||
eprintln!(
|
||||
|
||||
@ -74,12 +74,11 @@ pub(super) fn build_exit_phi(
|
||||
|
||||
carrier_phis.insert(carrier_name.clone(), phi_dst);
|
||||
|
||||
if debug {
|
||||
eprintln!(
|
||||
"[cf_loop/joinir] Exit block PHI (carrier '{}'): {:?} = phi {:?}",
|
||||
carrier_name, phi_dst, inputs
|
||||
);
|
||||
}
|
||||
// DEBUG-177: Always log exit block PHI creation for carrier debugging
|
||||
eprintln!(
|
||||
"[DEBUG-177] Exit block PHI (carrier '{}'): {:?} = phi {:?}",
|
||||
carrier_name, phi_dst, inputs
|
||||
);
|
||||
}
|
||||
|
||||
func.add_block(exit_block);
|
||||
|
||||
@ -604,12 +604,11 @@ pub(super) fn merge_and_rewrite(
|
||||
carrier_inputs.entry(binding.carrier_name.clone())
|
||||
.or_insert_with(Vec::new)
|
||||
.push((new_block_id, phi_dst));
|
||||
if debug {
|
||||
eprintln!(
|
||||
"[cf_loop/joinir] Phase 33-16: Using header PHI dst {:?} for carrier '{}'",
|
||||
phi_dst, binding.carrier_name
|
||||
);
|
||||
}
|
||||
// DEBUG-177: Always log carrier collection
|
||||
eprintln!(
|
||||
"[DEBUG-177] Phase 33-16: Collecting carrier '{}': from {:?} using header PHI {:?}",
|
||||
binding.carrier_name, new_block_id, phi_dst
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -84,6 +84,8 @@ impl LoopHeaderPhiBuilder {
|
||||
latch_incoming: None,
|
||||
},
|
||||
);
|
||||
// Phase 177-STRUCT-2: Record insertion order
|
||||
info.carrier_order.push(loop_var_name.to_string());
|
||||
|
||||
if debug {
|
||||
eprintln!(
|
||||
@ -103,6 +105,8 @@ impl LoopHeaderPhiBuilder {
|
||||
latch_incoming: None,
|
||||
},
|
||||
);
|
||||
// Phase 177-STRUCT-2: Record insertion order
|
||||
info.carrier_order.push(name.clone());
|
||||
|
||||
if debug {
|
||||
eprintln!(
|
||||
|
||||
@ -29,6 +29,14 @@ pub struct LoopHeaderPhiInfo {
|
||||
/// of this carrier during loop iteration.
|
||||
pub carrier_phis: BTreeMap<String, CarrierPhiEntry>,
|
||||
|
||||
/// Phase 177-STRUCT-2: Carrier names in insertion order
|
||||
///
|
||||
/// Preserves the order in which carriers were added (matches exit_bindings order).
|
||||
/// Used for index-based matching with loop_step params.
|
||||
///
|
||||
/// Order: [loop_var, carrier1, carrier2, ...]
|
||||
pub carrier_order: Vec<String>,
|
||||
|
||||
/// Expression result PHI dst (if loop is used as expression)
|
||||
///
|
||||
/// For Pattern 2 (joinir_min_loop), this is the same as the loop
|
||||
@ -55,10 +63,25 @@ impl LoopHeaderPhiInfo {
|
||||
Self {
|
||||
header_block,
|
||||
carrier_phis: BTreeMap::new(),
|
||||
carrier_order: Vec::new(),
|
||||
expr_result_phi: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Phase 177-STRUCT-2: Get carrier name at index (in insertion order)
|
||||
///
|
||||
/// Used for matching loop_step params by index.
|
||||
pub fn get_carrier_at_index(&self, idx: usize) -> Option<&str> {
|
||||
self.carrier_order.get(idx).map(|s| s.as_str())
|
||||
}
|
||||
|
||||
/// Phase 177-STRUCT-2: Get PHI entry at index (in insertion order)
|
||||
pub fn get_entry_at_index(&self, idx: usize) -> Option<&CarrierPhiEntry> {
|
||||
self.carrier_order
|
||||
.get(idx)
|
||||
.and_then(|name| self.carrier_phis.get(name))
|
||||
}
|
||||
|
||||
/// Get the PHI dst for a carrier variable
|
||||
pub fn get_carrier_phi(&self, name: &str) -> Option<ValueId> {
|
||||
self.carrier_phis.get(name).map(|e| e.phi_dst)
|
||||
|
||||
@ -340,12 +340,11 @@ pub(in crate::mir::builder) fn merge_joinir_mir_blocks(
|
||||
}
|
||||
|
||||
// Map loop_step's parameters
|
||||
if debug {
|
||||
eprintln!(
|
||||
"[cf_loop/joinir] Phase 33-21: function_params keys: {:?}",
|
||||
function_params.keys().collect::<Vec<_>>()
|
||||
);
|
||||
}
|
||||
// DEBUG-177: Always log function_params keys to diagnose multi-carrier issue
|
||||
eprintln!(
|
||||
"[DEBUG-177] Phase 33-21: function_params keys: {:?}",
|
||||
function_params.keys().collect::<Vec<_>>()
|
||||
);
|
||||
if function_params.get(loop_step_func_name).is_none() {
|
||||
eprintln!(
|
||||
"[cf_loop/joinir] WARNING: function_params.get('{}') returned None. Available keys: {:?}",
|
||||
@ -354,32 +353,56 @@ pub(in crate::mir::builder) fn merge_joinir_mir_blocks(
|
||||
);
|
||||
}
|
||||
if let Some(loop_step_params) = function_params.get(loop_step_func_name) {
|
||||
if debug {
|
||||
eprintln!(
|
||||
"[cf_loop/joinir] Phase 33-21: loop_step ({}) params: {:?}",
|
||||
loop_step_func_name, loop_step_params
|
||||
);
|
||||
}
|
||||
// Map loop_step's parameters to header PHI dsts
|
||||
// loop_step params: [i_param, carrier1_param, ...]
|
||||
// carrier_phis: [("i", entry), ("sum", entry), ...]
|
||||
for (idx, (carrier_name, entry)) in phi_info.carrier_phis.iter().enumerate() {
|
||||
if let Some(&loop_step_param) = loop_step_params.get(idx) {
|
||||
// Phase 177-3: Don't override condition_bindings
|
||||
if condition_binding_ids.contains(&loop_step_param) {
|
||||
// DEBUG-177: Always log loop_step params
|
||||
eprintln!(
|
||||
"[DEBUG-177] Phase 33-21: loop_step ({}) params: {:?}",
|
||||
loop_step_func_name, loop_step_params
|
||||
);
|
||||
// Phase 177-FIX: Process loop_step params but skip if already mapped
|
||||
//
|
||||
// We use a name-based approach: for each carrier_phi, check if
|
||||
// its join_value was already set in Phase 177-3-B (body-only carriers).
|
||||
// Only process loop_step params for carriers NOT already handled.
|
||||
for loop_step_param in loop_step_params {
|
||||
// Phase 177-3: Don't override condition_bindings
|
||||
if condition_binding_ids.contains(loop_step_param) {
|
||||
eprintln!(
|
||||
"[DEBUG-177] Phase 177-FIX: Skipping condition_binding {:?}",
|
||||
loop_step_param
|
||||
);
|
||||
continue;
|
||||
}
|
||||
// Find which carrier this param belongs to by matching join_value
|
||||
// Check if this param was already handled by Phase 177-3-B
|
||||
let already_mapped = boundary.condition_bindings.iter().any(|cb| {
|
||||
cb.join_value == *loop_step_param &&
|
||||
phi_info.carrier_phis.iter().any(|(name, _)| name == &cb.name)
|
||||
});
|
||||
if already_mapped {
|
||||
eprintln!(
|
||||
"[DEBUG-177] Phase 177-FIX: Skipping {:?} (already mapped by Phase 177-3-B)",
|
||||
loop_step_param
|
||||
);
|
||||
continue;
|
||||
}
|
||||
// Phase 177-STRUCT-2: Use carrier_order for index-based matching
|
||||
//
|
||||
// Problem: BTreeMap iterates in alphabetical order, but JoinIR
|
||||
// generates params in exit_bindings order.
|
||||
//
|
||||
// Solution: Use carrier_order (Vec<String>) which preserves insertion order.
|
||||
if let Some(param_idx) = loop_step_params.iter().position(|p| p == loop_step_param) {
|
||||
// Map params[i] to carrier_order[i]
|
||||
if let (Some(carrier_name), Some(entry)) = (
|
||||
phi_info.get_carrier_at_index(param_idx),
|
||||
phi_info.get_entry_at_index(param_idx),
|
||||
) {
|
||||
eprintln!(
|
||||
"[cf_loop/joinir] Phase 177-3: Skipping override for condition_binding {:?} ('{}')",
|
||||
loop_step_param, carrier_name
|
||||
"[DEBUG-177] Phase 177-STRUCT-2: REMAP loop_step param[{}] {:?} → {:?} (carrier '{}')",
|
||||
param_idx, loop_step_param, entry.phi_dst, carrier_name
|
||||
);
|
||||
continue;
|
||||
remapper.set_value(*loop_step_param, entry.phi_dst);
|
||||
}
|
||||
if debug {
|
||||
eprintln!(
|
||||
"[cf_loop/joinir] Phase 33-21: REMAP loop_step param {:?} → {:?} ('{}')",
|
||||
loop_step_param, entry.phi_dst, carrier_name
|
||||
);
|
||||
}
|
||||
remapper.set_value(loop_step_param, entry.phi_dst);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -403,10 +426,15 @@ pub(in crate::mir::builder) fn merge_joinir_mir_blocks(
|
||||
);
|
||||
}
|
||||
}
|
||||
for (idx, (carrier_name, entry)) in phi_info.carrier_phis.iter().enumerate() {
|
||||
// Phase 177-STRUCT-2: Use carrier_order for deterministic iteration
|
||||
for (idx, carrier_name) in phi_info.carrier_order.iter().enumerate() {
|
||||
if carrier_name == loop_var_name {
|
||||
continue;
|
||||
}
|
||||
let entry = match phi_info.carrier_phis.get(carrier_name) {
|
||||
Some(e) => e,
|
||||
None => continue,
|
||||
};
|
||||
let join_value_id = ValueId(idx as u32);
|
||||
// Phase 177-3: Don't override condition_bindings
|
||||
if !condition_binding_ids.contains(&join_value_id) {
|
||||
|
||||
Reference in New Issue
Block a user