105 lines
4.9 KiB
Plaintext
105 lines
4.9 KiB
Plaintext
|
|
// selfhost/shared/mir/loop_form_box.hako
|
||
|
|
// LoopFormBox — minimal loop structure builder (P2: continue/break snapshots + Exit PHI)
|
||
|
|
|
||
|
|
using "lang/src/shared/mir/mir_schema_box.hako" as MirSchemaBox
|
||
|
|
|
||
|
|
static box LoopFormBox {
|
||
|
|
|
||
|
|
// while (i < limit) {
|
||
|
|
// if (i == break_value) break;
|
||
|
|
// if (i == skip_value) continue;
|
||
|
|
// sum = sum + i;
|
||
|
|
// i = i + 1;
|
||
|
|
// }
|
||
|
|
// Builds LoopForm structure with Header/Latch PHI + Exit PHI (continue/break aware)
|
||
|
|
loop_counter(limit, skip_value, break_value) {
|
||
|
|
if skip_value == null { skip_value = 2 }
|
||
|
|
if break_value == null { break_value = limit }
|
||
|
|
|
||
|
|
// Preheader (block 0): initialise loop-carried values and constants, then jump header
|
||
|
|
local pre = new ArrayBox()
|
||
|
|
pre.push(MirSchemaBox.inst_const(1, 0)) // r1 = 0 (initial i)
|
||
|
|
pre.push(MirSchemaBox.inst_const(2, limit)) // r2 = limit
|
||
|
|
pre.push(MirSchemaBox.inst_const(3, 1)) // r3 = step
|
||
|
|
pre.push(MirSchemaBox.inst_const(4, 0)) // r4 = sum
|
||
|
|
pre.push(MirSchemaBox.inst_const(5, skip_value)) // r5 = continue trigger
|
||
|
|
pre.push(MirSchemaBox.inst_const(6, break_value))// r6 = break trigger
|
||
|
|
pre.push(MirSchemaBox.inst_jump(1)) // goto header
|
||
|
|
|
||
|
|
// Header (block 1): PHI(i), PHI(sum), compare, branch
|
||
|
|
local header = new ArrayBox()
|
||
|
|
local phi_i_inputs = new ArrayBox()
|
||
|
|
phi_i_inputs.push(MirSchemaBox.phi_incoming(0, 1)) // from preheader
|
||
|
|
phi_i_inputs.push(MirSchemaBox.phi_incoming(7, 18)) // from latch
|
||
|
|
header.push(MirSchemaBox.inst_phi(10, phi_i_inputs)) // r10 = current i
|
||
|
|
|
||
|
|
local phi_sum_inputs = new ArrayBox()
|
||
|
|
phi_sum_inputs.push(MirSchemaBox.phi_incoming(0, 4)) // from preheader
|
||
|
|
phi_sum_inputs.push(MirSchemaBox.phi_incoming(7, 19)) // from latch
|
||
|
|
header.push(MirSchemaBox.inst_phi(11, phi_sum_inputs))// r11 = current sum
|
||
|
|
|
||
|
|
header.push(MirSchemaBox.inst_compare("Lt", 10, 2, 12)) // r12 = (i < limit)
|
||
|
|
header.push(MirSchemaBox.inst_branch(12, 2, 8)) // body or exit
|
||
|
|
|
||
|
|
// Body entry (block 2): if (i == break) -> break else check continue
|
||
|
|
local body_check_break = new ArrayBox()
|
||
|
|
body_check_break.push(MirSchemaBox.inst_compare("Eq", 10, 6, 13)) // r13 = (i == break)
|
||
|
|
body_check_break.push(MirSchemaBox.inst_branch(13, 3, 4))
|
||
|
|
|
||
|
|
// Break path (block 3): jump directly to exit; exit PHI snapshots current sum
|
||
|
|
local break_block = new ArrayBox()
|
||
|
|
break_block.push(MirSchemaBox.inst_jump(8))
|
||
|
|
|
||
|
|
// Continue check (block 4): if (i == skip) -> continue else body work
|
||
|
|
local continue_check = new ArrayBox()
|
||
|
|
continue_check.push(MirSchemaBox.inst_compare("Eq", 10, 5, 14)) // r14 = (i == skip)
|
||
|
|
continue_check.push(MirSchemaBox.inst_branch(14, 5, 6))
|
||
|
|
|
||
|
|
// Continue path (block 5): snapshot sum, increment i, jump latch
|
||
|
|
local continue_block = new ArrayBox()
|
||
|
|
continue_block.push(MirSchemaBox.inst_binop("Add", 10, 3, 15)) // r15 = i + step
|
||
|
|
continue_block.push(MirSchemaBox.inst_jump(7))
|
||
|
|
|
||
|
|
// Body work (block 6): sum += i; i += step; jump latch
|
||
|
|
local body_block = new ArrayBox()
|
||
|
|
body_block.push(MirSchemaBox.inst_binop("Add", 11, 10, 16)) // r16 = sum + i
|
||
|
|
body_block.push(MirSchemaBox.inst_binop("Add", 10, 3, 17)) // r17 = i + step
|
||
|
|
body_block.push(MirSchemaBox.inst_jump(7))
|
||
|
|
|
||
|
|
// Latch (block 7): PHI merge for continue/normal, then jump header
|
||
|
|
local latch_block = new ArrayBox()
|
||
|
|
local latch_phi_i = new ArrayBox()
|
||
|
|
latch_phi_i.push(MirSchemaBox.phi_incoming(5, 15)) // continue path
|
||
|
|
latch_phi_i.push(MirSchemaBox.phi_incoming(6, 17)) // body path
|
||
|
|
latch_block.push(MirSchemaBox.inst_phi(18, latch_phi_i)) // feeds header.i
|
||
|
|
|
||
|
|
local latch_phi_sum = new ArrayBox()
|
||
|
|
latch_phi_sum.push(MirSchemaBox.phi_incoming(5, 11)) // continue keeps sum
|
||
|
|
latch_phi_sum.push(MirSchemaBox.phi_incoming(6, 16)) // body updated sum
|
||
|
|
latch_block.push(MirSchemaBox.inst_phi(19, latch_phi_sum)) // feeds header.sum
|
||
|
|
latch_block.push(MirSchemaBox.inst_jump(1))
|
||
|
|
|
||
|
|
// Exit (block 8): Merge sums from header fallthrough and break edge, then return
|
||
|
|
local exit_vals = new ArrayBox()
|
||
|
|
exit_vals.push(MirSchemaBox.phi_incoming(1, 11)) // normal completion
|
||
|
|
exit_vals.push(MirSchemaBox.phi_incoming(3, 11)) // break path
|
||
|
|
local exit_block = new ArrayBox()
|
||
|
|
exit_block.push(MirSchemaBox.inst_phi(20, exit_vals))
|
||
|
|
exit_block.push(MirSchemaBox.inst_ret(20))
|
||
|
|
|
||
|
|
// Assemble blocks
|
||
|
|
local blocks = new ArrayBox()
|
||
|
|
blocks.push(MirSchemaBox.block(0, pre))
|
||
|
|
blocks.push(MirSchemaBox.block(1, header))
|
||
|
|
blocks.push(MirSchemaBox.block(2, body_check_break))
|
||
|
|
blocks.push(MirSchemaBox.block(3, break_block))
|
||
|
|
blocks.push(MirSchemaBox.block(4, continue_check))
|
||
|
|
blocks.push(MirSchemaBox.block(5, continue_block))
|
||
|
|
blocks.push(MirSchemaBox.block(6, body_block))
|
||
|
|
blocks.push(MirSchemaBox.block(7, latch_block))
|
||
|
|
blocks.push(MirSchemaBox.block(8, exit_block))
|
||
|
|
|
||
|
|
return MirSchemaBox.module(MirSchemaBox.fn_main(blocks))
|
||
|
|
}
|
||
|
|
}
|