fix(mir): PHI検証panic修正 - update_cfg()を検証前に呼び出し

A案実装: debug_verify_phi_inputs呼び出し前にCFG predecessorを更新

修正箇所(7箇所):
- src/mir/builder/phi.rs:50, 73, 132, 143
- src/mir/builder/ops.rs:273, 328, 351

根本原因:
- Branch/Jump命令でsuccessorは即座に更新
- predecessorはupdate_cfg()で遅延再構築
- PHI検証が先に実行されてpredecessor未更新でpanic

解決策:
- 各debug_verify_phi_inputs呼び出し前に
  if let Some(func) = self.current_function.as_mut() {
      func.update_cfg();
  }
  を挿入してCFGを同期

影響: if/else文、論理演算子(&&/||)のPHI生成が正常動作
This commit is contained in:
nyash-codex
2025-11-01 13:28:56 +09:00
parent 149ec61d4d
commit 6a452b2dca
174 changed files with 2432 additions and 1014 deletions

View File

@ -7,8 +7,8 @@ static box LLVMAotFacadeBox {
_route(){
// Decide route by env (read-only). Default = lib (via AotBox)
// HAKO_AOT_USE_FFI=1 → ffi, HAKO_AOT_USE_PLUGIN=1 → plugin, else lib
local ffi = call("env.local.get/1", "HAKO_AOT_USE_FFI"); if LLVMAotFacadeBox._truthy(ffi) { return "ffi" }
local plug = call("env.local.get/1", "HAKO_AOT_USE_PLUGIN"); if LLVMAotFacadeBox._truthy(plug) { return "plugin" }
local ffi = env.get("HAKO_AOT_USE_FFI"); if LLVMAotFacadeBox._truthy(ffi) { return "ffi" }
local plug = env.get("HAKO_AOT_USE_PLUGIN"); if LLVMAotFacadeBox._truthy(plug) { return "plugin" }
return "lib"
}
_q(s){ return "\"" + s + "\"" }
@ -52,7 +52,7 @@ static box LLVMAotFacadeBox {
// Convenience wrappers (delegate to LLVMBuilderBox when gate=on; else inline JSON)
compile_link_ret0(obj_out, exe_out, flags){
local on = call("env.local.get/1", "HAKO_LLVM_SCRIPT_BUILDER");
local on = env.get("HAKO_LLVM_SCRIPT_BUILDER");
if on && (LLVMAotFacadeBox._truthy(on)) {
local json = LLVMBuilderBox.program_ret0()
return LLVMAotFacadeBox.compile_link_json(json, obj_out, exe_out, flags)
@ -63,7 +63,7 @@ static box LLVMAotFacadeBox {
return LLVMAotFacadeBox.compile_link_json(json, obj_out, exe_out, flags)
}
compile_link_ret_i64(v, obj_out, exe_out, flags){
local on = call("env.local.get/1", "HAKO_LLVM_SCRIPT_BUILDER");
local on = env.get("HAKO_LLVM_SCRIPT_BUILDER");
if on && (LLVMAotFacadeBox._truthy(on)) {
local json = LLVMBuilderBox.program_ret_i64(v)
return LLVMAotFacadeBox.compile_link_json(json, obj_out, exe_out, flags)
@ -73,7 +73,7 @@ static box LLVMAotFacadeBox {
return LLVMAotFacadeBox.compile_link_json(json, obj_out, exe_out, flags)
}
compile_link_binop_i64(lhs, rhs, opk, obj_out, exe_out, flags){
local on = call("env.local.get/1", "HAKO_LLVM_SCRIPT_BUILDER");
local on = env.get("HAKO_LLVM_SCRIPT_BUILDER");
if on && (LLVMAotFacadeBox._truthy(on)) {
local json = LLVMBuilderBox.program_binop_i64(lhs, rhs, opk)
return LLVMAotFacadeBox.compile_link_json(json, obj_out, exe_out, flags)
@ -143,7 +143,7 @@ static box LLVMAotFacadeBox {
// extern call convenience wrappers (console.*) — build via Builder and link
compile_link_call_console_log(obj_out, exe_out, flags){
local on = call("env.local.get/1", "HAKO_LLVM_SCRIPT_BUILDER");
local on = env.get("HAKO_LLVM_SCRIPT_BUILDER");
local json
if on && (LLVMAotFacadeBox._truthy(on)) { json = LLVMBuilderBox.program_call_console_log_ret0() }
else {
@ -156,7 +156,7 @@ static box LLVMAotFacadeBox {
return LLVMAotFacadeBox.compile_link_json(json, obj_out, exe_out, flags)
}
compile_link_call_console_warn(obj_out, exe_out, flags){
local on = call("env.local.get/1", "HAKO_LLVM_SCRIPT_BUILDER");
local on = env.get("HAKO_LLVM_SCRIPT_BUILDER");
local json
if on && (LLVMAotFacadeBox._truthy(on)) { json = LLVMBuilderBox.program_call_console_warn_ret0() }
else {
@ -169,7 +169,7 @@ static box LLVMAotFacadeBox {
return LLVMAotFacadeBox.compile_link_json(json, obj_out, exe_out, flags)
}
compile_link_call_console_error(obj_out, exe_out, flags){
local on = call("env.local.get/1", "HAKO_LLVM_SCRIPT_BUILDER");
local on = env.get("HAKO_LLVM_SCRIPT_BUILDER");
local json
if on && (LLVMAotFacadeBox._truthy(on)) { json = LLVMBuilderBox.program_call_console_error_ret0() }
else {
@ -193,7 +193,7 @@ static box LLVMAotFacadeBox {
}
// time.now_ms — build via Builder when gate, else inline JSON; ret 0
compile_link_call_time_now_ms(obj_out, exe_out, flags){
local on = call("env.local.get/1", "HAKO_LLVM_SCRIPT_BUILDER");
local on = env.get("HAKO_LLVM_SCRIPT_BUILDER");
local json
if on && (LLVMAotFacadeBox._truthy(on)) { json = LLVMBuilderBox.program_call_time_now_ms_ret0() }
else {
@ -206,7 +206,7 @@ static box LLVMAotFacadeBox {
}
// JSON.stringify(any) — via nyash.json.stringify_h; ret 0
compile_link_call_json_stringify(obj_out, exe_out, flags){
local on = call("env.local.get/1", "HAKO_LLVM_SCRIPT_BUILDER");
local on = env.get("HAKO_LLVM_SCRIPT_BUILDER");
local json
if on && (LLVMAotFacadeBox._truthy(on)) { json = LLVMBuilderBox.program_call_json_stringify_ret0() }
else {
@ -220,7 +220,7 @@ static box LLVMAotFacadeBox {
}
// env.mem.alloc/free wrapper — ret 0
compile_link_call_mem_alloc_free(sz, obj_out, exe_out, flags){
local on = call("env.local.get/1", "HAKO_LLVM_SCRIPT_BUILDER");
local on = env.get("HAKO_LLVM_SCRIPT_BUILDER");
local json
if on && (LLVMAotFacadeBox._truthy(on)) { json = LLVMBuilderBox.program_call_mem_alloc_free_ret0(sz) }
else {
@ -236,7 +236,7 @@ static box LLVMAotFacadeBox {
}
// env.local.get wrapper — ret 0 (value ignored)
compile_link_call_env_local_get(key, obj_out, exe_out, flags){
local on = call("env.local.get/1", "HAKO_LLVM_SCRIPT_BUILDER");
local on = env.get("HAKO_LLVM_SCRIPT_BUILDER");
local json
if on && (LLVMAotFacadeBox._truthy(on)) { json = LLVMBuilderBox.program_call_env_local_get_ret0(key) }
else {

View File

@ -50,7 +50,7 @@ static box AotPrepBox {
if ls < 0 { return [-1, -1] }
local depth = 0
local i = ls
local L = s.size()
local L = s.length()
local rs = -1
loop(i < L) {
local ch = s.substring(i, i+1)
@ -75,7 +75,7 @@ static box AotPrepBox {
local k = "\"dst\":"
local i = ss.indexOf(k, pos)
if i < 0 { return -1 }
i = i + k.size()
i = i + k.length()
local digs = StringHelpers.read_digits(ss, i)
if digs == "" { return -1 }
return StringHelpers.to_i64(digs)
@ -84,7 +84,7 @@ static box AotPrepBox {
local k = "\"value\":{\"type\":\"i64\",\"value\":"
local i = ss.indexOf(k, pos)
if i < 0 { return null }
i = i + k.size()
i = i + k.length()
local digs = StringHelpers.read_digits(ss, i)
if digs == "" { return null }
return StringHelpers.to_i64(digs)
@ -98,7 +98,7 @@ static box AotPrepBox {
local k = key
local i = ss.indexOf(k, pos)
if i < 0 { return -1 }
i = i + k.size()
i = i + k.length()
local digs = StringHelpers.read_digits(ss, i)
if digs == "" { return -1 }
return StringHelpers.to_i64(digs)
@ -107,7 +107,7 @@ static box AotPrepBox {
local k = "\"operation\":\""
local i = ss.indexOf(k, pos)
if i < 0 { return "" }
i = i + k.size()
i = i + k.length()
local j = ss.indexOf("\"", i)
if j < 0 { return "" }
return ss.substring(i, j)
@ -127,7 +127,7 @@ static box AotPrepBox {
"{\\\"op\\\":\\\"const\\\",\\\"dst\\\":" + StringHelpers.int_to_str(d1) + ",\\\"value\\\":{\\\"type\\\":\\\"i64\\\",\\\"value\\\":" + StringHelpers.int_to_str(res) + "}}," +
"{\\\"op\\\":\\\"ret\\\",\\\"value\\\":" + StringHelpers.int_to_str(d1) + "}]"
local head = s.substring(0, arr_start)
local tail = s.substring(arr_end + 1, s.size())
local tail = s.substring(arr_end + 1, s.length())
return head + new_insts + tail
}
// Pass 1: prefer name:"main"

View File

@ -28,17 +28,17 @@ static box LLVMBuilderBox {
"{\\\"op\\\":\\\"ret\\\",\\\"value\\\":1}] } ] } ] }"
}
const_i64(fn_handle, value){
local strict = call("env.local.get/1", "HAKO_LLVM_SCRIPT_BUILDER_STRICT");
local strict = env.get("HAKO_LLVM_SCRIPT_BUILDER_STRICT");
if strict && strict != "0" && strict != "false" { print("UNSUPPORTED: const_i64 (stub)"); return -1 }
return 0
}
binop_add(fn_handle, lhs, rhs){
local strict = call("env.local.get/1", "HAKO_LLVM_SCRIPT_BUILDER_STRICT");
local strict = env.get("HAKO_LLVM_SCRIPT_BUILDER_STRICT");
if strict && strict != "0" && strict != "false" { print("UNSUPPORTED: binop_add (stub)"); return -1 }
return 0
}
ret(fn_handle, val){
local strict = call("env.local.get/1", "HAKO_LLVM_SCRIPT_BUILDER_STRICT");
local strict = env.get("HAKO_LLVM_SCRIPT_BUILDER_STRICT");
if strict && strict != "0" && strict != "false" { print("UNSUPPORTED: ret (stub)"); return -1 }
return 0
}

View File

@ -2,7 +2,7 @@
static box LLVMModuleBox {
new(name, triple, dl){
// Gate: optin のみ
local on = call("env.local.get/1", "HAKO_LLVM_SCRIPT_BUILDER");
local on = env.get("HAKO_LLVM_SCRIPT_BUILDER");
if !on || on == "0" || on == "false" { return -1 }
// For MVP, just return a dummy handle (=1)
return 1

View File

@ -37,7 +37,7 @@ static box V0Demo {
static box Main {
// デモエントリ: ret 0 の exe を生成
main(){
local tmp = call("env.local.get/1", "NYASH_ROOT")
local tmp = env.get("NYASH_ROOT")
if !tmp { tmp = "." }
local obj = tmp + "/tmp/v0_min.o"
local exe = tmp + "/tmp/v0_min_exe"

View File

@ -36,7 +36,7 @@ static box LLVMBranchInstructionBox {
batch_branch(branch_list) {
local results = []
local i = 0
while i < branch_list.size() {
while i < branch_list.length() {
local branch = branch_list[i]
local json = me.lower_branch(branch.cond, branch.then_block, branch.else_block)
results.push(json)

View File

@ -60,7 +60,7 @@ static box LLVMCompareInstructionBox {
batch_compare(compare_list) {
local results = []
local i = 0
while i < compare_list.size() {
while i < compare_list.length() {
local cmp = compare_list[i]
local json = me.lower_compare(cmp.op, cmp.lhs, cmp.rhs, cmp.dst)
results.push(json)

View File

@ -40,7 +40,7 @@ static box LLVMCopyInstructionBox {
batch_copy(copy_list) {
local results = []
local i = 0
while i < copy_list.size() {
while i < copy_list.length() {
local copy = copy_list[i]
local json = me.lower_copy(copy.dst, copy.src)
results.push(json)

View File

@ -45,7 +45,7 @@ static box LLVMJumpInstructionBox {
batch_jump(jump_list) {
local results = []
local i = 0
while i < jump_list.size() {
while i < jump_list.length() {
local jump = jump_list[i]
local json = me.lower_jump(jump.target)
results.push(json)