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,6 +1,6 @@
|
||||
use super::{MirInstruction, MirType, ValueId};
|
||||
use crate::mir::loop_api::LoopBuilderApi; // for current_block()
|
||||
use crate::ast::{ASTNode, BinaryOperator};
|
||||
use crate::mir::loop_api::LoopBuilderApi; // for current_block()
|
||||
use crate::mir::{BinaryOp, CompareOp, TypeOpKind, UnaryOp};
|
||||
|
||||
// Internal classification for binary operations
|
||||
@ -38,7 +38,10 @@ impl super::MirBuilder {
|
||||
|
||||
let mir_op = self.convert_binary_operator(operator)?;
|
||||
|
||||
let all_call = std::env::var("NYASH_BUILDER_OPERATOR_BOX_ALL_CALL").ok().as_deref() == Some("1");
|
||||
let all_call = std::env::var("NYASH_BUILDER_OPERATOR_BOX_ALL_CALL")
|
||||
.ok()
|
||||
.as_deref()
|
||||
== Some("1");
|
||||
|
||||
match mir_op {
|
||||
// Arithmetic operations
|
||||
@ -51,11 +54,19 @@ impl super::MirBuilder {
|
||||
.unwrap_or(false);
|
||||
if matches!(op, crate::mir::BinaryOp::Add)
|
||||
&& !in_add_op
|
||||
&& (all_call || std::env::var("NYASH_BUILDER_OPERATOR_BOX_ADD_CALL").ok().as_deref() == Some("1"))
|
||||
&& (all_call
|
||||
|| std::env::var("NYASH_BUILDER_OPERATOR_BOX_ADD_CALL")
|
||||
.ok()
|
||||
.as_deref()
|
||||
== Some("1"))
|
||||
{
|
||||
// AddOperator.apply/2(lhs, rhs)
|
||||
let name = "AddOperator.apply/2".to_string();
|
||||
self.emit_legacy_call(Some(dst), super::builder_calls::CallTarget::Global(name), vec![lhs, rhs])?;
|
||||
self.emit_legacy_call(
|
||||
Some(dst),
|
||||
super::builder_calls::CallTarget::Global(name),
|
||||
vec![lhs, rhs],
|
||||
)?;
|
||||
// 型注釈(従来と同等)
|
||||
let lhs_is_str = match self.value_types.get(&lhs) {
|
||||
Some(MirType::String) => true,
|
||||
@ -81,21 +92,39 @@ impl super::MirBuilder {
|
||||
crate::mir::BinaryOp::Mod => ("ModOperator.apply/2", "ModOperator.apply/"),
|
||||
crate::mir::BinaryOp::Shl => ("ShlOperator.apply/2", "ShlOperator.apply/"),
|
||||
crate::mir::BinaryOp::Shr => ("ShrOperator.apply/2", "ShrOperator.apply/"),
|
||||
crate::mir::BinaryOp::BitAnd => ("BitAndOperator.apply/2", "BitAndOperator.apply/"),
|
||||
crate::mir::BinaryOp::BitOr => ("BitOrOperator.apply/2", "BitOrOperator.apply/"),
|
||||
crate::mir::BinaryOp::BitXor => ("BitXorOperator.apply/2", "BitXorOperator.apply/"),
|
||||
crate::mir::BinaryOp::BitAnd => {
|
||||
("BitAndOperator.apply/2", "BitAndOperator.apply/")
|
||||
}
|
||||
crate::mir::BinaryOp::BitOr => {
|
||||
("BitOrOperator.apply/2", "BitOrOperator.apply/")
|
||||
}
|
||||
crate::mir::BinaryOp::BitXor => {
|
||||
("BitXorOperator.apply/2", "BitXorOperator.apply/")
|
||||
}
|
||||
_ => ("", ""),
|
||||
};
|
||||
if !name.is_empty() {
|
||||
let in_guard = self.current_function.as_ref().map(|f| f.signature.name.starts_with(guard_prefix)).unwrap_or(false);
|
||||
let in_guard = self
|
||||
.current_function
|
||||
.as_ref()
|
||||
.map(|f| f.signature.name.starts_with(guard_prefix))
|
||||
.unwrap_or(false);
|
||||
if !in_guard {
|
||||
self.emit_legacy_call(Some(dst), super::builder_calls::CallTarget::Global(name.to_string()), vec![lhs, rhs])?;
|
||||
self.emit_legacy_call(
|
||||
Some(dst),
|
||||
super::builder_calls::CallTarget::Global(name.to_string()),
|
||||
vec![lhs, rhs],
|
||||
)?;
|
||||
// 型注釈: 算術はおおむね整数(Addは上で注釈済み)
|
||||
self.value_types.insert(dst, MirType::Integer);
|
||||
} else {
|
||||
// guard中は従来のBinOp
|
||||
if let (Some(func), Some(cur_bb)) = (self.current_function.as_mut(), self.current_block) {
|
||||
crate::mir::ssot::binop_lower::emit_binop_to_dst(func, cur_bb, dst, op, lhs, rhs);
|
||||
if let (Some(func), Some(cur_bb)) =
|
||||
(self.current_function.as_mut(), self.current_block)
|
||||
{
|
||||
crate::mir::ssot::binop_lower::emit_binop_to_dst(
|
||||
func, cur_bb, dst, op, lhs, rhs,
|
||||
);
|
||||
} else {
|
||||
self.emit_instruction(MirInstruction::BinOp { dst, op, lhs, rhs })?;
|
||||
}
|
||||
@ -103,8 +132,12 @@ impl super::MirBuilder {
|
||||
}
|
||||
} else {
|
||||
// 既存の算術経路
|
||||
if let (Some(func), Some(cur_bb)) = (self.current_function.as_mut(), self.current_block) {
|
||||
crate::mir::ssot::binop_lower::emit_binop_to_dst(func, cur_bb, dst, op, lhs, rhs);
|
||||
if let (Some(func), Some(cur_bb)) =
|
||||
(self.current_function.as_mut(), self.current_block)
|
||||
{
|
||||
crate::mir::ssot::binop_lower::emit_binop_to_dst(
|
||||
func, cur_bb, dst, op, lhs, rhs,
|
||||
);
|
||||
} else {
|
||||
self.emit_instruction(MirInstruction::BinOp { dst, op, lhs, rhs })?;
|
||||
}
|
||||
@ -130,8 +163,12 @@ impl super::MirBuilder {
|
||||
}
|
||||
} else {
|
||||
// 既存の算術経路
|
||||
if let (Some(func), Some(cur_bb)) = (self.current_function.as_mut(), self.current_block) {
|
||||
crate::mir::ssot::binop_lower::emit_binop_to_dst(func, cur_bb, dst, op, lhs, rhs);
|
||||
if let (Some(func), Some(cur_bb)) =
|
||||
(self.current_function.as_mut(), self.current_block)
|
||||
{
|
||||
crate::mir::ssot::binop_lower::emit_binop_to_dst(
|
||||
func, cur_bb, dst, op, lhs, rhs,
|
||||
);
|
||||
} else {
|
||||
self.emit_instruction(MirInstruction::BinOp { dst, op, lhs, rhs })?;
|
||||
}
|
||||
@ -165,7 +202,12 @@ impl super::MirBuilder {
|
||||
.map(|f| f.signature.name.starts_with("CompareOperator.apply/"))
|
||||
.unwrap_or(false);
|
||||
if !in_cmp_op
|
||||
&& (all_call || std::env::var("NYASH_BUILDER_OPERATOR_BOX_COMPARE_CALL").ok().as_deref() == Some("1")) {
|
||||
&& (all_call
|
||||
|| std::env::var("NYASH_BUILDER_OPERATOR_BOX_COMPARE_CALL")
|
||||
.ok()
|
||||
.as_deref()
|
||||
== Some("1"))
|
||||
{
|
||||
// op名の文字列化
|
||||
let opname = match op {
|
||||
CompareOp::Eq => "Eq",
|
||||
@ -175,10 +217,15 @@ impl super::MirBuilder {
|
||||
CompareOp::Gt => "Gt",
|
||||
CompareOp::Ge => "Ge",
|
||||
};
|
||||
let op_const = crate::mir::builder::emission::constant::emit_string(self, opname);
|
||||
let op_const =
|
||||
crate::mir::builder::emission::constant::emit_string(self, opname);
|
||||
// そのまま値を渡す(型変換/slot化は演算子内orVMで行う)
|
||||
let name = "CompareOperator.apply/3".to_string();
|
||||
self.emit_legacy_call(Some(dst), super::builder_calls::CallTarget::Global(name), vec![op_const, lhs, rhs])?;
|
||||
self.emit_legacy_call(
|
||||
Some(dst),
|
||||
super::builder_calls::CallTarget::Global(name),
|
||||
vec![op_const, lhs, rhs],
|
||||
)?;
|
||||
self.value_types.insert(dst, MirType::Bool);
|
||||
} else {
|
||||
// 既存の比較経路(安全のための型注釈/slot化含む)
|
||||
@ -245,7 +292,9 @@ impl super::MirBuilder {
|
||||
// Branch on LHS truthiness (runtime to_bool semantics in interpreter/LLVM)
|
||||
let mut lhs_cond = self.local_cond(lhs_val);
|
||||
crate::mir::builder::ssa::local::finalize_branch_cond(self, &mut lhs_cond);
|
||||
crate::mir::builder::emission::branch::emit_conditional(self, lhs_cond, then_block, else_block)?;
|
||||
crate::mir::builder::emission::branch::emit_conditional(
|
||||
self, lhs_cond, then_block, else_block,
|
||||
)?;
|
||||
// Record predecessor block for branch (for single-pred PHI materialization)
|
||||
let pre_branch_bb = self.current_block()?;
|
||||
|
||||
@ -273,7 +322,9 @@ impl super::MirBuilder {
|
||||
let rhs_val = self.build_expression(right.clone())?;
|
||||
let mut rhs_cond = self.local_cond(rhs_val);
|
||||
crate::mir::builder::ssa::local::finalize_branch_cond(self, &mut rhs_cond);
|
||||
crate::mir::builder::emission::branch::emit_conditional(self, rhs_cond, rhs_true, rhs_false)?;
|
||||
crate::mir::builder::emission::branch::emit_conditional(
|
||||
self, rhs_cond, rhs_true, rhs_false,
|
||||
)?;
|
||||
// true path
|
||||
self.start_new_block(rhs_true)?;
|
||||
let t_id = crate::mir::builder::emission::constant::emit_bool(self, true);
|
||||
@ -286,7 +337,9 @@ impl super::MirBuilder {
|
||||
let rhs_false_exit = self.current_block()?;
|
||||
// join rhs result into a single bool
|
||||
self.start_new_block(rhs_join)?;
|
||||
if let Some(func) = self.current_function.as_mut() { func.update_cfg(); }
|
||||
if let Some(func) = self.current_function.as_mut() {
|
||||
func.update_cfg();
|
||||
}
|
||||
let rhs_bool = self.insert_phi_binary(rhs_true_exit, t_id, rhs_false_exit, f_id)?;
|
||||
self.value_types.insert(rhs_bool, MirType::Bool);
|
||||
rhs_bool
|
||||
@ -323,7 +376,9 @@ impl super::MirBuilder {
|
||||
let rhs_val = self.build_expression(right)?;
|
||||
let mut rhs_cond = self.local_cond(rhs_val);
|
||||
crate::mir::builder::ssa::local::finalize_branch_cond(self, &mut rhs_cond);
|
||||
crate::mir::builder::emission::branch::emit_conditional(self, rhs_cond, rhs_true, rhs_false)?;
|
||||
crate::mir::builder::emission::branch::emit_conditional(
|
||||
self, rhs_cond, rhs_true, rhs_false,
|
||||
)?;
|
||||
// true path
|
||||
self.start_new_block(rhs_true)?;
|
||||
let t_id = crate::mir::builder::emission::constant::emit_bool(self, true);
|
||||
@ -336,7 +391,9 @@ impl super::MirBuilder {
|
||||
let rhs_false_exit = self.current_block()?;
|
||||
// join rhs result into a single bool
|
||||
self.start_new_block(rhs_join)?;
|
||||
if let Some(func) = self.current_function.as_mut() { func.update_cfg(); }
|
||||
if let Some(func) = self.current_function.as_mut() {
|
||||
func.update_cfg();
|
||||
}
|
||||
let rhs_bool = self.insert_phi_binary(rhs_true_exit, t_id, rhs_false_exit, f_id)?;
|
||||
self.value_types.insert(rhs_bool, MirType::Bool);
|
||||
rhs_bool
|
||||
@ -357,10 +414,16 @@ impl super::MirBuilder {
|
||||
|
||||
// Result PHI (bool) — consider only reachable predecessors
|
||||
let mut inputs: Vec<(crate::mir::BasicBlockId, ValueId)> = Vec::new();
|
||||
if then_reaches_merge { inputs.push((then_exit_block, then_value_raw)); }
|
||||
if else_reaches_merge { inputs.push((else_exit_block, else_value_raw)); }
|
||||
if then_reaches_merge {
|
||||
inputs.push((then_exit_block, then_value_raw));
|
||||
}
|
||||
if else_reaches_merge {
|
||||
inputs.push((else_exit_block, else_value_raw));
|
||||
}
|
||||
let result_val = if inputs.len() >= 2 {
|
||||
if let Some(func) = self.current_function.as_mut() { func.update_cfg(); }
|
||||
if let Some(func) = self.current_function.as_mut() {
|
||||
func.update_cfg();
|
||||
}
|
||||
let dst = self.insert_phi(inputs)?;
|
||||
self.value_types.insert(dst, MirType::Bool);
|
||||
dst
|
||||
@ -375,8 +438,16 @@ impl super::MirBuilder {
|
||||
self.merge_modified_vars(
|
||||
then_block,
|
||||
else_block,
|
||||
if then_reaches_merge { Some(then_exit_block) } else { None },
|
||||
if else_reaches_merge { Some(else_exit_block) } else { None },
|
||||
if then_reaches_merge {
|
||||
Some(then_exit_block)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
if else_reaches_merge {
|
||||
Some(else_exit_block)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
&pre_if_var_map,
|
||||
&then_var_map_end,
|
||||
&Some(else_var_map_end),
|
||||
@ -394,19 +465,38 @@ impl super::MirBuilder {
|
||||
operand: ASTNode,
|
||||
) -> Result<ValueId, String> {
|
||||
let operand_val = self.build_expression(operand)?;
|
||||
let all_call = std::env::var("NYASH_BUILDER_OPERATOR_BOX_ALL_CALL").ok().as_deref() == Some("1");
|
||||
let all_call = std::env::var("NYASH_BUILDER_OPERATOR_BOX_ALL_CALL")
|
||||
.ok()
|
||||
.as_deref()
|
||||
== Some("1");
|
||||
if all_call {
|
||||
let (name, guard_prefix, rett) = match operator.as_str() {
|
||||
"-" => ("NegOperator.apply/1", "NegOperator.apply/", MirType::Integer),
|
||||
"-" => (
|
||||
"NegOperator.apply/1",
|
||||
"NegOperator.apply/",
|
||||
MirType::Integer,
|
||||
),
|
||||
"!" | "not" => ("NotOperator.apply/1", "NotOperator.apply/", MirType::Bool),
|
||||
"~" => ("BitNotOperator.apply/1", "BitNotOperator.apply/", MirType::Integer),
|
||||
"~" => (
|
||||
"BitNotOperator.apply/1",
|
||||
"BitNotOperator.apply/",
|
||||
MirType::Integer,
|
||||
),
|
||||
_ => ("", "", MirType::Integer),
|
||||
};
|
||||
if !name.is_empty() {
|
||||
let in_guard = self.current_function.as_ref().map(|f| f.signature.name.starts_with(guard_prefix)).unwrap_or(false);
|
||||
let in_guard = self
|
||||
.current_function
|
||||
.as_ref()
|
||||
.map(|f| f.signature.name.starts_with(guard_prefix))
|
||||
.unwrap_or(false);
|
||||
let dst = self.next_value_id();
|
||||
if !in_guard {
|
||||
self.emit_legacy_call(Some(dst), super::builder_calls::CallTarget::Global(name.to_string()), vec![operand_val])?;
|
||||
self.emit_legacy_call(
|
||||
Some(dst),
|
||||
super::builder_calls::CallTarget::Global(name.to_string()),
|
||||
vec![operand_val],
|
||||
)?;
|
||||
self.value_types.insert(dst, rett);
|
||||
return Ok(dst);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user