2025-11-24 14:17:02 +09:00
|
|
|
|
//! Generic Case A LoopForm → JoinIR lowering (v1, minimal_ssa_skip_ws 専用)
|
|
|
|
|
|
//!
|
|
|
|
|
|
//! 制約(必読):
|
|
|
|
|
|
//! - 条件式の中身を解析しない(Compare/BinOp を MIR そのままコピーするだけ)
|
|
|
|
|
|
//! - 多重ヘッダ/ネストループは対象外(v1 は minimal_ssa_skip_ws の単純ループ専用)
|
|
|
|
|
|
//! - pinned/carrier/exit は LoopVarClassBox / LoopExitLivenessBox から渡された前提で扱う
|
|
|
|
|
|
//! - 解析に失敗したら必ず None を返し、呼び元にフォールバックさせる
|
|
|
|
|
|
|
2025-11-25 06:32:08 +09:00
|
|
|
|
use std::collections::BTreeMap;
|
2025-11-24 14:17:02 +09:00
|
|
|
|
|
2025-11-25 06:32:08 +09:00
|
|
|
|
use crate::mir::join_ir::lowering::loop_scope_shape::CaseAContext;
|
2025-11-24 14:17:02 +09:00
|
|
|
|
use crate::mir::join_ir::lowering::value_id_ranges;
|
|
|
|
|
|
use crate::mir::join_ir::lowering::value_id_ranges::skip_ws as vid;
|
|
|
|
|
|
use crate::mir::join_ir::lowering::value_id_ranges::stage1_using_resolver as stage1_vid;
|
|
|
|
|
|
use crate::mir::join_ir::{
|
|
|
|
|
|
BinOpKind, CompareOp, ConstValue, JoinContId, JoinFuncId, JoinFunction, JoinInst, JoinModule,
|
|
|
|
|
|
LoopExitShape, LoopHeaderShape, MirLikeInst,
|
|
|
|
|
|
};
|
|
|
|
|
|
use crate::mir::loop_form::LoopForm;
|
|
|
|
|
|
use crate::mir::phi_core::loop_exit_liveness::LoopExitLivenessBox;
|
|
|
|
|
|
use crate::mir::phi_core::loop_var_classifier::LoopVarClassBox;
|
|
|
|
|
|
use crate::mir::{MirFunction, MirQuery, ValueId};
|
|
|
|
|
|
|
|
|
|
|
|
/// v1: minimal_ssa_skip_ws 専用の汎用 Case A ロワー
|
|
|
|
|
|
///
|
|
|
|
|
|
/// - LoopForm / VarClass / ExitLiveness は形の検証にのみ使う(パターンが合わなければ None)
|
|
|
|
|
|
/// - JoinModule の形は hand-written skip_ws と同一になるように組み立てる
|
|
|
|
|
|
pub fn lower_case_a_loop_to_joinir_for_minimal_skip_ws(
|
|
|
|
|
|
loop_form: &LoopForm,
|
|
|
|
|
|
var_classes: &LoopVarClassBox,
|
|
|
|
|
|
exit_live: &LoopExitLivenessBox,
|
|
|
|
|
|
query: &impl MirQuery,
|
|
|
|
|
|
mir_func: &MirFunction,
|
|
|
|
|
|
) -> Option<JoinModule> {
|
2025-11-25 06:32:08 +09:00
|
|
|
|
// 追加の latch チェック(skip_ws 固有)
|
2025-11-24 14:17:02 +09:00
|
|
|
|
if loop_form.latch != loop_form.body && loop_form.latch != loop_form.header {
|
|
|
|
|
|
eprintln!(
|
|
|
|
|
|
"[joinir/generic_case_a] unexpected latch {:?} (body={:?}, header={:?}), fallback",
|
|
|
|
|
|
loop_form.latch, loop_form.body, loop_form.header
|
|
|
|
|
|
);
|
|
|
|
|
|
return None;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-25 06:32:08 +09:00
|
|
|
|
// CaseAContext で共通ロジックを実行
|
|
|
|
|
|
let ctx = CaseAContext::new(
|
|
|
|
|
|
loop_form,
|
|
|
|
|
|
var_classes,
|
|
|
|
|
|
exit_live,
|
|
|
|
|
|
query,
|
|
|
|
|
|
mir_func,
|
|
|
|
|
|
"skip_ws",
|
|
|
|
|
|
|offset| vid::loop_step(offset),
|
|
|
|
|
|
)?;
|
|
|
|
|
|
|
|
|
|
|
|
// JoinModule を手書き skip_ws と同じ形で構築(ValueId 範囲も揃える)
|
|
|
|
|
|
let string_key = ctx.pinned_name_or_first(0)?;
|
|
|
|
|
|
let len_key = ctx.pinned_name_or_first(1).unwrap_or_else(|| string_key.clone());
|
|
|
|
|
|
let index_key = ctx.carrier_name_or_first(0)?;
|
|
|
|
|
|
|
|
|
|
|
|
let s_loop = ctx.get_loop_id(&string_key)?;
|
|
|
|
|
|
let i_loop = ctx.get_loop_id(&index_key)?;
|
|
|
|
|
|
let n_loop = ctx.get_loop_id(&len_key)?;
|
2025-11-24 14:17:02 +09:00
|
|
|
|
|
|
|
|
|
|
let mut join_module = JoinModule::new();
|
|
|
|
|
|
|
|
|
|
|
|
// entry: skip(s)
|
|
|
|
|
|
let skip_id = JoinFuncId::new(0);
|
|
|
|
|
|
let s_param = vid::entry(0); // 3000
|
|
|
|
|
|
let mut skip_func = JoinFunction::new(skip_id, "skip".to_string(), vec![s_param]);
|
|
|
|
|
|
|
|
|
|
|
|
let i_init = vid::entry(1); // 3001
|
|
|
|
|
|
let n_val = vid::entry(2); // 3002
|
|
|
|
|
|
|
|
|
|
|
|
let mut entry_name_to_id: BTreeMap<String, ValueId> = BTreeMap::new();
|
|
|
|
|
|
entry_name_to_id.insert(string_key.clone(), s_param);
|
|
|
|
|
|
entry_name_to_id.insert(index_key.clone(), i_init);
|
|
|
|
|
|
entry_name_to_id.insert(len_key.clone(), n_val);
|
|
|
|
|
|
|
|
|
|
|
|
skip_func.body.push(JoinInst::Compute(MirLikeInst::Const {
|
|
|
|
|
|
dst: i_init,
|
|
|
|
|
|
value: ConstValue::Integer(0),
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
skip_func.body.push(JoinInst::Compute(MirLikeInst::BoxCall {
|
|
|
|
|
|
dst: Some(n_val),
|
|
|
|
|
|
box_name: "StringBox".to_string(),
|
|
|
|
|
|
method: "length".to_string(),
|
|
|
|
|
|
args: vec![s_param],
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
let loop_step_id = JoinFuncId::new(1);
|
2025-11-25 06:32:08 +09:00
|
|
|
|
let loop_call_args: Vec<ValueId> = ctx
|
|
|
|
|
|
.ordered_pinned
|
2025-11-24 14:17:02 +09:00
|
|
|
|
.iter()
|
2025-11-25 06:32:08 +09:00
|
|
|
|
.chain(ctx.ordered_carriers.iter())
|
2025-11-24 14:17:02 +09:00
|
|
|
|
.map(|name| entry_name_to_id.get(name).copied())
|
|
|
|
|
|
.collect::<Option<_>>()?;
|
|
|
|
|
|
|
|
|
|
|
|
skip_func.body.push(JoinInst::Call {
|
|
|
|
|
|
func: loop_step_id,
|
|
|
|
|
|
args: loop_call_args,
|
|
|
|
|
|
k_next: None,
|
|
|
|
|
|
dst: None,
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
join_module.entry = Some(skip_id);
|
|
|
|
|
|
join_module.add_function(skip_func);
|
|
|
|
|
|
|
|
|
|
|
|
// loop_step(s, i, n)
|
2025-11-25 06:32:08 +09:00
|
|
|
|
let header_shape = LoopHeaderShape::new_manual(ctx.pinned_ids.clone(), ctx.carrier_ids.clone());
|
2025-11-24 14:17:02 +09:00
|
|
|
|
let loop_params = header_shape.to_loop_step_params();
|
|
|
|
|
|
let mut loop_step_func =
|
|
|
|
|
|
JoinFunction::new(loop_step_id, "loop_step".to_string(), loop_params.clone());
|
|
|
|
|
|
|
|
|
|
|
|
let cmp1_result = vid::loop_step(3); // 4003
|
|
|
|
|
|
let ch = vid::loop_step(4); // 4004
|
|
|
|
|
|
let cmp2_result = vid::loop_step(5); // 4005
|
|
|
|
|
|
let i_plus_1 = vid::loop_step(6); // 4006
|
|
|
|
|
|
let const_1 = vid::loop_step(7); // 4007
|
|
|
|
|
|
let const_space = vid::loop_step(10); // 4010
|
|
|
|
|
|
let bool_false = vid::loop_step(11); // 4011
|
|
|
|
|
|
let cmp2_is_false = vid::loop_step(12); // 4012
|
|
|
|
|
|
|
|
|
|
|
|
// cmp1_result = (i >= n)
|
|
|
|
|
|
loop_step_func
|
|
|
|
|
|
.body
|
|
|
|
|
|
.push(JoinInst::Compute(MirLikeInst::Compare {
|
|
|
|
|
|
dst: cmp1_result,
|
|
|
|
|
|
op: CompareOp::Ge,
|
|
|
|
|
|
lhs: i_loop,
|
|
|
|
|
|
rhs: n_loop,
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
2025-11-25 06:32:08 +09:00
|
|
|
|
let _exit_shape = if ctx.exit_args.is_empty() {
|
2025-11-24 14:17:02 +09:00
|
|
|
|
LoopExitShape::new_manual(vec![i_loop])
|
|
|
|
|
|
} else {
|
2025-11-25 06:32:08 +09:00
|
|
|
|
LoopExitShape::new_manual(ctx.exit_args.clone())
|
2025-11-24 14:17:02 +09:00
|
|
|
|
}; // exit_args = [i] が期待値
|
|
|
|
|
|
|
|
|
|
|
|
// if i >= n { return i }
|
|
|
|
|
|
loop_step_func.body.push(JoinInst::Jump {
|
|
|
|
|
|
cont: JoinContId::new(0),
|
|
|
|
|
|
args: vec![i_loop],
|
|
|
|
|
|
cond: Some(cmp1_result),
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// const 1
|
|
|
|
|
|
loop_step_func
|
|
|
|
|
|
.body
|
|
|
|
|
|
.push(JoinInst::Compute(MirLikeInst::Const {
|
|
|
|
|
|
dst: const_1,
|
|
|
|
|
|
value: ConstValue::Integer(1),
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
// i_plus_1 = i + 1
|
|
|
|
|
|
loop_step_func
|
|
|
|
|
|
.body
|
|
|
|
|
|
.push(JoinInst::Compute(MirLikeInst::BinOp {
|
|
|
|
|
|
dst: i_plus_1,
|
|
|
|
|
|
op: BinOpKind::Add,
|
|
|
|
|
|
lhs: i_loop,
|
|
|
|
|
|
rhs: const_1,
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
// ch = s.substring(i, i + 1)
|
|
|
|
|
|
loop_step_func
|
|
|
|
|
|
.body
|
|
|
|
|
|
.push(JoinInst::Compute(MirLikeInst::BoxCall {
|
|
|
|
|
|
dst: Some(ch),
|
|
|
|
|
|
box_name: "StringBox".to_string(),
|
|
|
|
|
|
method: "substring".to_string(),
|
|
|
|
|
|
args: vec![s_loop, i_loop, i_plus_1],
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
// const " "
|
|
|
|
|
|
loop_step_func
|
|
|
|
|
|
.body
|
|
|
|
|
|
.push(JoinInst::Compute(MirLikeInst::Const {
|
|
|
|
|
|
dst: const_space,
|
|
|
|
|
|
value: ConstValue::String(" ".to_string()),
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
// cmp2_result = (ch == " ")
|
|
|
|
|
|
loop_step_func
|
|
|
|
|
|
.body
|
|
|
|
|
|
.push(JoinInst::Compute(MirLikeInst::Compare {
|
|
|
|
|
|
dst: cmp2_result,
|
|
|
|
|
|
op: CompareOp::Eq,
|
|
|
|
|
|
lhs: ch,
|
|
|
|
|
|
rhs: const_space,
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
// bool false
|
|
|
|
|
|
loop_step_func
|
|
|
|
|
|
.body
|
|
|
|
|
|
.push(JoinInst::Compute(MirLikeInst::Const {
|
|
|
|
|
|
dst: bool_false,
|
|
|
|
|
|
value: ConstValue::Bool(false),
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
// cmp2_is_false = (cmp2_result == false)
|
|
|
|
|
|
loop_step_func
|
|
|
|
|
|
.body
|
|
|
|
|
|
.push(JoinInst::Compute(MirLikeInst::Compare {
|
|
|
|
|
|
dst: cmp2_is_false,
|
|
|
|
|
|
op: CompareOp::Eq,
|
|
|
|
|
|
lhs: cmp2_result,
|
|
|
|
|
|
rhs: bool_false,
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
// if ch != " " { return i }
|
|
|
|
|
|
loop_step_func.body.push(JoinInst::Jump {
|
|
|
|
|
|
cont: JoinContId::new(1),
|
|
|
|
|
|
args: vec![i_loop],
|
|
|
|
|
|
cond: Some(cmp2_is_false),
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// continue: loop_step(s, i+1, n)
|
|
|
|
|
|
loop_step_func.body.push(JoinInst::Call {
|
|
|
|
|
|
func: loop_step_id,
|
|
|
|
|
|
args: vec![s_loop, i_plus_1, n_loop],
|
|
|
|
|
|
k_next: None,
|
|
|
|
|
|
dst: None,
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
join_module.add_function(loop_step_func);
|
|
|
|
|
|
|
|
|
|
|
|
eprintln!(
|
|
|
|
|
|
"[joinir/generic_case_a] ✅ constructed JoinIR (functions={}, value_range={}..{})",
|
|
|
|
|
|
join_module.functions.len(),
|
|
|
|
|
|
value_id_ranges::base::SKIP_WS,
|
|
|
|
|
|
value_id_ranges::base::SKIP_WS + 1999
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
Some(join_module)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Placeholder: trim minimal 用の generic Case A ロワー(v0, 未実装)
|
|
|
|
|
|
///
|
|
|
|
|
|
/// - いまは構造チェックのみで必ず None を返し、呼び元でフォールバックさせる
|
|
|
|
|
|
/// - 将来 trim_minimal を generic_case_a で置き換える際の導線として用意
|
|
|
|
|
|
pub fn lower_case_a_loop_to_joinir_for_trim_minimal(
|
|
|
|
|
|
loop_form: &LoopForm,
|
|
|
|
|
|
var_classes: &LoopVarClassBox,
|
|
|
|
|
|
exit_live: &LoopExitLivenessBox,
|
|
|
|
|
|
query: &impl MirQuery,
|
|
|
|
|
|
mir_func: &MirFunction,
|
|
|
|
|
|
) -> Option<JoinModule> {
|
2025-11-25 06:32:08 +09:00
|
|
|
|
// CaseAContext で共通ロジックを実行
|
|
|
|
|
|
let ctx = CaseAContext::new(
|
|
|
|
|
|
loop_form,
|
|
|
|
|
|
var_classes,
|
|
|
|
|
|
exit_live,
|
|
|
|
|
|
query,
|
|
|
|
|
|
mir_func,
|
|
|
|
|
|
"trim",
|
|
|
|
|
|
|offset| value_id_ranges::funcscanner_trim::loop_step(offset),
|
|
|
|
|
|
)?;
|
|
|
|
|
|
|
|
|
|
|
|
let string_key = ctx.pinned_name_or_first(0)?;
|
|
|
|
|
|
let base_key = ctx.pinned_name_or_first(1).unwrap_or_else(|| string_key.clone());
|
|
|
|
|
|
let carrier_key = ctx.carrier_name_or_first(0)?;
|
|
|
|
|
|
|
|
|
|
|
|
let s_loop = ctx.get_loop_id(&string_key)?;
|
|
|
|
|
|
let b_loop = ctx.get_loop_id(&base_key)?;
|
|
|
|
|
|
let e_loop = ctx.get_loop_id(&carrier_key)?;
|
2025-11-24 14:17:02 +09:00
|
|
|
|
|
|
|
|
|
|
let mut join_module = JoinModule::new();
|
|
|
|
|
|
|
|
|
|
|
|
// entry: trim_main(s_param)
|
|
|
|
|
|
let trim_main_id = JoinFuncId::new(0);
|
|
|
|
|
|
let s_param = value_id_ranges::funcscanner_trim::entry(0);
|
|
|
|
|
|
let mut trim_main_func =
|
|
|
|
|
|
JoinFunction::new(trim_main_id, "trim_main".to_string(), vec![s_param]);
|
|
|
|
|
|
|
|
|
|
|
|
let str_val = value_id_ranges::funcscanner_trim::entry(1);
|
|
|
|
|
|
let n_val = value_id_ranges::funcscanner_trim::entry(2);
|
|
|
|
|
|
let b_val = value_id_ranges::funcscanner_trim::entry(3);
|
|
|
|
|
|
let e_init = value_id_ranges::funcscanner_trim::entry(4);
|
|
|
|
|
|
let const_empty = value_id_ranges::funcscanner_trim::entry(5);
|
|
|
|
|
|
let const_zero = value_id_ranges::funcscanner_trim::entry(6);
|
|
|
|
|
|
|
|
|
|
|
|
trim_main_func
|
|
|
|
|
|
.body
|
|
|
|
|
|
.push(JoinInst::Compute(MirLikeInst::Const {
|
|
|
|
|
|
dst: const_empty,
|
|
|
|
|
|
value: ConstValue::String("".to_string()),
|
|
|
|
|
|
}));
|
|
|
|
|
|
trim_main_func
|
|
|
|
|
|
.body
|
|
|
|
|
|
.push(JoinInst::Compute(MirLikeInst::BinOp {
|
|
|
|
|
|
dst: str_val,
|
|
|
|
|
|
lhs: const_empty,
|
|
|
|
|
|
rhs: s_param,
|
|
|
|
|
|
op: BinOpKind::Add,
|
|
|
|
|
|
}));
|
|
|
|
|
|
trim_main_func
|
|
|
|
|
|
.body
|
|
|
|
|
|
.push(JoinInst::Compute(MirLikeInst::BoxCall {
|
|
|
|
|
|
dst: Some(n_val),
|
|
|
|
|
|
box_name: "StringBox".to_string(),
|
|
|
|
|
|
method: "length".to_string(),
|
|
|
|
|
|
args: vec![str_val],
|
|
|
|
|
|
}));
|
|
|
|
|
|
trim_main_func
|
|
|
|
|
|
.body
|
|
|
|
|
|
.push(JoinInst::Compute(MirLikeInst::Const {
|
|
|
|
|
|
dst: const_zero,
|
|
|
|
|
|
value: ConstValue::Integer(0),
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
let skip_leading_id = JoinFuncId::new(2);
|
|
|
|
|
|
trim_main_func.body.push(JoinInst::Call {
|
|
|
|
|
|
func: skip_leading_id,
|
|
|
|
|
|
args: vec![str_val, const_zero, n_val],
|
|
|
|
|
|
k_next: None,
|
|
|
|
|
|
dst: Some(b_val),
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
trim_main_func
|
|
|
|
|
|
.body
|
|
|
|
|
|
.push(JoinInst::Compute(MirLikeInst::BinOp {
|
|
|
|
|
|
dst: e_init,
|
|
|
|
|
|
op: BinOpKind::Add,
|
|
|
|
|
|
lhs: n_val,
|
|
|
|
|
|
rhs: const_zero,
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
let mut entry_name_to_id: BTreeMap<String, ValueId> = BTreeMap::new();
|
|
|
|
|
|
entry_name_to_id.insert(string_key.clone(), str_val);
|
|
|
|
|
|
entry_name_to_id.insert(base_key.clone(), b_val);
|
|
|
|
|
|
entry_name_to_id.insert(carrier_key.clone(), e_init);
|
|
|
|
|
|
|
2025-11-25 06:32:08 +09:00
|
|
|
|
let loop_call_args: Vec<ValueId> = ctx
|
|
|
|
|
|
.ordered_pinned
|
2025-11-24 14:17:02 +09:00
|
|
|
|
.iter()
|
2025-11-25 06:32:08 +09:00
|
|
|
|
.chain(ctx.ordered_carriers.iter())
|
2025-11-24 14:17:02 +09:00
|
|
|
|
.map(|name| entry_name_to_id.get(name).copied())
|
|
|
|
|
|
.collect::<Option<_>>()?;
|
|
|
|
|
|
|
|
|
|
|
|
let loop_step_id = JoinFuncId::new(1);
|
|
|
|
|
|
trim_main_func.body.push(JoinInst::Call {
|
|
|
|
|
|
func: loop_step_id,
|
|
|
|
|
|
args: loop_call_args,
|
|
|
|
|
|
k_next: None,
|
|
|
|
|
|
dst: None,
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
join_module.entry = Some(trim_main_id);
|
|
|
|
|
|
join_module.add_function(trim_main_func);
|
|
|
|
|
|
|
|
|
|
|
|
// loop_step(str, b, e)
|
2025-11-25 06:32:08 +09:00
|
|
|
|
let header_shape = LoopHeaderShape::new_manual(ctx.pinned_ids.clone(), ctx.carrier_ids.clone());
|
2025-11-24 14:17:02 +09:00
|
|
|
|
let loop_params = header_shape.to_loop_step_params();
|
|
|
|
|
|
let mut loop_step_func =
|
|
|
|
|
|
JoinFunction::new(loop_step_id, "loop_step".to_string(), loop_params.clone());
|
|
|
|
|
|
|
|
|
|
|
|
let cond = value_id_ranges::funcscanner_trim::loop_step(3);
|
|
|
|
|
|
loop_step_func
|
|
|
|
|
|
.body
|
|
|
|
|
|
.push(JoinInst::Compute(MirLikeInst::Compare {
|
|
|
|
|
|
dst: cond,
|
|
|
|
|
|
lhs: e_loop,
|
|
|
|
|
|
rhs: b_loop,
|
|
|
|
|
|
op: CompareOp::Gt,
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
let bool_false = value_id_ranges::funcscanner_trim::loop_step(19);
|
|
|
|
|
|
loop_step_func
|
|
|
|
|
|
.body
|
|
|
|
|
|
.push(JoinInst::Compute(MirLikeInst::Const {
|
|
|
|
|
|
dst: bool_false,
|
|
|
|
|
|
value: ConstValue::Bool(false),
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
let trimmed_base = value_id_ranges::funcscanner_trim::loop_step(4);
|
|
|
|
|
|
loop_step_func
|
|
|
|
|
|
.body
|
|
|
|
|
|
.push(JoinInst::Compute(MirLikeInst::BoxCall {
|
|
|
|
|
|
dst: Some(trimmed_base),
|
|
|
|
|
|
box_name: "StringBox".to_string(),
|
|
|
|
|
|
method: "substring".to_string(),
|
|
|
|
|
|
args: vec![s_loop, b_loop, e_loop],
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
let cond_is_false = value_id_ranges::funcscanner_trim::loop_step(20);
|
|
|
|
|
|
loop_step_func
|
|
|
|
|
|
.body
|
|
|
|
|
|
.push(JoinInst::Compute(MirLikeInst::Compare {
|
|
|
|
|
|
dst: cond_is_false,
|
|
|
|
|
|
lhs: cond,
|
|
|
|
|
|
rhs: bool_false,
|
|
|
|
|
|
op: CompareOp::Eq,
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
2025-11-25 06:32:08 +09:00
|
|
|
|
let _exit_shape_trim = if ctx.exit_args.is_empty() {
|
2025-11-24 14:17:02 +09:00
|
|
|
|
LoopExitShape::new_manual(vec![e_loop])
|
|
|
|
|
|
} else {
|
2025-11-25 06:32:08 +09:00
|
|
|
|
LoopExitShape::new_manual(ctx.exit_args.clone())
|
2025-11-24 14:17:02 +09:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
loop_step_func.body.push(JoinInst::Jump {
|
|
|
|
|
|
cont: JoinContId::new(0),
|
|
|
|
|
|
args: vec![trimmed_base],
|
|
|
|
|
|
cond: Some(cond_is_false),
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
let const_1 = value_id_ranges::funcscanner_trim::loop_step(5);
|
|
|
|
|
|
loop_step_func
|
|
|
|
|
|
.body
|
|
|
|
|
|
.push(JoinInst::Compute(MirLikeInst::Const {
|
|
|
|
|
|
dst: const_1,
|
|
|
|
|
|
value: ConstValue::Integer(1),
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
let e_minus_1 = value_id_ranges::funcscanner_trim::loop_step(6);
|
|
|
|
|
|
loop_step_func
|
|
|
|
|
|
.body
|
|
|
|
|
|
.push(JoinInst::Compute(MirLikeInst::BinOp {
|
|
|
|
|
|
dst: e_minus_1,
|
|
|
|
|
|
lhs: e_loop,
|
|
|
|
|
|
rhs: const_1,
|
|
|
|
|
|
op: BinOpKind::Sub,
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
let ch = value_id_ranges::funcscanner_trim::loop_step(7);
|
|
|
|
|
|
loop_step_func
|
|
|
|
|
|
.body
|
|
|
|
|
|
.push(JoinInst::Compute(MirLikeInst::BoxCall {
|
|
|
|
|
|
dst: Some(ch),
|
|
|
|
|
|
box_name: "StringBox".to_string(),
|
|
|
|
|
|
method: "substring".to_string(),
|
|
|
|
|
|
args: vec![s_loop, e_minus_1, e_loop],
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
let cmp_space = value_id_ranges::funcscanner_trim::loop_step(8);
|
|
|
|
|
|
let cmp_tab = value_id_ranges::funcscanner_trim::loop_step(9);
|
|
|
|
|
|
let cmp_newline = value_id_ranges::funcscanner_trim::loop_step(10);
|
|
|
|
|
|
let cmp_cr = value_id_ranges::funcscanner_trim::loop_step(11);
|
|
|
|
|
|
|
|
|
|
|
|
let const_space = value_id_ranges::funcscanner_trim::loop_step(12);
|
|
|
|
|
|
let const_tab = value_id_ranges::funcscanner_trim::loop_step(13);
|
|
|
|
|
|
let const_newline = value_id_ranges::funcscanner_trim::loop_step(14);
|
|
|
|
|
|
let const_cr = value_id_ranges::funcscanner_trim::loop_step(15);
|
|
|
|
|
|
|
|
|
|
|
|
loop_step_func
|
|
|
|
|
|
.body
|
|
|
|
|
|
.push(JoinInst::Compute(MirLikeInst::Const {
|
|
|
|
|
|
dst: const_space,
|
|
|
|
|
|
value: ConstValue::String(" ".to_string()),
|
|
|
|
|
|
}));
|
|
|
|
|
|
loop_step_func
|
|
|
|
|
|
.body
|
|
|
|
|
|
.push(JoinInst::Compute(MirLikeInst::Compare {
|
|
|
|
|
|
dst: cmp_space,
|
|
|
|
|
|
lhs: ch,
|
|
|
|
|
|
rhs: const_space,
|
|
|
|
|
|
op: CompareOp::Eq,
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
loop_step_func
|
|
|
|
|
|
.body
|
|
|
|
|
|
.push(JoinInst::Compute(MirLikeInst::Const {
|
|
|
|
|
|
dst: const_tab,
|
|
|
|
|
|
value: ConstValue::String("\\t".to_string()),
|
|
|
|
|
|
}));
|
|
|
|
|
|
loop_step_func
|
|
|
|
|
|
.body
|
|
|
|
|
|
.push(JoinInst::Compute(MirLikeInst::Compare {
|
|
|
|
|
|
dst: cmp_tab,
|
|
|
|
|
|
lhs: ch,
|
|
|
|
|
|
rhs: const_tab,
|
|
|
|
|
|
op: CompareOp::Eq,
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
loop_step_func
|
|
|
|
|
|
.body
|
|
|
|
|
|
.push(JoinInst::Compute(MirLikeInst::Const {
|
|
|
|
|
|
dst: const_newline,
|
|
|
|
|
|
value: ConstValue::String("\\n".to_string()),
|
|
|
|
|
|
}));
|
|
|
|
|
|
loop_step_func
|
|
|
|
|
|
.body
|
|
|
|
|
|
.push(JoinInst::Compute(MirLikeInst::Compare {
|
|
|
|
|
|
dst: cmp_newline,
|
|
|
|
|
|
lhs: ch,
|
|
|
|
|
|
rhs: const_newline,
|
|
|
|
|
|
op: CompareOp::Eq,
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
loop_step_func
|
|
|
|
|
|
.body
|
|
|
|
|
|
.push(JoinInst::Compute(MirLikeInst::Const {
|
|
|
|
|
|
dst: const_cr,
|
|
|
|
|
|
value: ConstValue::String("\\r".to_string()),
|
|
|
|
|
|
}));
|
|
|
|
|
|
loop_step_func
|
|
|
|
|
|
.body
|
|
|
|
|
|
.push(JoinInst::Compute(MirLikeInst::Compare {
|
|
|
|
|
|
dst: cmp_cr,
|
|
|
|
|
|
lhs: ch,
|
|
|
|
|
|
rhs: const_cr,
|
|
|
|
|
|
op: CompareOp::Eq,
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
let or1 = value_id_ranges::funcscanner_trim::loop_step(16);
|
|
|
|
|
|
let or2 = value_id_ranges::funcscanner_trim::loop_step(17);
|
|
|
|
|
|
let is_space = value_id_ranges::funcscanner_trim::loop_step(18);
|
|
|
|
|
|
|
|
|
|
|
|
loop_step_func
|
|
|
|
|
|
.body
|
|
|
|
|
|
.push(JoinInst::Compute(MirLikeInst::BinOp {
|
|
|
|
|
|
dst: or1,
|
|
|
|
|
|
lhs: cmp_space,
|
|
|
|
|
|
rhs: cmp_tab,
|
|
|
|
|
|
op: BinOpKind::Or,
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
loop_step_func
|
|
|
|
|
|
.body
|
|
|
|
|
|
.push(JoinInst::Compute(MirLikeInst::BinOp {
|
|
|
|
|
|
dst: or2,
|
|
|
|
|
|
lhs: or1,
|
|
|
|
|
|
rhs: cmp_newline,
|
|
|
|
|
|
op: BinOpKind::Or,
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
loop_step_func
|
|
|
|
|
|
.body
|
|
|
|
|
|
.push(JoinInst::Compute(MirLikeInst::BinOp {
|
|
|
|
|
|
dst: is_space,
|
|
|
|
|
|
lhs: or2,
|
|
|
|
|
|
rhs: cmp_cr,
|
|
|
|
|
|
op: BinOpKind::Or,
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
let is_space_false = value_id_ranges::funcscanner_trim::loop_step(21);
|
|
|
|
|
|
loop_step_func
|
|
|
|
|
|
.body
|
|
|
|
|
|
.push(JoinInst::Compute(MirLikeInst::Compare {
|
|
|
|
|
|
dst: is_space_false,
|
|
|
|
|
|
lhs: is_space,
|
|
|
|
|
|
rhs: bool_false,
|
|
|
|
|
|
op: CompareOp::Eq,
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
loop_step_func.body.push(JoinInst::Jump {
|
|
|
|
|
|
cont: JoinContId::new(1),
|
|
|
|
|
|
args: vec![trimmed_base],
|
|
|
|
|
|
cond: Some(is_space_false),
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
let e_next = value_id_ranges::funcscanner_trim::loop_step(22);
|
|
|
|
|
|
loop_step_func
|
|
|
|
|
|
.body
|
|
|
|
|
|
.push(JoinInst::Compute(MirLikeInst::BinOp {
|
|
|
|
|
|
dst: e_next,
|
|
|
|
|
|
lhs: e_loop,
|
|
|
|
|
|
rhs: const_1,
|
|
|
|
|
|
op: BinOpKind::Sub,
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
loop_step_func.body.push(JoinInst::Call {
|
|
|
|
|
|
func: loop_step_id,
|
|
|
|
|
|
args: vec![s_loop, b_loop, e_next],
|
|
|
|
|
|
k_next: None,
|
|
|
|
|
|
dst: None,
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
join_module.add_function(loop_step_func);
|
|
|
|
|
|
|
|
|
|
|
|
// skip_leading 関数(共通ロジックを手書き版と合わせる)
|
|
|
|
|
|
let mut skip_func = JoinFunction::new(
|
|
|
|
|
|
skip_leading_id,
|
|
|
|
|
|
"skip_leading".to_string(),
|
|
|
|
|
|
vec![ValueId(7000), ValueId(7001), ValueId(7002)],
|
|
|
|
|
|
);
|
|
|
|
|
|
let s_skip = ValueId(7000);
|
|
|
|
|
|
let i_skip = ValueId(7001);
|
|
|
|
|
|
let n_skip = ValueId(7002);
|
|
|
|
|
|
let cmp_len = ValueId(7003);
|
|
|
|
|
|
let const_1_skip = ValueId(7004);
|
|
|
|
|
|
let i_plus_1_skip = ValueId(7005);
|
|
|
|
|
|
let ch_skip = ValueId(7006);
|
|
|
|
|
|
let cmp_space_skip = ValueId(7007);
|
|
|
|
|
|
let cmp_tab_skip = ValueId(7008);
|
|
|
|
|
|
let cmp_newline_skip = ValueId(7009);
|
|
|
|
|
|
let cmp_cr_skip = ValueId(7010);
|
|
|
|
|
|
let const_space_skip = ValueId(7011);
|
|
|
|
|
|
let const_tab_skip = ValueId(7012);
|
|
|
|
|
|
let const_newline_skip = ValueId(7013);
|
|
|
|
|
|
let const_cr_skip = ValueId(7014);
|
|
|
|
|
|
let or1_skip = ValueId(7015);
|
|
|
|
|
|
let or2_skip = ValueId(7016);
|
|
|
|
|
|
let is_space_skip = ValueId(7017);
|
|
|
|
|
|
let bool_false_skip = ValueId(7018);
|
|
|
|
|
|
let is_space_false_skip = ValueId(7019);
|
|
|
|
|
|
|
|
|
|
|
|
skip_func.body.push(JoinInst::Compute(MirLikeInst::Compare {
|
|
|
|
|
|
dst: cmp_len,
|
|
|
|
|
|
lhs: i_skip,
|
|
|
|
|
|
rhs: n_skip,
|
|
|
|
|
|
op: CompareOp::Ge,
|
|
|
|
|
|
}));
|
|
|
|
|
|
skip_func.body.push(JoinInst::Jump {
|
|
|
|
|
|
cont: JoinContId::new(2),
|
|
|
|
|
|
args: vec![i_skip],
|
|
|
|
|
|
cond: Some(cmp_len),
|
|
|
|
|
|
});
|
|
|
|
|
|
skip_func.body.push(JoinInst::Compute(MirLikeInst::Const {
|
|
|
|
|
|
dst: const_1_skip,
|
|
|
|
|
|
value: ConstValue::Integer(1),
|
|
|
|
|
|
}));
|
|
|
|
|
|
skip_func.body.push(JoinInst::Compute(MirLikeInst::BinOp {
|
|
|
|
|
|
dst: i_plus_1_skip,
|
|
|
|
|
|
lhs: i_skip,
|
|
|
|
|
|
rhs: const_1_skip,
|
|
|
|
|
|
op: BinOpKind::Add,
|
|
|
|
|
|
}));
|
|
|
|
|
|
skip_func.body.push(JoinInst::Compute(MirLikeInst::BoxCall {
|
|
|
|
|
|
dst: Some(ch_skip),
|
|
|
|
|
|
box_name: "StringBox".to_string(),
|
|
|
|
|
|
method: "substring".to_string(),
|
|
|
|
|
|
args: vec![s_skip, i_skip, i_plus_1_skip],
|
|
|
|
|
|
}));
|
|
|
|
|
|
skip_func.body.push(JoinInst::Compute(MirLikeInst::Const {
|
|
|
|
|
|
dst: const_space_skip,
|
|
|
|
|
|
value: ConstValue::String(" ".to_string()),
|
|
|
|
|
|
}));
|
|
|
|
|
|
skip_func.body.push(JoinInst::Compute(MirLikeInst::Compare {
|
|
|
|
|
|
dst: cmp_space_skip,
|
|
|
|
|
|
lhs: ch_skip,
|
|
|
|
|
|
rhs: const_space_skip,
|
|
|
|
|
|
op: CompareOp::Eq,
|
|
|
|
|
|
}));
|
|
|
|
|
|
skip_func.body.push(JoinInst::Compute(MirLikeInst::Const {
|
|
|
|
|
|
dst: const_tab_skip,
|
|
|
|
|
|
value: ConstValue::String("\\t".to_string()),
|
|
|
|
|
|
}));
|
|
|
|
|
|
skip_func.body.push(JoinInst::Compute(MirLikeInst::Compare {
|
|
|
|
|
|
dst: cmp_tab_skip,
|
|
|
|
|
|
lhs: ch_skip,
|
|
|
|
|
|
rhs: const_tab_skip,
|
|
|
|
|
|
op: CompareOp::Eq,
|
|
|
|
|
|
}));
|
|
|
|
|
|
skip_func.body.push(JoinInst::Compute(MirLikeInst::Const {
|
|
|
|
|
|
dst: const_newline_skip,
|
|
|
|
|
|
value: ConstValue::String("\\n".to_string()),
|
|
|
|
|
|
}));
|
|
|
|
|
|
skip_func.body.push(JoinInst::Compute(MirLikeInst::Compare {
|
|
|
|
|
|
dst: cmp_newline_skip,
|
|
|
|
|
|
lhs: ch_skip,
|
|
|
|
|
|
rhs: const_newline_skip,
|
|
|
|
|
|
op: CompareOp::Eq,
|
|
|
|
|
|
}));
|
|
|
|
|
|
skip_func.body.push(JoinInst::Compute(MirLikeInst::Const {
|
|
|
|
|
|
dst: const_cr_skip,
|
|
|
|
|
|
value: ConstValue::String("\\r".to_string()),
|
|
|
|
|
|
}));
|
|
|
|
|
|
skip_func.body.push(JoinInst::Compute(MirLikeInst::Compare {
|
|
|
|
|
|
dst: cmp_cr_skip,
|
|
|
|
|
|
lhs: ch_skip,
|
|
|
|
|
|
rhs: const_cr_skip,
|
|
|
|
|
|
op: CompareOp::Eq,
|
|
|
|
|
|
}));
|
|
|
|
|
|
skip_func.body.push(JoinInst::Compute(MirLikeInst::BinOp {
|
|
|
|
|
|
dst: or1_skip,
|
|
|
|
|
|
lhs: cmp_space_skip,
|
|
|
|
|
|
rhs: cmp_tab_skip,
|
|
|
|
|
|
op: BinOpKind::Or,
|
|
|
|
|
|
}));
|
|
|
|
|
|
skip_func.body.push(JoinInst::Compute(MirLikeInst::BinOp {
|
|
|
|
|
|
dst: or2_skip,
|
|
|
|
|
|
lhs: or1_skip,
|
|
|
|
|
|
rhs: cmp_newline_skip,
|
|
|
|
|
|
op: BinOpKind::Or,
|
|
|
|
|
|
}));
|
|
|
|
|
|
skip_func.body.push(JoinInst::Compute(MirLikeInst::BinOp {
|
|
|
|
|
|
dst: is_space_skip,
|
|
|
|
|
|
lhs: or2_skip,
|
|
|
|
|
|
rhs: cmp_cr_skip,
|
|
|
|
|
|
op: BinOpKind::Or,
|
|
|
|
|
|
}));
|
|
|
|
|
|
skip_func.body.push(JoinInst::Compute(MirLikeInst::Const {
|
|
|
|
|
|
dst: bool_false_skip,
|
|
|
|
|
|
value: ConstValue::Bool(false),
|
|
|
|
|
|
}));
|
|
|
|
|
|
skip_func.body.push(JoinInst::Compute(MirLikeInst::Compare {
|
|
|
|
|
|
dst: is_space_false_skip,
|
|
|
|
|
|
lhs: is_space_skip,
|
|
|
|
|
|
rhs: bool_false_skip,
|
|
|
|
|
|
op: CompareOp::Eq,
|
|
|
|
|
|
}));
|
|
|
|
|
|
skip_func.body.push(JoinInst::Jump {
|
|
|
|
|
|
cont: JoinContId::new(3),
|
|
|
|
|
|
args: vec![i_skip],
|
|
|
|
|
|
cond: Some(is_space_false_skip),
|
|
|
|
|
|
});
|
|
|
|
|
|
skip_func.body.push(JoinInst::Call {
|
|
|
|
|
|
func: skip_leading_id,
|
|
|
|
|
|
args: vec![s_skip, i_plus_1_skip, n_skip],
|
|
|
|
|
|
k_next: None,
|
|
|
|
|
|
dst: None,
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
join_module.add_function(skip_func);
|
|
|
|
|
|
|
|
|
|
|
|
eprintln!(
|
|
|
|
|
|
"[joinir/generic_case_a/trim] ✅ constructed JoinIR (functions={}, value_range={}..{})",
|
|
|
|
|
|
join_module.functions.len(),
|
|
|
|
|
|
value_id_ranges::base::FUNCSCANNER_TRIM,
|
|
|
|
|
|
value_id_ranges::base::FUNCSCANNER_TRIM + 1999
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
Some(join_module)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// append_defs_minimal 用の generic Case A ロワー(LoopForm/VarClass/ExitLiveness ベース)
|
|
|
|
|
|
///
|
|
|
|
|
|
/// - LoopForm が単一 header/latch でない場合や、必要な変数がマッピングできない場合は None を返す。
|
|
|
|
|
|
/// - 既存の手書き JoinIR(append_defs_entry + loop_step)と同じ形を目指す。
|
|
|
|
|
|
pub fn lower_case_a_loop_to_joinir_for_append_defs_minimal(
|
|
|
|
|
|
loop_form: &LoopForm,
|
|
|
|
|
|
var_classes: &LoopVarClassBox,
|
|
|
|
|
|
exit_live: &LoopExitLivenessBox,
|
|
|
|
|
|
query: &impl MirQuery,
|
|
|
|
|
|
mir_func: &MirFunction,
|
|
|
|
|
|
) -> Option<JoinModule> {
|
2025-11-25 06:32:08 +09:00
|
|
|
|
// CaseAContext で共通ロジックを実行
|
|
|
|
|
|
let ctx = CaseAContext::new(
|
|
|
|
|
|
loop_form,
|
|
|
|
|
|
var_classes,
|
|
|
|
|
|
exit_live,
|
|
|
|
|
|
query,
|
|
|
|
|
|
mir_func,
|
|
|
|
|
|
"append_defs",
|
|
|
|
|
|
|offset| value_id_ranges::funcscanner_append_defs::loop_step(offset),
|
|
|
|
|
|
)?;
|
|
|
|
|
|
|
|
|
|
|
|
let dst_key = ctx.pinned_name_or_first(0)?;
|
|
|
|
|
|
let defs_key = ctx.pinned_name_or_first(1).unwrap_or_else(|| dst_key.clone());
|
|
|
|
|
|
let n_key = ctx.pinned_name_or_first(2).unwrap_or_else(|| defs_key.clone());
|
|
|
|
|
|
let i_key = ctx.carrier_name_or_first(0)?;
|
|
|
|
|
|
|
|
|
|
|
|
let dst_loop = ctx.get_loop_id(&dst_key)?;
|
|
|
|
|
|
let defs_loop = ctx.get_loop_id(&defs_key)?;
|
|
|
|
|
|
let n_loop = ctx.get_loop_id(&n_key)?;
|
|
|
|
|
|
let i_loop = ctx.get_loop_id(&i_key)?;
|
2025-11-24 14:17:02 +09:00
|
|
|
|
|
|
|
|
|
|
let mut join_module = JoinModule::new();
|
|
|
|
|
|
|
|
|
|
|
|
// entry: append_defs_entry(dst, defs_box, n)
|
|
|
|
|
|
let entry_id = JoinFuncId::new(0);
|
|
|
|
|
|
let dst_param = value_id_ranges::funcscanner_append_defs::entry(0);
|
|
|
|
|
|
let defs_box_param = value_id_ranges::funcscanner_append_defs::entry(1);
|
|
|
|
|
|
let n_param = value_id_ranges::funcscanner_append_defs::entry(2);
|
|
|
|
|
|
let mut entry_func = JoinFunction::new(
|
|
|
|
|
|
entry_id,
|
|
|
|
|
|
"append_defs_entry".to_string(),
|
|
|
|
|
|
vec![dst_param, defs_box_param, n_param],
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
let i_init = value_id_ranges::funcscanner_append_defs::entry(10);
|
|
|
|
|
|
entry_func.body.push(JoinInst::Compute(MirLikeInst::Const {
|
|
|
|
|
|
dst: i_init,
|
|
|
|
|
|
value: ConstValue::Integer(0),
|
|
|
|
|
|
}));
|
|
|
|
|
|
let mut entry_name_to_id: BTreeMap<String, ValueId> = BTreeMap::new();
|
|
|
|
|
|
entry_name_to_id.insert("s".to_string(), dst_param); // intake で param0 を "s" にするため
|
|
|
|
|
|
entry_name_to_id.insert("dst".to_string(), dst_param);
|
|
|
|
|
|
entry_name_to_id.insert("param1".to_string(), defs_box_param);
|
|
|
|
|
|
entry_name_to_id.insert("defs_box".to_string(), defs_box_param);
|
|
|
|
|
|
entry_name_to_id.insert("n".to_string(), n_param);
|
|
|
|
|
|
entry_name_to_id.insert("i".to_string(), i_init);
|
|
|
|
|
|
|
2025-11-25 06:32:08 +09:00
|
|
|
|
let loop_call_args: Vec<ValueId> = ctx
|
|
|
|
|
|
.ordered_pinned
|
2025-11-24 14:17:02 +09:00
|
|
|
|
.iter()
|
2025-11-25 06:32:08 +09:00
|
|
|
|
.chain(ctx.ordered_carriers.iter())
|
2025-11-24 14:17:02 +09:00
|
|
|
|
.map(|name| entry_name_to_id.get(name).copied())
|
|
|
|
|
|
.collect::<Option<_>>()?;
|
|
|
|
|
|
|
|
|
|
|
|
let loop_step_id = JoinFuncId::new(1);
|
|
|
|
|
|
entry_func.body.push(JoinInst::Call {
|
|
|
|
|
|
func: loop_step_id,
|
|
|
|
|
|
args: loop_call_args,
|
|
|
|
|
|
k_next: None,
|
|
|
|
|
|
dst: None,
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
join_module.entry = Some(entry_id);
|
|
|
|
|
|
join_module.add_function(entry_func);
|
|
|
|
|
|
|
|
|
|
|
|
// loop_step(dst, defs_box, n, i)
|
2025-11-25 06:32:08 +09:00
|
|
|
|
let header_shape = LoopHeaderShape::new_manual(ctx.pinned_ids.clone(), ctx.carrier_ids.clone());
|
2025-11-24 14:17:02 +09:00
|
|
|
|
let loop_params = header_shape.to_loop_step_params();
|
|
|
|
|
|
let mut loop_step_func =
|
|
|
|
|
|
JoinFunction::new(loop_step_id, "loop_step".to_string(), loop_params.clone());
|
|
|
|
|
|
|
|
|
|
|
|
let cmp_result = value_id_ranges::funcscanner_append_defs::loop_step(10);
|
|
|
|
|
|
loop_step_func
|
|
|
|
|
|
.body
|
|
|
|
|
|
.push(JoinInst::Compute(MirLikeInst::Compare {
|
|
|
|
|
|
dst: cmp_result,
|
|
|
|
|
|
op: CompareOp::Ge,
|
|
|
|
|
|
lhs: i_loop,
|
|
|
|
|
|
rhs: n_loop,
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
2025-11-25 06:32:08 +09:00
|
|
|
|
let _exit_shape = LoopExitShape::new_manual(ctx.exit_args.clone());
|
2025-11-24 14:17:02 +09:00
|
|
|
|
|
|
|
|
|
|
loop_step_func.body.push(JoinInst::Jump {
|
|
|
|
|
|
cont: JoinContId::new(0),
|
2025-11-25 06:32:08 +09:00
|
|
|
|
args: ctx.exit_args.clone(),
|
2025-11-24 14:17:02 +09:00
|
|
|
|
cond: Some(cmp_result),
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
let item_value = value_id_ranges::funcscanner_append_defs::loop_step(11);
|
|
|
|
|
|
let next_i = value_id_ranges::funcscanner_append_defs::loop_step(12);
|
|
|
|
|
|
let const_1 = value_id_ranges::funcscanner_append_defs::loop_step(13);
|
|
|
|
|
|
|
|
|
|
|
|
loop_step_func
|
|
|
|
|
|
.body
|
|
|
|
|
|
.push(JoinInst::Compute(MirLikeInst::BoxCall {
|
|
|
|
|
|
dst: Some(item_value),
|
|
|
|
|
|
box_name: "ArrayBox".to_string(),
|
|
|
|
|
|
method: "get".to_string(),
|
|
|
|
|
|
args: vec![defs_loop, i_loop],
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
loop_step_func
|
|
|
|
|
|
.body
|
|
|
|
|
|
.push(JoinInst::Compute(MirLikeInst::BoxCall {
|
|
|
|
|
|
dst: None,
|
|
|
|
|
|
box_name: "ArrayBox".to_string(),
|
|
|
|
|
|
method: "push".to_string(),
|
|
|
|
|
|
args: vec![dst_loop, item_value],
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
loop_step_func
|
|
|
|
|
|
.body
|
|
|
|
|
|
.push(JoinInst::Compute(MirLikeInst::Const {
|
|
|
|
|
|
dst: const_1,
|
|
|
|
|
|
value: ConstValue::Integer(1),
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
loop_step_func
|
|
|
|
|
|
.body
|
|
|
|
|
|
.push(JoinInst::Compute(MirLikeInst::BinOp {
|
|
|
|
|
|
dst: next_i,
|
|
|
|
|
|
op: BinOpKind::Add,
|
|
|
|
|
|
lhs: i_loop,
|
|
|
|
|
|
rhs: const_1,
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
loop_step_func.body.push(JoinInst::Call {
|
|
|
|
|
|
func: loop_step_id,
|
|
|
|
|
|
args: vec![dst_loop, defs_loop, n_loop, next_i],
|
|
|
|
|
|
k_next: None,
|
|
|
|
|
|
dst: None,
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
join_module.add_function(loop_step_func);
|
|
|
|
|
|
|
|
|
|
|
|
eprintln!(
|
|
|
|
|
|
"[joinir/generic_case_a/append_defs] ✅ constructed JoinIR (functions={}, value_range={}..{})",
|
|
|
|
|
|
join_module.functions.len(),
|
|
|
|
|
|
value_id_ranges::base::FUNCSCANNER_APPEND_DEFS,
|
|
|
|
|
|
value_id_ranges::base::FUNCSCANNER_APPEND_DEFS + 1999
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
Some(join_module)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Stage1UsingResolver minimal 用の generic Case A ロワー(LoopForm/VarClass/ExitLiveness ベース)
|
|
|
|
|
|
pub fn lower_case_a_loop_to_joinir_for_stage1_usingresolver_minimal(
|
|
|
|
|
|
loop_form: &LoopForm,
|
|
|
|
|
|
var_classes: &LoopVarClassBox,
|
|
|
|
|
|
exit_live: &LoopExitLivenessBox,
|
|
|
|
|
|
query: &impl MirQuery,
|
|
|
|
|
|
mir_func: &MirFunction,
|
|
|
|
|
|
) -> Option<JoinModule> {
|
2025-11-25 06:32:08 +09:00
|
|
|
|
// CaseAContext で共通ロジックを実行
|
|
|
|
|
|
let ctx = CaseAContext::new(
|
|
|
|
|
|
loop_form,
|
|
|
|
|
|
var_classes,
|
|
|
|
|
|
exit_live,
|
|
|
|
|
|
query,
|
|
|
|
|
|
mir_func,
|
|
|
|
|
|
"stage1",
|
|
|
|
|
|
|offset| stage1_vid::loop_step(offset),
|
|
|
|
|
|
)?;
|
|
|
|
|
|
|
|
|
|
|
|
let entries_key = ctx.pinned_name_or_first(0)?;
|
|
|
|
|
|
let n_key = ctx.pinned_name_or_first(1).unwrap_or_else(|| entries_key.clone());
|
|
|
|
|
|
let modules_key = ctx.pinned_name_or_first(2).unwrap_or_else(|| entries_key.clone());
|
|
|
|
|
|
let seen_key = ctx.pinned_name_or_first(3).unwrap_or_else(|| entries_key.clone());
|
|
|
|
|
|
let prefix_key = ctx.carrier_name_or_first(0)?;
|
|
|
|
|
|
let i_key = ctx.carrier_name_or_first(1).unwrap_or_else(|| prefix_key.clone());
|
|
|
|
|
|
|
|
|
|
|
|
let entries_loop = ctx.get_loop_id(&entries_key)?;
|
|
|
|
|
|
let n_loop = ctx.get_loop_id(&n_key)?;
|
|
|
|
|
|
let modules_loop = ctx.get_loop_id(&modules_key)?;
|
|
|
|
|
|
let seen_loop = ctx.get_loop_id(&seen_key)?;
|
|
|
|
|
|
let prefix_loop = ctx.get_loop_id(&prefix_key)?;
|
|
|
|
|
|
let i_loop = ctx.get_loop_id(&i_key)?;
|
2025-11-24 14:17:02 +09:00
|
|
|
|
|
|
|
|
|
|
let mut join_module = JoinModule::new();
|
|
|
|
|
|
|
|
|
|
|
|
// entry: resolve_entries(entries, n, modules, seen, prefix_init)
|
|
|
|
|
|
let resolve_id = JoinFuncId::new(0);
|
|
|
|
|
|
let entries_param = stage1_vid::entry(0);
|
|
|
|
|
|
let n_param = stage1_vid::entry(1);
|
|
|
|
|
|
let modules_param = stage1_vid::entry(2);
|
|
|
|
|
|
let seen_param = stage1_vid::entry(3);
|
|
|
|
|
|
let prefix_param = stage1_vid::entry(4);
|
|
|
|
|
|
let mut resolve_func = JoinFunction::new(
|
|
|
|
|
|
resolve_id,
|
|
|
|
|
|
"resolve_entries".to_string(),
|
|
|
|
|
|
vec![
|
|
|
|
|
|
entries_param,
|
|
|
|
|
|
n_param,
|
|
|
|
|
|
modules_param,
|
|
|
|
|
|
seen_param,
|
|
|
|
|
|
prefix_param,
|
|
|
|
|
|
],
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
let i_init = stage1_vid::entry(10);
|
|
|
|
|
|
resolve_func
|
|
|
|
|
|
.body
|
|
|
|
|
|
.push(JoinInst::Compute(MirLikeInst::Const {
|
|
|
|
|
|
dst: i_init,
|
|
|
|
|
|
value: ConstValue::Integer(0),
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
let mut entry_name_to_id: BTreeMap<String, ValueId> = BTreeMap::new();
|
|
|
|
|
|
entry_name_to_id.insert(entries_key.clone(), entries_param);
|
|
|
|
|
|
entry_name_to_id.insert(n_key.clone(), n_param);
|
|
|
|
|
|
entry_name_to_id.insert(modules_key.clone(), modules_param);
|
|
|
|
|
|
entry_name_to_id.insert(seen_key.clone(), seen_param);
|
|
|
|
|
|
entry_name_to_id.insert(prefix_key.clone(), prefix_param);
|
|
|
|
|
|
entry_name_to_id.insert(i_key.clone(), i_init);
|
|
|
|
|
|
|
2025-11-25 06:32:08 +09:00
|
|
|
|
let loop_call_args: Vec<ValueId> = ctx
|
|
|
|
|
|
.ordered_pinned
|
2025-11-24 14:17:02 +09:00
|
|
|
|
.iter()
|
2025-11-25 06:32:08 +09:00
|
|
|
|
.chain(ctx.ordered_carriers.iter())
|
2025-11-24 14:17:02 +09:00
|
|
|
|
.map(|name| entry_name_to_id.get(name).copied())
|
|
|
|
|
|
.collect::<Option<_>>()?;
|
|
|
|
|
|
|
|
|
|
|
|
let loop_step_id = JoinFuncId::new(1);
|
|
|
|
|
|
resolve_func.body.push(JoinInst::Call {
|
|
|
|
|
|
func: loop_step_id,
|
|
|
|
|
|
args: loop_call_args,
|
|
|
|
|
|
k_next: None,
|
|
|
|
|
|
dst: None,
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
join_module.entry = Some(resolve_id);
|
|
|
|
|
|
join_module.add_function(resolve_func);
|
|
|
|
|
|
|
|
|
|
|
|
// loop_step(entries, n, modules, seen, prefix, i)
|
2025-11-25 06:32:08 +09:00
|
|
|
|
let header_shape = LoopHeaderShape::new_manual(ctx.pinned_ids.clone(), ctx.carrier_ids.clone());
|
2025-11-24 14:17:02 +09:00
|
|
|
|
let loop_params = header_shape.to_loop_step_params();
|
|
|
|
|
|
let mut loop_step_func =
|
|
|
|
|
|
JoinFunction::new(loop_step_id, "loop_step".to_string(), loop_params.clone());
|
|
|
|
|
|
|
|
|
|
|
|
let cmp_result = stage1_vid::loop_step(10);
|
|
|
|
|
|
loop_step_func
|
|
|
|
|
|
.body
|
|
|
|
|
|
.push(JoinInst::Compute(MirLikeInst::Compare {
|
|
|
|
|
|
dst: cmp_result,
|
|
|
|
|
|
op: CompareOp::Ge,
|
|
|
|
|
|
lhs: i_loop,
|
|
|
|
|
|
rhs: n_loop,
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
2025-11-25 06:32:08 +09:00
|
|
|
|
let exit_shape = if ctx.exit_args.is_empty() {
|
2025-11-24 14:17:02 +09:00
|
|
|
|
LoopExitShape::new_manual(vec![prefix_loop])
|
|
|
|
|
|
} else {
|
2025-11-25 06:32:08 +09:00
|
|
|
|
LoopExitShape::new_manual(ctx.exit_args.clone())
|
2025-11-24 14:17:02 +09:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
loop_step_func.body.push(JoinInst::Jump {
|
|
|
|
|
|
cont: JoinContId::new(0),
|
|
|
|
|
|
args: exit_shape.exit_args.clone(),
|
|
|
|
|
|
cond: Some(cmp_result),
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
let entry_value = stage1_vid::loop_step(11);
|
|
|
|
|
|
let next_i = stage1_vid::loop_step(12);
|
|
|
|
|
|
let const_1 = stage1_vid::loop_step(13);
|
|
|
|
|
|
let new_prefix = stage1_vid::loop_step(14);
|
|
|
|
|
|
|
|
|
|
|
|
loop_step_func
|
|
|
|
|
|
.body
|
|
|
|
|
|
.push(JoinInst::Compute(MirLikeInst::BoxCall {
|
|
|
|
|
|
dst: Some(entry_value),
|
|
|
|
|
|
box_name: "ArrayBox".to_string(),
|
|
|
|
|
|
method: "get".to_string(),
|
|
|
|
|
|
args: vec![entries_loop, i_loop],
|
|
|
|
|
|
}));
|
|
|
|
|
|
loop_step_func
|
|
|
|
|
|
.body
|
|
|
|
|
|
.push(JoinInst::Compute(MirLikeInst::Const {
|
|
|
|
|
|
dst: const_1,
|
|
|
|
|
|
value: ConstValue::Integer(1),
|
|
|
|
|
|
}));
|
|
|
|
|
|
loop_step_func
|
|
|
|
|
|
.body
|
|
|
|
|
|
.push(JoinInst::Compute(MirLikeInst::BinOp {
|
|
|
|
|
|
dst: next_i,
|
|
|
|
|
|
op: BinOpKind::Add,
|
|
|
|
|
|
lhs: i_loop,
|
|
|
|
|
|
rhs: const_1,
|
|
|
|
|
|
}));
|
|
|
|
|
|
loop_step_func
|
|
|
|
|
|
.body
|
|
|
|
|
|
.push(JoinInst::Compute(MirLikeInst::BinOp {
|
|
|
|
|
|
dst: new_prefix,
|
|
|
|
|
|
op: BinOpKind::Or,
|
|
|
|
|
|
lhs: prefix_loop,
|
|
|
|
|
|
rhs: entry_value,
|
|
|
|
|
|
}));
|
|
|
|
|
|
loop_step_func.body.push(JoinInst::Call {
|
|
|
|
|
|
func: loop_step_id,
|
|
|
|
|
|
args: vec![
|
|
|
|
|
|
entries_loop,
|
|
|
|
|
|
n_loop,
|
|
|
|
|
|
modules_loop,
|
|
|
|
|
|
seen_loop,
|
|
|
|
|
|
new_prefix,
|
|
|
|
|
|
next_i,
|
|
|
|
|
|
],
|
|
|
|
|
|
k_next: None,
|
|
|
|
|
|
dst: None,
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
join_module.add_function(loop_step_func);
|
|
|
|
|
|
|
|
|
|
|
|
eprintln!(
|
|
|
|
|
|
"[joinir/generic_case_a/stage1] ✅ constructed JoinIR (functions={}, value_range={}..{})",
|
|
|
|
|
|
join_module.functions.len(),
|
|
|
|
|
|
value_id_ranges::base::STAGE1_USING_RESOLVER,
|
|
|
|
|
|
value_id_ranges::base::STAGE1_USING_RESOLVER + 1999
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
Some(join_module)
|
|
|
|
|
|
}
|