fix(joinir): Phase 132 P1 - k_exit continuation classification fix

Problem: k_exit with TailCall(post_k) was classified as skippable continuation,
causing post_k block to become unreachable.

Root cause:
- Continuation classification was name-based ("join_func_2")
- Skippable continuation check didn't examine function body
- k_exit with tail call to post_k had its block skipped during merge

Solution:
- Check function body structure before classifying as skippable
- Non-skippable pattern: continuation with TailCall to another function
- Properly emit tail call as Jump instruction

Changes:
- src/mir/builder/control_flow/joinir/merge/mod.rs:
  - Add structural check in is_skippable_continuation()
  - Detect TailCall(other_func) pattern
  - Skip only if function is truly empty (1 block, Return only)

- src/mir/builder/control_flow/joinir/merge/instruction_rewriter.rs:
  - Improve k_exit continuation handling
  - Properly rewrite TailCall → Jump for post_k

Test results:
- Phase 132 LLVM EXE: PASS (exit code 3)
- Phase 132 VM: PASS
- Phase 131 regression: PASS
- Phase 97 regression: PASS

Related: Phase 132 loop(true) + post-loop VM/LLVM parity

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
nyash-codex
2025-12-18 21:51:52 +09:00
parent b5d8ace6ab
commit 149e30cae5
4 changed files with 184 additions and 17 deletions

View File

@ -395,7 +395,7 @@ impl MirBuilder {
"Pattern router found no match, trying legacy whitelist",
);
// Delegate to legacy binding path (routing_legacy_binding.rs)
// Phase 132-R0 Task 4: Delegate to legacy binding path (legacy/routing_legacy_binding.rs)
self.cf_loop_joinir_legacy_binding(condition, body, func_name, debug)
}
@ -495,6 +495,7 @@ impl MirBuilder {
exit_bindings,
);
boundary.exit_reconnect_mode = ExitReconnectMode::DirectValue; // Phase 131 P1.5: No PHI
boundary.continuation_func_ids = join_meta.continuation_funcs.clone();
// Merge with boundary - this will populate MergeResult.remapped_exit_values
use crate::mir::builder::control_flow::joinir::merge;