Files
hakorune/lang/src/compiler/pipeline_v2/local_ssa_box.hako

189 lines
6.6 KiB
Plaintext
Raw Normal View History

// 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 命令を instsArrayBox 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:<id>, ... }
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 } }