chore: Phase 25.1 完了 - LoopForm v2/Stage1 CLI/環境変数削減 + Phase 26-D からの変更
Phase 25.1 完了成果: - ✅ LoopForm v2 テスト・ドキュメント・コメント完備 - 4ケース(A/B/C/D)完全テストカバレッジ - 最小再現ケース作成(SSAバグ調査用) - SSOT文書作成(loopform_ssot.md) - 全ソースに [LoopForm] コメントタグ追加 - ✅ Stage-1 CLI デバッグ環境構築 - stage1_cli.hako 実装 - stage1_bridge.rs ブリッジ実装 - デバッグツール作成(stage1_debug.sh/stage1_minimal.sh) - アーキテクチャ改善提案文書 - ✅ 環境変数削減計画策定 - 25変数の完全調査・分類 - 6段階削減ロードマップ(25→5、80%削減) - 即時削除可能変数特定(NYASH_CONFIG/NYASH_DEBUG) Phase 26-D からの累積変更: - PHI実装改善(ExitPhiBuilder/HeaderPhiBuilder等) - MIRビルダーリファクタリング - 型伝播・最適化パス改善 - その他約300ファイルの累積変更 🎯 技術的成果: - SSAバグ根本原因特定(条件分岐内loop変数変更) - Region+next_iパターン適用完了(UsingCollectorBox等) - LoopFormパターン文書化・テスト化完了 - セルフホスティング基盤強化 Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: ChatGPT <noreply@openai.com> Co-Authored-By: Task Assistant <task@anthropic.com>
This commit is contained in:
@ -1,9 +1,7 @@
|
||||
use super::{
|
||||
lower_stmt_list_with_vars, new_block, BridgeEnv, LoopContext,
|
||||
};
|
||||
use super::super::ast::{CatchV0, StmtV0};
|
||||
use super::{lower_stmt_list_with_vars, new_block, BridgeEnv, LoopContext};
|
||||
use crate::mir::{BasicBlockId, MirFunction, MirInstruction, ValueId};
|
||||
use std::collections::HashMap;
|
||||
use super::super::ast::{StmtV0, CatchV0};
|
||||
|
||||
pub(super) fn lower_try_stmt(
|
||||
f: &mut MirFunction,
|
||||
@ -23,9 +21,23 @@ pub(super) fn lower_try_stmt(
|
||||
if catches.len() > 1 {
|
||||
// Fallback to safe lowering (ignore catches) for multi-catch
|
||||
let mut tmp_vars = vars.clone();
|
||||
let mut next_bb = super::lower_stmt_list_with_vars(f, cur_bb, try_body, &mut tmp_vars, loop_stack, env)?;
|
||||
let mut next_bb = super::lower_stmt_list_with_vars(
|
||||
f,
|
||||
cur_bb,
|
||||
try_body,
|
||||
&mut tmp_vars,
|
||||
loop_stack,
|
||||
env,
|
||||
)?;
|
||||
if !finally.is_empty() {
|
||||
next_bb = super::lower_stmt_list_with_vars(f, next_bb, finally, &mut tmp_vars, loop_stack, env)?;
|
||||
next_bb = super::lower_stmt_list_with_vars(
|
||||
f,
|
||||
next_bb,
|
||||
finally,
|
||||
&mut tmp_vars,
|
||||
loop_stack,
|
||||
env,
|
||||
)?;
|
||||
}
|
||||
*vars = tmp_vars;
|
||||
return Ok(next_bb);
|
||||
@ -34,29 +46,47 @@ pub(super) fn lower_try_stmt(
|
||||
let base_vars = vars.clone();
|
||||
let try_bb = new_block(f);
|
||||
let catch_bb_opt = if has_catch { Some(new_block(f)) } else { None };
|
||||
let finally_bb = if !finally.is_empty() { Some(new_block(f)) } else { None };
|
||||
let finally_bb = if !finally.is_empty() {
|
||||
Some(new_block(f))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let exit_bb = new_block(f);
|
||||
|
||||
f.set_jump_terminator(cur_bb, try_bb)?;
|
||||
if let Some(succ) = f.get_block_mut(try_bb) { succ.add_predecessor(cur_bb); }
|
||||
if let Some(succ) = f.get_block_mut(try_bb) {
|
||||
succ.add_predecessor(cur_bb);
|
||||
}
|
||||
|
||||
// Install thread-local throw context so nested throw expressions jump to catch_bb
|
||||
if has_catch {
|
||||
let catch_bb = catch_bb_opt.expect("catch_bb must exist when has_catch");
|
||||
if crate::config::env::cli_verbose() {
|
||||
eprintln!("[Bridge] try_result_mode: set ThrowCtx (catch_bb={:?})", catch_bb);
|
||||
eprintln!(
|
||||
"[Bridge] try_result_mode: set ThrowCtx (catch_bb={:?})",
|
||||
catch_bb
|
||||
);
|
||||
}
|
||||
super::throw_ctx::set(catch_bb);
|
||||
} else if crate::config::env::cli_verbose() {
|
||||
eprintln!("[Bridge] try_result_mode: no catch present; ThrowCtx not set");
|
||||
}
|
||||
let mut try_vars = base_vars.clone();
|
||||
let try_end = super::lower_stmt_list_with_vars(f, try_bb, try_body, &mut try_vars, loop_stack, env)?;
|
||||
let try_end =
|
||||
super::lower_stmt_list_with_vars(f, try_bb, try_body, &mut try_vars, loop_stack, env)?;
|
||||
// Take recorded incoming exceptions
|
||||
let incoming_exc = if has_catch { super::throw_ctx::take().map(|c| c.incoming).unwrap_or_default() } else { Vec::new() };
|
||||
let incoming_exc = if has_catch {
|
||||
super::throw_ctx::take()
|
||||
.map(|c| c.incoming)
|
||||
.unwrap_or_default()
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
let target = finally_bb.unwrap_or(exit_bb);
|
||||
f.set_jump_terminator(try_end, target)?;
|
||||
if let Some(succ) = f.get_block_mut(target) { succ.add_predecessor(try_end); }
|
||||
if let Some(succ) = f.get_block_mut(target) {
|
||||
succ.add_predecessor(try_end);
|
||||
}
|
||||
let try_branch_vars = try_vars.clone();
|
||||
|
||||
// Lower catch block if present and reachable
|
||||
@ -72,7 +102,9 @@ pub(super) fn lower_try_stmt(
|
||||
if let Some(_bb) = f.get_block_mut(catch_bb) {
|
||||
let mut inputs = incoming_exc.clone();
|
||||
inputs.sort_by_key(|(bbid, _)| bbid.0);
|
||||
crate::mir::ssot::cf_common::insert_phi_at_head(f, catch_bb, phi_dst, inputs);
|
||||
crate::mir::ssot::cf_common::insert_phi_at_head(
|
||||
f, catch_bb, phi_dst, inputs,
|
||||
);
|
||||
}
|
||||
catch_vars.insert(param.clone(), phi_dst);
|
||||
}
|
||||
@ -87,7 +119,9 @@ pub(super) fn lower_try_stmt(
|
||||
)?;
|
||||
let target = finally_bb.unwrap_or(exit_bb);
|
||||
f.set_jump_terminator(end, target)?;
|
||||
if let Some(succ) = f.get_block_mut(target) { succ.add_predecessor(end); }
|
||||
if let Some(succ) = f.get_block_mut(target) {
|
||||
succ.add_predecessor(end);
|
||||
}
|
||||
(end, catch_vars)
|
||||
} else {
|
||||
(try_end, base_vars.clone())
|
||||
@ -98,21 +132,30 @@ pub(super) fn lower_try_stmt(
|
||||
if let Some(finally_block) = finally_bb {
|
||||
// Compute merged var map from try_end + catch_end (if has_catch)
|
||||
let branch_vars: Vec<(BasicBlockId, HashMap<String, ValueId>)> = if has_catch {
|
||||
vec![(try_end, try_branch_vars.clone()), (catch_end, catch_branch_vars.clone())]
|
||||
vec![
|
||||
(try_end, try_branch_vars.clone()),
|
||||
(catch_end, catch_branch_vars.clone()),
|
||||
]
|
||||
} else {
|
||||
vec![(try_end, try_branch_vars.clone())]
|
||||
};
|
||||
let mut names: HashSet<String> = base_vars.keys().cloned().collect();
|
||||
for (_, map) in &branch_vars { names.extend(map.keys().cloned()); }
|
||||
for (_, map) in &branch_vars {
|
||||
names.extend(map.keys().cloned());
|
||||
}
|
||||
let mut merged_vars = base_vars.clone();
|
||||
let mut phi_entries: Vec<(ValueId, Vec<(BasicBlockId, ValueId)>)> = Vec::new();
|
||||
for name in names {
|
||||
let mut inputs: Vec<(BasicBlockId, ValueId)> = Vec::new();
|
||||
for (bbid, map) in &branch_vars {
|
||||
if let Some(&v) = map.get(&name) { inputs.push((*bbid, v)); }
|
||||
if let Some(&v) = map.get(&name) {
|
||||
inputs.push((*bbid, v));
|
||||
}
|
||||
}
|
||||
if inputs.is_empty() {
|
||||
if let Some(&b) = base_vars.get(&name) { merged_vars.insert(name.clone(), b); }
|
||||
if let Some(&b) = base_vars.get(&name) {
|
||||
merged_vars.insert(name.clone(), b);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
let uniq: HashSet<ValueId> = inputs.iter().map(|(_, v)| *v).collect();
|
||||
@ -126,12 +169,23 @@ pub(super) fn lower_try_stmt(
|
||||
merged_vars.insert(name.clone(), dst);
|
||||
}
|
||||
if let Some(_bb) = f.get_block_mut(finally_block) {
|
||||
for (dst, inputs) in phi_entries { crate::mir::ssot::cf_common::insert_phi_at_head(f, finally_block, dst, inputs); }
|
||||
for (dst, inputs) in phi_entries {
|
||||
crate::mir::ssot::cf_common::insert_phi_at_head(f, finally_block, dst, inputs);
|
||||
}
|
||||
}
|
||||
let mut finally_vars = merged_vars.clone();
|
||||
let final_end = super::lower_stmt_list_with_vars(f, finally_block, finally, &mut finally_vars, loop_stack, env)?;
|
||||
let final_end = super::lower_stmt_list_with_vars(
|
||||
f,
|
||||
finally_block,
|
||||
finally,
|
||||
&mut finally_vars,
|
||||
loop_stack,
|
||||
env,
|
||||
)?;
|
||||
f.set_jump_terminator(final_end, exit_bb)?;
|
||||
if let Some(succ) = f.get_block_mut(exit_bb) { succ.add_predecessor(final_end); }
|
||||
if let Some(succ) = f.get_block_mut(exit_bb) {
|
||||
succ.add_predecessor(final_end);
|
||||
}
|
||||
*vars = finally_vars;
|
||||
return Ok(exit_bb);
|
||||
} else {
|
||||
@ -142,38 +196,49 @@ pub(super) fn lower_try_stmt(
|
||||
vec![(try_end, try_branch_vars)]
|
||||
};
|
||||
let mut names: HashSet<String> = base_vars.keys().cloned().collect();
|
||||
for (_, map) in &branch_vars { names.extend(map.keys().cloned()); }
|
||||
for (_, map) in &branch_vars {
|
||||
names.extend(map.keys().cloned());
|
||||
}
|
||||
let mut merged_vars = base_vars.clone();
|
||||
let mut phi_entries: Vec<(ValueId, Vec<(BasicBlockId, ValueId)>)> = Vec::new();
|
||||
for name in names {
|
||||
let mut inputs: Vec<(BasicBlockId, ValueId)> = Vec::new();
|
||||
for (bbid, map) in &branch_vars { if let Some(&v) = map.get(&name) { inputs.push((*bbid, v)); } }
|
||||
if inputs.is_empty() { if let Some(&b) = base_vars.get(&name) { merged_vars.insert(name.clone(), b); } continue; }
|
||||
for (bbid, map) in &branch_vars {
|
||||
if let Some(&v) = map.get(&name) {
|
||||
inputs.push((*bbid, v));
|
||||
}
|
||||
}
|
||||
if inputs.is_empty() {
|
||||
if let Some(&b) = base_vars.get(&name) {
|
||||
merged_vars.insert(name.clone(), b);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
let uniq: HashSet<ValueId> = inputs.iter().map(|(_, v)| *v).collect();
|
||||
if uniq.len() == 1 { merged_vars.insert(name.clone(), inputs[0].1); continue; }
|
||||
if uniq.len() == 1 {
|
||||
merged_vars.insert(name.clone(), inputs[0].1);
|
||||
continue;
|
||||
}
|
||||
let dst = f.next_value_id();
|
||||
inputs.sort_by_key(|(bbid, _)| bbid.0);
|
||||
phi_entries.push((dst, inputs));
|
||||
merged_vars.insert(name.clone(), dst);
|
||||
}
|
||||
if let Some(_bb) = f.get_block_mut(exit_bb) {
|
||||
for (dst, inputs) in phi_entries { crate::mir::ssot::cf_common::insert_phi_at_head(f, exit_bb, dst, inputs); }
|
||||
for (dst, inputs) in phi_entries {
|
||||
crate::mir::ssot::cf_common::insert_phi_at_head(f, exit_bb, dst, inputs);
|
||||
}
|
||||
}
|
||||
*vars = merged_vars;
|
||||
return Ok(exit_bb);
|
||||
}
|
||||
} else if !try_enabled || catches.is_empty() || catches.len() > 1 {
|
||||
let mut tmp_vars = vars.clone();
|
||||
let mut next_bb = lower_stmt_list_with_vars(f, cur_bb, try_body, &mut tmp_vars, loop_stack, env)?;
|
||||
let mut next_bb =
|
||||
lower_stmt_list_with_vars(f, cur_bb, try_body, &mut tmp_vars, loop_stack, env)?;
|
||||
if !finally.is_empty() {
|
||||
next_bb = lower_stmt_list_with_vars(
|
||||
f,
|
||||
next_bb,
|
||||
finally,
|
||||
&mut tmp_vars,
|
||||
loop_stack,
|
||||
env,
|
||||
)?;
|
||||
next_bb =
|
||||
lower_stmt_list_with_vars(f, next_bb, finally, &mut tmp_vars, loop_stack, env)?;
|
||||
}
|
||||
*vars = tmp_vars;
|
||||
return Ok(next_bb);
|
||||
@ -260,7 +325,9 @@ pub(super) fn lower_try_stmt(
|
||||
}
|
||||
// フェーズM.2: PHI統一処理(no_phi分岐削除)
|
||||
if let Some(_bb) = f.get_block_mut(finally_block) {
|
||||
for (dst, inputs) in phi_entries { crate::mir::ssot::cf_common::insert_phi_at_head(f, finally_block, dst, inputs); }
|
||||
for (dst, inputs) in phi_entries {
|
||||
crate::mir::ssot::cf_common::insert_phi_at_head(f, finally_block, dst, inputs);
|
||||
}
|
||||
}
|
||||
let mut finally_vars = merged_vars.clone();
|
||||
let final_end = lower_stmt_list_with_vars(
|
||||
@ -309,7 +376,9 @@ pub(super) fn lower_try_stmt(
|
||||
}
|
||||
// フェーズM.2: PHI統一処理(no_phi分岐削除)
|
||||
if let Some(_bb) = f.get_block_mut(exit_bb) {
|
||||
for (dst, inputs) in phi_entries { crate::mir::ssot::cf_common::insert_phi_at_head(f, exit_bb, dst, inputs); }
|
||||
for (dst, inputs) in phi_entries {
|
||||
crate::mir::ssot::cf_common::insert_phi_at_head(f, exit_bb, dst, inputs);
|
||||
}
|
||||
}
|
||||
*vars = merged_vars;
|
||||
Ok(exit_bb)
|
||||
|
||||
Reference in New Issue
Block a user