refactor(joinir): L-2.2 Step-1 - Unify Stage-B lowering via LoopToJoinLowerer

Stage-B minimal JoinIR lowering統一化:

1. Add Case-A helpers to loop_to_join.rs:
   - lower_case_a_for_stageb_body (StageBBodyExtractorBox.build_body_src/2)
   - lower_case_a_for_stageb_funcscanner (StageBFuncScannerBox.scan_all_boxes/1)

2. Update stageb_body.rs and stageb_funcscanner.rs:
   - Replace manual LoopForm construction with construct_simple_while_loopform
   - Route through LoopToJoinLowerer like other Case-A functions
   - Remove unused imports (LoopForm, MirQuery)

Now all 6 JoinIR lowering modules use the same unified pattern:
- skip_ws, trim, append_defs, stage1_resolver, stageb_body, stageb_funcscanner
All route through LoopToJoinLowerer for consistency.

Test results: JSON snapshot 6/6 PASS

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
nyash-codex
2025-11-26 10:47:35 +09:00
parent 853cb36800
commit 9d769e9217
3 changed files with 64 additions and 30 deletions

View File

@ -339,6 +339,26 @@ impl LoopToJoinLowerer {
) -> Option<JoinModule> { ) -> Option<JoinModule> {
self.lower(func, loop_form, Some("Stage1UsingResolverBox.resolve_for_source/5")) self.lower(func, loop_form, Some("Stage1UsingResolverBox.resolve_for_source/5"))
} }
/// Case-A 汎用 lowerer の「StageBBodyExtractorBox.build_body_src/2 用」薄いラッパー。
/// 実際のロジックは `lower` に集約されている。
pub fn lower_case_a_for_stageb_body(
&self,
func: &MirFunction,
loop_form: &LoopForm,
) -> Option<JoinModule> {
self.lower(func, loop_form, Some("StageBBodyExtractorBox.build_body_src/2"))
}
/// Case-A 汎用 lowerer の「StageBFuncScannerBox.scan_all_boxes/1 用」薄いラッパー。
/// 実際のロジックは `lower` に集約されている。
pub fn lower_case_a_for_stageb_funcscanner(
&self,
func: &MirFunction,
loop_form: &LoopForm,
) -> Option<JoinModule> {
self.lower(func, loop_form, Some("StageBFuncScannerBox.scan_all_boxes/1"))
}
} }
#[cfg(test)] #[cfg(test)]

View File

@ -11,8 +11,7 @@ use crate::mir::join_ir::lowering::common::{
}; };
use crate::mir::join_ir::lowering::value_id_ranges::stageb_body_extract as vid; use crate::mir::join_ir::lowering::value_id_ranges::stageb_body_extract as vid;
use crate::mir::join_ir::JoinModule; use crate::mir::join_ir::JoinModule;
use crate::mir::loop_form::LoopForm; use crate::mir::query::MirQueryBox;
use crate::mir::query::{MirQuery, MirQueryBox};
/// Public dispatcher (MIR-based vs handwritten) /// Public dispatcher (MIR-based vs handwritten)
pub fn lower_stageb_body_to_joinir(module: &crate::mir::MirModule) -> Option<JoinModule> { pub fn lower_stageb_body_to_joinir(module: &crate::mir::MirModule) -> Option<JoinModule> {
@ -173,22 +172,30 @@ fn lower_from_mir(module: &crate::mir::MirModule) -> Option<JoinModule> {
return lower_handwritten(module); return lower_handwritten(module);
} }
// Phase 32: LoopToJoinLowerer 統一箱経由に移行
// construct_simple_while_loopform 共通ヘルパーを使用
if crate::mir::join_ir::env_flag_is_1("NYASH_JOINIR_LOWER_GENERIC") { if crate::mir::join_ir::env_flag_is_1("NYASH_JOINIR_LOWER_GENERIC") {
let header = query.succs(entry).get(0).copied().unwrap_or(entry); use crate::mir::join_ir::lowering::common::construct_simple_while_loopform;
let succs_header = query.succs(header); use crate::mir::join_ir::lowering::loop_to_join::LoopToJoinLowerer;
let body = succs_header.get(0).copied().unwrap_or(header);
let exit = succs_header.get(1).copied().unwrap_or(header); // stageb_body: entry_is_preheader=true, has_break=true
let loop_form = LoopForm { let Some(loop_form) = construct_simple_while_loopform(entry, &query, true, true) else {
preheader: entry, eprintln!("[joinir/stageb_body/generic-hook] failed to construct LoopForm from CFG");
header, return build_stageb_body_joinir(module);
body,
latch: body,
exit,
continue_targets: vec![body],
break_targets: vec![exit],
}; };
if crate::mir::join_ir::lowering::common::case_a::is_simple_case_a_loop(&loop_form) { if crate::mir::join_ir::lowering::common::case_a::is_simple_case_a_loop(&loop_form) {
eprintln!("[joinir/stageb_body/generic-hook] simple Case A loop detected (generic_case_a hook placeholder)"); eprintln!(
"[joinir/stageb_body/generic-hook] simple Case A loop detected (LoopToJoinLowerer)"
);
let lowerer = LoopToJoinLowerer::new();
if let Some(jm) = lowerer.lower_case_a_for_stageb_body(target_func, &loop_form) {
eprintln!("[joinir/stageb_body/generic-hook] LoopToJoinLowerer produced JoinIR, returning early");
return Some(jm);
}
eprintln!(
"[joinir/stageb_body/generic-hook] LoopToJoinLowerer returned None, falling back to handwritten"
);
} }
} }

View File

@ -11,8 +11,7 @@ use crate::mir::join_ir::lowering::common::{
}; };
use crate::mir::join_ir::lowering::value_id_ranges::stageb_funcscanner as vid; use crate::mir::join_ir::lowering::value_id_ranges::stageb_funcscanner as vid;
use crate::mir::join_ir::JoinModule; use crate::mir::join_ir::JoinModule;
use crate::mir::loop_form::LoopForm; use crate::mir::query::MirQueryBox;
use crate::mir::query::{MirQuery, MirQueryBox};
/// Public dispatcher (MIR-based vs handwritten) /// Public dispatcher (MIR-based vs handwritten)
pub fn lower_stageb_funcscanner_to_joinir(module: &crate::mir::MirModule) -> Option<JoinModule> { pub fn lower_stageb_funcscanner_to_joinir(module: &crate::mir::MirModule) -> Option<JoinModule> {
@ -163,22 +162,30 @@ fn lower_from_mir(module: &crate::mir::MirModule) -> Option<JoinModule> {
return lower_handwritten(module); return lower_handwritten(module);
} }
// Phase 32: LoopToJoinLowerer 統一箱経由に移行
// construct_simple_while_loopform 共通ヘルパーを使用
if crate::mir::join_ir::env_flag_is_1("NYASH_JOINIR_LOWER_GENERIC") { if crate::mir::join_ir::env_flag_is_1("NYASH_JOINIR_LOWER_GENERIC") {
let header = query.succs(entry).get(0).copied().unwrap_or(entry); use crate::mir::join_ir::lowering::common::construct_simple_while_loopform;
let succs_header = query.succs(header); use crate::mir::join_ir::lowering::loop_to_join::LoopToJoinLowerer;
let body = succs_header.get(0).copied().unwrap_or(header);
let exit = succs_header.get(1).copied().unwrap_or(header); // stageb_funcscanner: entry_is_preheader=true, has_break=true
let loop_form = LoopForm { let Some(loop_form) = construct_simple_while_loopform(entry, &query, true, true) else {
preheader: entry, eprintln!("[joinir/stageb_funcscanner/generic-hook] failed to construct LoopForm from CFG");
header, return build_stageb_funcscanner_joinir(module);
body,
latch: body,
exit,
continue_targets: vec![body],
break_targets: vec![exit],
}; };
if crate::mir::join_ir::lowering::common::case_a::is_simple_case_a_loop(&loop_form) { if crate::mir::join_ir::lowering::common::case_a::is_simple_case_a_loop(&loop_form) {
eprintln!("[joinir/stageb_funcscanner/generic-hook] simple Case A loop detected (generic_case_a hook placeholder)"); eprintln!(
"[joinir/stageb_funcscanner/generic-hook] simple Case A loop detected (LoopToJoinLowerer)"
);
let lowerer = LoopToJoinLowerer::new();
if let Some(jm) = lowerer.lower_case_a_for_stageb_funcscanner(target_func, &loop_form) {
eprintln!("[joinir/stageb_funcscanner/generic-hook] LoopToJoinLowerer produced JoinIR, returning early");
return Some(jm);
}
eprintln!(
"[joinir/stageb_funcscanner/generic-hook] LoopToJoinLowerer returned None, falling back to handwritten"
);
} }
} }