114 lines
4.8 KiB
Plaintext
114 lines
4.8 KiB
Plaintext
// v1_phi_table.hako — V1PhiTableBox
|
|
// Responsibility: apply SSA φ at block entry (v1 JSON), using prev_bb to select incoming.
|
|
|
|
using selfhost.vm.hakorune-vm.json_v1_reader as JsonV1ReaderBox
|
|
using selfhost.shared.json.utils.json_frag as JsonFragBox
|
|
using selfhost.shared.common.string_ops as StringOps
|
|
using selfhost.vm.helpers.instruction_scanner as InstructionScannerBox
|
|
using selfhost.vm.helpers.v1_phi_adapter as V1PhiAdapterBox
|
|
using selfhost.shared.common.string_helpers as StringHelpers
|
|
|
|
static box V1PhiTableBox {
|
|
// Apply φ for the given block id using prev_bb. Strict/tolerate are string flags ("1"/"0").
|
|
apply_at_entry(json, regs, prev_bb, bb, strict, tolerate, flow_trace) {
|
|
if prev_bb == null { return 0 }
|
|
if bb == null { return 0 }
|
|
json = "" + json
|
|
local trace = 0
|
|
if flow_trace != null { if flow_trace == 1 { trace = 1 } }
|
|
// find instructions array for the block
|
|
local start = JsonV1ReaderBox.block_insts_start(json, bb)
|
|
if start < 0 { return 0 }
|
|
local endp = JsonFragBox._seek_array_end(json, start)
|
|
if endp <= start { return 0 }
|
|
local seg = json.substring(start + 1, endp)
|
|
local pscan = 0
|
|
loop(true) {
|
|
if pscan >= seg.length() { break }
|
|
local pt = InstructionScannerBox.next_tuple(seg, pscan)
|
|
if pt == "" { break }
|
|
local pc1 = StringOps.index_of_from(pt, ",", 0)
|
|
local pc2 = StringOps.index_of_from(pt, ",", pc1+1)
|
|
if pc1 < 0 || pc2 < 0 { break }
|
|
local ps = JsonFragBox._str_to_int(pt.substring(0, pc1))
|
|
local pe = JsonFragBox._str_to_int(pt.substring(pc1+1, pc2))
|
|
local pop = pt.substring(pc2+1, pt.length())
|
|
if pop == "phi" {
|
|
local pitem = seg.substring(ps, pe)
|
|
local dstp = JsonFragBox.get_int(pitem, "dst")
|
|
if dstp == null { return 0 }
|
|
local chosen = V1PhiAdapterBox.pick_incoming_value_id(pitem, prev_bb, trace)
|
|
local write = null
|
|
if chosen == null {
|
|
if trace == 1 { print("[phi] dst=" + (""+dstp) + " prev=" + (""+prev_bb) + " chosen=null") }
|
|
if strict == "1" && tolerate != "1" { return -1 }
|
|
if tolerate == "1" { write = "0" }
|
|
} else {
|
|
local srcv = regs.getField(StringHelpers.int_to_str(chosen))
|
|
if srcv == null {
|
|
if trace == 1 { print("[phi] dst=" + (""+dstp) + " prev=" + (""+prev_bb) + " chosen=" + (""+chosen) + " srcv=null") }
|
|
if strict == "1" && tolerate != "1" { return -1 }
|
|
if tolerate == "1" { write = "0" }
|
|
} else {
|
|
if trace == 1 { print("[phi] dst=" + (""+dstp) + " prev=" + (""+prev_bb) + " chosen=" + (""+chosen) + " srcv=" + (""+srcv) + " write=" + (""+srcv)) }
|
|
write = "" + srcv
|
|
}
|
|
}
|
|
if write != null { regs.setField(StringHelpers.int_to_str(dstp), write) }
|
|
}
|
|
pscan = pe
|
|
}
|
|
return 0
|
|
}
|
|
// Apply φ from a pre-parsed table entry list for a block.
|
|
// table: ArrayBox of { dst:int, incoming:ArrayBox of [pred:int, val:int] }
|
|
apply_table_at_entry(table, regs, prev_bb, strict, tolerate, flow_trace) {
|
|
if table == null { return 0 }
|
|
local trace = 0
|
|
if flow_trace != null { if flow_trace == 1 { trace = 1 } }
|
|
local n = table.size()
|
|
local i = 0
|
|
loop(i < n) {
|
|
local ent = table.get(i)
|
|
i = i + 1
|
|
if ent == null { continue }
|
|
local dstp = ent.get("dst")
|
|
local inc = ent.get("incoming")
|
|
if dstp == null || inc == null { continue }
|
|
local write = null
|
|
local m = inc.size()
|
|
local j = 0
|
|
loop(j < m) {
|
|
local pair = inc.get(j)
|
|
j = j + 1
|
|
if pair == null { continue }
|
|
// pair = [pred, val]
|
|
local pred = 0; local val = 0
|
|
if pair.size() >= 1 { pred = JsonFragBox._str_to_int(""+pair.get(0)) }
|
|
if pair.size() >= 2 { val = JsonFragBox._str_to_int(""+pair.get(1)) }
|
|
if pred == prev_bb {
|
|
local sv = regs.getField(StringHelpers.int_to_str(val))
|
|
if sv == null {
|
|
if trace == 1 { print("[phi] dst=" + (""+dstp) + " prev=" + (""+prev_bb) + " chosen=" + (""+val) + " srcv=null") }
|
|
if strict == "1" && tolerate != "1" { return -1 }
|
|
if tolerate == "1" { write = "0" }
|
|
} else {
|
|
if trace == 1 { print("[phi] dst=" + (""+dstp) + " prev=" + (""+prev_bb) + " chosen=" + (""+val) + " srcv=" + (""+sv) + " write=" + (""+sv)) }
|
|
write = "" + sv
|
|
}
|
|
break
|
|
}
|
|
}
|
|
if write == null {
|
|
if trace == 1 { print("[phi] dst=" + (""+dstp) + " prev=" + (""+prev_bb) + " chosen=null") }
|
|
if strict == "1" && tolerate != "1" { return -1 }
|
|
if tolerate == "1" { write = "0" }
|
|
}
|
|
if write != null { regs.setField(StringHelpers.int_to_str(dstp), write) }
|
|
}
|
|
return 0
|
|
}
|
|
}
|
|
|
|
static box V1PhiTableMain { method main(args) { return 0 } }
|