From 7c3f1eafdeb2b7f9fb3f6deee214628f242349f3 Mon Sep 17 00:00:00 2001 From: nyash-codex Date: Wed, 19 Nov 2025 23:53:41 +0900 Subject: [PATCH] loopform: add exit PHI fallthrough for body-local vars --- src/mir/phi_core/loopform_builder.rs | 35 ++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/mir/phi_core/loopform_builder.rs b/src/mir/phi_core/loopform_builder.rs index 875aa53e..510216c8 100644 --- a/src/mir/phi_core/loopform_builder.rs +++ b/src/mir/phi_core/loopform_builder.rs @@ -412,6 +412,41 @@ impl LoopFormBuilder { .push((branch_source_block, carrier.header_phi)); } + // Phase 25.1c/k: Add header fallthrough for body-local variables + // Body-local variables (declared inside loop body) are not in pinned/carriers, + // but they need exit PHI with header fallthrough when accessed after loop. + // Collect all variables from exit_snapshots and add header values for body-locals. + let mut body_local_names: std::collections::HashSet = std::collections::HashSet::new(); + for (_block_id, snapshot) in exit_snapshots { + for var_name in snapshot.keys() { + // Check if this variable is NOT in pinned/carriers (= body-local) + let is_pinned = self.pinned.iter().any(|p| &p.name == var_name); + let is_carrier = self.carriers.iter().any(|c| &c.name == var_name); + if !is_pinned && !is_carrier { + body_local_names.insert(var_name.clone()); + } + } + } + + if debug && !body_local_names.is_empty() { + eprintln!("[DEBUG/exit_phi] Found {} body-local variables in exit_snapshots", body_local_names.len()); + } + + // Get header variable map and add fallthrough for body-locals + for var_name in &body_local_names { + if let Some(header_value) = ops.get_variable_at_block(var_name, self.header_id) { + all_vars + .entry(var_name.clone()) + .or_default() + .push((branch_source_block, header_value)); + if debug { + eprintln!("[DEBUG/exit_phi] Added header fallthrough for body-local '{}': {:?}", var_name, header_value); + } + } else if debug { + eprintln!("[DEBUG/exit_phi] ⚠️ Body-local '{}' not found at header block", var_name); + } + } + // 📦 Hotfix 6: Get actual CFG predecessors for exit block let exit_preds = ops.get_block_predecessors(exit_id); if debug {