Skip to content

bloqade.lanes.rewrite.stackify

stackify

bloqade.lanes.rewrite.stackify

Stackification for single-block stack_move ir.Method.

stackify(method) is the primary entry point. It normalises a stack_move ir.Method in place so that BytecodeEncoder can walk the entry block in statement order and emit correct bytecode.

Restriction: the method must contain exactly one block with no branches or back-edges. This is enforced at runtime. All IR produced by the current compiler pipeline (Move → StackMove → Bytecode) satisfies this invariant.

Three sub-passes run in sequence:

Pass 1 — CloneConstants (RewriteRule via Walk) For each consuming statement, clones every ConstantLike (Const*) argument and inserts the clone immediately before the consumer in stack-depth order: deepest arg first (highest stmt.args index), top-of-stack arg last (index 0). The arg reference on the consumer is updated to the clone in-place; the original becomes dead and is removed by Pass 2.

Pass 2 — DCE Removes the now-dead original constant definitions left behind by Pass 1.

Pass 3 — Dup/Swap insertion For each non-Pure SSA value consumed by more than one statement (e.g. an AwaitMeasure result used by N GetItem statements), inserts Dup/Swap instructions so the value remains available for later consumers without violating the stack discipline. For consumers c_0, …, c_{N-1} in block order the pattern emitted before each non-last consumer c_k is:

Dup(live_copy) ← save a copy below c_k’s const args <const args of c_k> ← already placed by Pass 1 c_k(dup_result, …) ← consumes the dup Swap(c_k.result, live) ← out_top = live copy (for c_{k+1})

The last consumer uses out_top from the preceding Swap directly.