summary_two-phase-lower0.md 2.2 KB

Lower phase — slice 0 (mechanism + scalar L0 subset)

Branch ast-stage-c. Suite 180/180 (178 + 2 Lower comparisons); self-hosting fixpoint OK (3,090,949 bytes; slice 13 was 3,042,040). Plan of record: docs/plan-lower.md.

What landed

The mechanism that lets the AST be lowered and byte-compared against the legacy emit, plus the first subset.

  • compiler/src/Lower.def/.mod — the walk. CanLower(unit) gates a unit to the supported subset; LowerUnit(unit) re-emits it: OpenModule, SetOutName(<mod>L), SetModule(<mod>), declarations, BeginBody, body, EndModule(<mod>).
  • QbeGen.SetOutName (new, additive): overrides only the image file name used by EndModule, leaving the mangled symbol name unchanged — so a matching walk writes a byte-identical image to a different file.
  • -lower driver flag: the grammar re-emits the program unit from the AST inside the unit's END action, right after the legacy EndModule and before SymTab.EndUnit (the module scope must still be open — Lower resolves names through SymTab).
  • Grammar exports SetLower/GetUnit; parser.frm's definition module re-exports them; Lower is linked like AST.

L0 subset

A program unit with scalar CONST/VAR and a body of x := <integer expression> (literals/idents, + - * DIV MOD, unary -), reproducing Design's scalar emit (LoadVar / const CopyOp) and AssOrDecl's scalar store, including Fold2 constant folding.

Verified

./M2 -lower tests/t_exit.mod and t_arith.mod produce gen_ssa/<Mod>L.ssa byte-identical to the legacy image (now asserted by lower_ok in run_tests.sh).

Finding

SymTab.EndUnit closes the module scope, so Lower cannot run after Parse (names no longer resolve). It must run at unit end, before EndUnit — and after the legacy EndModule so re-opening the backend does not clobber the legacy image buffer.

Next (per docs/plan-lower.md)

Extend the subset one step at a time — L1 relations/booleans/short-circuit, L2 control flow, L3 procedures, … — each gated by lower_ok + suite + fixpoint, until a unit can be lowered from the AST instead of inline (phase 3), then delete the inline emit and Fwd* machinery.