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:
nyash-codex
2025-11-21 06:25:17 +09:00
parent baf028a94f
commit f9d100ce01
366 changed files with 14322 additions and 5236 deletions

View File

@ -31,28 +31,38 @@ impl MirBuilder {
let changed_set: HashSet<String> = conservative.changed_vars.iter().cloned().collect();
// Use PhiMergeHelper for unified variable merging
let mut helper = super::phi_merge::PhiMergeHelper::new(
self,
then_exit_block_opt,
else_exit_block_opt,
);
let mut helper =
super::phi_merge::PhiMergeHelper::new(self, then_exit_block_opt, else_exit_block_opt);
helper.merge_all_vars(pre_if_snapshot, then_map_end, else_map_end_opt, skip_var)?;
// Ensure pinned synthetic slots ("__pin$...") have a block-local definition at the merge,
// even if their values did not change across branches. This avoids undefined uses when
// subsequent blocks re-use pinned values without modifications.
for (pin_name, pre_val) in pre_if_snapshot.iter() {
if !pin_name.starts_with("__pin$") { continue; }
if skip_var.map(|s| s == pin_name.as_str()).unwrap_or(false) { continue; }
if changed_set.contains(pin_name) { continue; }
let then_v = then_map_end.get(pin_name.as_str()).copied().unwrap_or(*pre_val);
if !pin_name.starts_with("__pin$") {
continue;
}
if skip_var.map(|s| s == pin_name.as_str()).unwrap_or(false) {
continue;
}
if changed_set.contains(pin_name) {
continue;
}
let then_v = then_map_end
.get(pin_name.as_str())
.copied()
.unwrap_or(*pre_val);
let else_v = else_map_end_opt
.as_ref()
.and_then(|m| m.get(pin_name.as_str()).copied())
.unwrap_or(*pre_val);
let mut inputs: Vec<(super::BasicBlockId, super::ValueId)> = Vec::new();
if let Some(tp) = then_exit_block_opt { inputs.push((tp, then_v)); }
if let Some(ep) = else_exit_block_opt { inputs.push((ep, else_v)); }
if let Some(tp) = then_exit_block_opt {
inputs.push((tp, then_v));
}
if let Some(ep) = else_exit_block_opt {
inputs.push((ep, else_v));
}
match inputs.len() {
0 => {}
1 => {
@ -60,15 +70,27 @@ impl MirBuilder {
self.variable_map.insert(pin_name.clone(), v);
}
_ => {
if let Some(func) = self.current_function.as_mut() { func.update_cfg(); }
if let (Some(func), Some(cur_bb)) = (&self.current_function, self.current_block) {
crate::mir::phi_core::common::debug_verify_phi_inputs(func, cur_bb, &inputs);
if let Some(func) = self.current_function.as_mut() {
func.update_cfg();
}
if let (Some(func), Some(cur_bb)) = (&self.current_function, self.current_block)
{
crate::mir::phi_core::common::debug_verify_phi_inputs(
func, cur_bb, &inputs,
);
}
let merged = self.next_value_id();
if let (Some(func), Some(cur_bb)) = (self.current_function.as_mut(), self.current_block) {
crate::mir::ssot::cf_common::insert_phi_at_head(func, cur_bb, merged, inputs);
if let (Some(func), Some(cur_bb)) =
(self.current_function.as_mut(), self.current_block)
{
crate::mir::ssot::cf_common::insert_phi_at_head(
func, cur_bb, merged, inputs,
);
} else {
self.emit_instruction(MirInstruction::Phi { dst: merged, inputs })?;
self.emit_instruction(MirInstruction::Phi {
dst: merged,
inputs,
})?;
}
self.variable_map.insert(pin_name.clone(), merged);
}
@ -95,7 +117,8 @@ impl MirBuilder {
) -> Result<ValueId, String> {
// If only the then-branch assigns a variable (e.g., `if c { x = ... }`) and the else
// does not assign the same variable, bind that variable to a Phi of (then_value, pre_if_value).
let assigned_var_then = crate::mir::phi_core::if_phi::extract_assigned_var(then_ast_for_analysis);
let assigned_var_then =
crate::mir::phi_core::if_phi::extract_assigned_var(then_ast_for_analysis);
let assigned_var_else = else_ast_for_analysis
.as_ref()
.and_then(|a| crate::mir::phi_core::if_phi::extract_assigned_var(a));
@ -131,8 +154,12 @@ impl MirBuilder {
};
// Build inputs from reachable predecessors only
let mut inputs: Vec<(BasicBlockId, ValueId)> = Vec::new();
if let Some(tp) = then_exit_block_opt { inputs.push((tp, then_value_for_var)); }
if let Some(ep) = else_exit_block_opt { inputs.push((ep, else_value_for_var)); }
if let Some(tp) = then_exit_block_opt {
inputs.push((tp, then_value_for_var));
}
if let Some(ep) = else_exit_block_opt {
inputs.push((ep, else_value_for_var));
}
match inputs.len() {
0 => {}
1 => {
@ -142,9 +169,14 @@ impl MirBuilder {
return Ok(inputs[0].1);
}
_ => {
if let Some(func) = self.current_function.as_mut() { func.update_cfg(); }
if let (Some(func), Some(cur_bb)) = (&self.current_function, self.current_block) {
crate::mir::phi_core::common::debug_verify_phi_inputs(func, cur_bb, &inputs);
if let Some(func) = self.current_function.as_mut() {
func.update_cfg();
}
if let (Some(func), Some(cur_bb)) = (&self.current_function, self.current_block)
{
crate::mir::phi_core::common::debug_verify_phi_inputs(
func, cur_bb, &inputs,
);
}
self.insert_phi_with_dst(result_val, inputs)?;
}
@ -154,10 +186,15 @@ impl MirBuilder {
} else {
// No variable assignment pattern detected just emit Phi for expression result
let mut inputs: Vec<(BasicBlockId, ValueId)> = Vec::new();
if let Some(tp) = then_exit_block_opt { inputs.push((tp, then_value_raw)); }
if let Some(ep) = else_exit_block_opt { inputs.push((ep, else_value_raw)); }
if let Some(tp) = then_exit_block_opt {
inputs.push((tp, then_value_raw));
}
if let Some(ep) = else_exit_block_opt {
inputs.push((ep, else_value_raw));
}
match inputs.len() {
0 => { /* leave result_val as fresh, but unused; synthesize void */
0 => {
/* leave result_val as fresh, but unused; synthesize void */
let v = crate::mir::builder::emission::constant::emit_void(self);
return Ok(v);
}
@ -165,9 +202,14 @@ impl MirBuilder {
return Ok(inputs[0].1);
}
_ => {
if let Some(func) = self.current_function.as_mut() { func.update_cfg(); }
if let (Some(func), Some(cur_bb)) = (&self.current_function, self.current_block) {
crate::mir::phi_core::common::debug_verify_phi_inputs(func, cur_bb, &inputs);
if let Some(func) = self.current_function.as_mut() {
func.update_cfg();
}
if let (Some(func), Some(cur_bb)) = (&self.current_function, self.current_block)
{
crate::mir::phi_core::common::debug_verify_phi_inputs(
func, cur_bb, &inputs,
);
}
self.insert_phi_with_dst(result_val, inputs)?;
}