// LocalSSABox — 材化(materialize)/Copy 挿入の最小ポリシーを集約 // Phase 15.7: 最小実装。将来 PHI/Call 前の規約をここに集約して拡張する。 using "lang/src/shared/common/box_helpers.hako" as BoxHelpers static box LocalSSABox { _maybe_unwrap_instructions(insts) { if insts == null { return null } local repr = "" + insts if repr.indexOf("MapBox(") == 0 { local inner = BoxHelpers.map_get(insts, "instructions") if inner != null { return inner } } return insts } // 汎用: copy 命令を insts(ArrayBox of Map)末尾に追加 add_copy(insts, dst, src) { if insts == null { return 1 } insts = me._maybe_unwrap_instructions(insts) if insts == null { return 1 } call("ArrayBox.push/2", insts, { op:"copy", dst: dst, src: src }) return 0 } // PHI直後の材化(最小): いまは add_copy と同じ。将来 PHI 群スキップを実装 ensure_after_phis_copy(insts, src, dst) { if insts == null { return 1 } insts = me._maybe_unwrap_instructions(insts) if insts == null { return 1 } if BoxHelpers.is_array(insts) == 0 { return me.add_copy(insts, dst, src) } local n = BoxHelpers.array_len(insts) local i = 0 loop (i < n) { local ins = BoxHelpers.array_get(insts, i) if ins == null { break } local op = BoxHelpers.map_get(ins, "op") if op == null || op != "phi" { break } i = i + 1 } local insert_at = i // phi 直後 local node = { op:"copy", dst: dst, src: src } if insert_at >= n { call("ArrayBox.push/2", insts, node) return 0 } if n > 0 { call("ArrayBox.push/2", insts, BoxHelpers.array_get(insts, n - 1)) local j = n - 1 loop (j >= insert_at) { call("ArrayBox.set/3", insts, j + 1, BoxHelpers.array_get(insts, j)) j = j - 1 } call("ArrayBox.set/3", insts, insert_at, node) return 0 } call("ArrayBox.push/2", insts, node) return 0 } // 新規: 定義直後に copy を挿入(安全・最小) ensure_after_last_def_copy(insts, src, dst) { if insts == null { return 1 } if BoxHelpers.is_array(insts) == 0 { return 1 } local n = BoxHelpers.array_len(insts) local insert_at = n // Find the first terminator index (ret/branch/jump/throw) to ensure block ends with a terminator local term_at = n { local i = 0 loop(i < n) { local ins = BoxHelpers.array_get(insts, i) if ins != null { local op = BoxHelpers.map_get(ins, "op") if op == "ret" || op == "branch" || op == "jump" || op == "throw" { term_at = i break } } i = i + 1 } } // 探索: 最後に dst=src を定義した位置 { local i = 0 loop (i < n) { local ins = BoxHelpers.array_get(insts, i) if ins != null { print("[LS] checking def ins=" + ("" + ins)) local d_raw = BoxHelpers.map_get(ins, "dst") print("[LS] dst raw=" + ("" + d_raw)) local d = BoxHelpers.value_i64(d_raw) if d != null && d == src { insert_at = i + 1 } } i = i + 1 } } // Do not cross terminator: insert before the first terminator if present if insert_at > term_at { insert_at = term_at } local node = { op:"copy", dst: dst, src: src } if insert_at >= n { call("ArrayBox.push/2", insts, node) return 0 } // 1つ末尾に空きを作る(末尾要素を複製して押し出す) if n > 0 { call("ArrayBox.push/2", insts, BoxHelpers.array_get(insts, n - 1)) local j = n - 1 loop (j >= insert_at) { call("ArrayBox.set/3", insts, j + 1, BoxHelpers.array_get(insts, j)) j = j - 1 } call("ArrayBox.set/3", insts, insert_at, node) return 0 } call("ArrayBox.push/2", insts, node) return 0 } // calls の最小材化: 最後の ret が参照する値 src を探し、src の直後に copy(dst=src+1) を挿入する。 // mod_full: { functions: [ { blocks: [ { instructions: [...] } ] } ] } ensure_materialize_last_ret(mod_full) { if mod_full == null { return 1 } local fns = BoxHelpers.map_get(mod_full, "functions") if fns == null || BoxHelpers.array_len(fns) == 0 { return 1 } local blocks = BoxHelpers.map_get(BoxHelpers.array_get(fns, 0), "blocks") if blocks == null || BoxHelpers.array_len(blocks) == 0 { return 1 } local insts = BoxHelpers.map_get(BoxHelpers.array_get(blocks, 0), "instructions") if insts == null || BoxHelpers.array_len(insts) == 0 { return 1 } // ret の引数を探索 local n = BoxHelpers.array_len(insts) local src = null { local i = 0 loop(i < n) { local ins = BoxHelpers.array_get(insts, i) if ins != null { local op = BoxHelpers.map_get(ins, "op") if op == "ret" { src = BoxHelpers.value_i64(BoxHelpers.map_get(ins, "value")) } } i = i + 1 } } if src == null { return 1 } return me.ensure_after_last_def_copy(insts, src, src + 1) } // ensure_cond: 最初の branch の cond を検出し、その定義直後に copy を1つ挿入(最小) // - 形状期待: いずれかの block.instructions に { op:"branch", cond:, ... } ensure_cond(mod_full) { if mod_full == null { return 1 } local fns = BoxHelpers.map_get(mod_full, "functions") if fns == null { return 1 } local bn = BoxHelpers.array_len(fns) if bn == 0 { return 1 } local blocks = BoxHelpers.map_get(BoxHelpers.array_get(fns, 0), "blocks") if blocks == null || BoxHelpers.array_len(blocks) == 0 { return 1 } // 探索: 各ブロックの instructions から最初の branch を見つけ、そのブロックで材化 local bi = 0 local block_count = BoxHelpers.array_len(blocks) loop (bi < block_count) { local insts = BoxHelpers.map_get(BoxHelpers.array_get(blocks, bi), "instructions") local insts_len = BoxHelpers.array_len(insts) if insts_len > 0 { local n = insts_len local cond = null { local i = 0 loop(i < n) { local ins = BoxHelpers.array_get(insts, i) if ins != null { local op = BoxHelpers.map_get(ins, "op") if op == "branch" { cond = BoxHelpers.value_i64(BoxHelpers.map_get(ins, "cond")) break } } i = i + 1 } } if cond != null { return me.ensure_after_last_def_copy(insts, cond, cond + 2) } } bi = bi + 1 } return 1 } } static box LocalSSAStub { main(args) { return 0 } }