feat(joinir): Phase 246-EX Part 2 - Exit PHI & step scheduling fixes

Phase 246-EX Part 2 completes the _atoi JoinIR integration:

Key fixes:
- Exit PHI connection: ExitLineReconnector now correctly uses exit PHI dsts
- Jump args preservation: BasicBlock.jump_args field stores JoinIR exit values
- instruction_rewriter: Reads jump_args, remaps JoinIR→HOST values by carrier order
- step_schedule.rs: New module for body-local init step ordering

Files changed:
- reconnector.rs: Exit PHI connection improvements
- instruction_rewriter.rs: Jump args reading & carrier value mapping
- loop_with_break_minimal.rs: Refactored step scheduling
- step_schedule.rs: NEW - Step ordering logic extracted

Tests: 931/931 PASS (no regression)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
nyash-codex
2025-12-11 16:46:53 +09:00
parent e356524b0a
commit eb00d97fdb
16 changed files with 802 additions and 219 deletions

View File

@ -5,6 +5,7 @@ use crate::mir::builder::MirBuilder;
use crate::mir::ValueId;
use super::super::trace;
use crate::mir::loop_pattern_detection::error_messages;
use crate::mir::join_ir::lowering::carrier_info::CarrierInit;
/// Phase 185-2: Collect body-local variable declarations from loop body
///
@ -511,6 +512,7 @@ impl MirBuilder {
carrier_updates.contains_key(&carrier.name)
|| carrier.role == CarrierRole::ConditionOnly
|| carrier.init == CarrierInit::FromHost // Phase 247-EX
|| carrier.init == CarrierInit::LoopLocalZero // Phase 247-EX: Derived carrier (digit_value)
});
eprintln!(
@ -524,18 +526,28 @@ impl MirBuilder {
// need to be added to ConditionEnv with their initial values.
for carrier in &carrier_info.carriers {
if env.get(&carrier.name).is_none() {
// Allocate a new JoinIR ValueId for this carrier
let join_value = alloc_join_value();
// Use the carrier's assigned param ID when available to keep IDs aligned
let join_value = carrier
.join_id
.unwrap_or_else(|| alloc_join_value());
// Add to ConditionEnv
env.insert(carrier.name.clone(), join_value);
// Add to condition_bindings for later processing
condition_bindings.push(ConditionBinding {
name: carrier.name.clone(),
host_value: carrier.host_id,
join_value,
});
// Loop-local carriers (e.g., digit_value) have no host slot; skip binding to avoid bogus copies.
if carrier.init != CarrierInit::LoopLocalZero {
condition_bindings.push(ConditionBinding {
name: carrier.name.clone(),
host_value: carrier.host_id,
join_value,
});
} else {
eprintln!(
"[cf_loop/pattern2] Phase 247-EX: Skipping host binding for loop-local carrier '{}' (init=LoopLocalZero)",
carrier.name
);
}
eprintln!(
"[cf_loop/pattern2] Phase 176-5: Added body-only carrier '{}' to ConditionEnv: HOST {:?} → JoinIR {:?}",