feat(joinir): Phase 61-4-D/E function guard and toplevel emitter
Phase 61-4 追加実装: 1. Phase 61-4-D: 関数名ガード整理 - is_joinir_if_toplevel_target() ヘルパー追加 - IfSelectTest.*, IfToplevelTest.*, IfMergeTest.* 対応 - if_form.rs で関数名チェック統合 2. Phase 61-4-E: emit_toplevel_phis() 追加 - IfInLoopPhiEmitter に toplevel 用メソッド追加 - carrier_names 不要(PhiSpec の全変数を対象) - HAKO_JOINIR_IF_TOPLEVEL_TRACE でトレース可能 現状: - dry-run モードでパターンマッチング確認可能 - 本番経路のPHI生成統合は次フェーズ(MirBuilder PHI emit 方式検討必要) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -154,6 +154,110 @@ impl IfInLoopPhiEmitter {
|
||||
|
||||
Ok(phi_count)
|
||||
}
|
||||
|
||||
/// Phase 61-4: ループ外 If PHI 生成(Toplevel If)
|
||||
///
|
||||
/// ループ外の純粋な if に対して PHI を生成する。
|
||||
/// carrier_names が空のため、PhiSpec の全変数を対象とする。
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `phi_spec` - JoinIR から計算された PHI 仕様
|
||||
/// * `pre_if_var_map` - if 直前の変数マップ
|
||||
/// * `then_snapshot` - then 腕終了時の変数スナップショット
|
||||
/// * `else_snapshot_opt` - else 腕終了時の変数スナップショット
|
||||
/// * `ops` - PHI 生成操作インターフェース
|
||||
/// * `if_shape` - If 構造情報
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// 生成した PHI の数
|
||||
pub fn emit_toplevel_phis<O: PhiBuilderOps>(
|
||||
phi_spec: &PhiSpec,
|
||||
pre_if_var_map: &BTreeMap<String, ValueId>,
|
||||
then_snapshot: &BTreeMap<String, ValueId>,
|
||||
else_snapshot_opt: Option<&BTreeMap<String, ValueId>>,
|
||||
ops: &mut O,
|
||||
if_shape: &IfShape,
|
||||
) -> Result<usize, String> {
|
||||
let mut phi_count = 0;
|
||||
let trace_on =
|
||||
std::env::var("HAKO_JOINIR_IF_TOPLEVEL_TRACE").ok().as_deref() == Some("1");
|
||||
|
||||
if trace_on {
|
||||
eprintln!("[Phase 61-4] IfInLoopPhiEmitter::emit_toplevel_phis start");
|
||||
eprintln!("[Phase 61-4] header_phis: {:?}", phi_spec.header_phis);
|
||||
}
|
||||
|
||||
// Toplevel PHI 生成: PhiSpec の全変数を対象
|
||||
for var_name in &phi_spec.header_phis {
|
||||
// pre_if値を取得
|
||||
let pre_val = match pre_if_var_map.get(var_name) {
|
||||
Some(&v) => v,
|
||||
None => {
|
||||
if trace_on {
|
||||
eprintln!(
|
||||
"[Phase 61-4] ⚠️ var={} not found in pre_if_var_map, skipping",
|
||||
var_name
|
||||
);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
// Then値: snapshot から取得、なければ pre_val
|
||||
let then_val = then_snapshot.get(var_name).copied().unwrap_or(pre_val);
|
||||
|
||||
// Else値: snapshot から取得、なければ pre_val
|
||||
let else_val = else_snapshot_opt
|
||||
.and_then(|m| m.get(var_name).copied())
|
||||
.unwrap_or(pre_val);
|
||||
|
||||
// 値が同一なら PHI 不要
|
||||
if then_val == else_val {
|
||||
if trace_on {
|
||||
eprintln!(
|
||||
"[Phase 61-4] var={}: then_val == else_val ({:?}), no PHI needed",
|
||||
var_name, then_val
|
||||
);
|
||||
}
|
||||
ops.update_var(var_name.clone(), then_val);
|
||||
continue;
|
||||
}
|
||||
|
||||
// PHI 生成
|
||||
let phi_dst = ops.new_value();
|
||||
let mut inputs = Vec::new();
|
||||
|
||||
// Then 入力
|
||||
inputs.push((if_shape.then_block, then_val));
|
||||
|
||||
// Else 入力
|
||||
if let Some(else_bb) = if_shape.else_block {
|
||||
inputs.push((else_bb, else_val));
|
||||
}
|
||||
|
||||
if trace_on {
|
||||
eprintln!(
|
||||
"[Phase 61-4] var={}: emit PHI dst={:?} inputs={:?}",
|
||||
var_name, phi_dst, inputs
|
||||
);
|
||||
}
|
||||
|
||||
ops.emit_phi(if_shape.merge_block, phi_dst, inputs)?;
|
||||
ops.update_var(var_name.clone(), phi_dst);
|
||||
phi_count += 1;
|
||||
}
|
||||
|
||||
if trace_on {
|
||||
eprintln!(
|
||||
"[Phase 61-4] IfInLoopPhiEmitter::emit_toplevel_phis done: {} PHIs",
|
||||
phi_count
|
||||
);
|
||||
}
|
||||
|
||||
Ok(phi_count)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
Reference in New Issue
Block a user