|
|
@@ -0,0 +1,58 @@
|
|
|
+# Lower phase — L7 (the flip): status and plan (2026-10-05)
|
|
|
+
|
|
|
+Branch **`ast-stage-c`**. L7 = "flip: lower from the AST instead of
|
|
|
+inline; delete the inline emit + `Fwd*` machinery".
|
|
|
+
|
|
|
+## Why L7 is not incremental
|
|
|
+
|
|
|
+The flip makes `Lower` the sole emitter. The obstacle is that `QbeGen`
|
|
|
+holds **one** session state, used by the inline emit *during* parse; a
|
|
|
+per-unit `Lower` emit would be clobbered by the next unit's inline emit.
|
|
|
+So the flip is a **big-bang**: either remove/suppress the grammar's 533
|
|
|
+`QbeGen.*` call sites, or give `QbeGen` two states — neither is a
|
|
|
+byte-verifiable step.
|
|
|
+
|
|
|
+The pragmatic path is therefore a **session re-emit**: collect every
|
|
|
+unit's AST and re-emit the whole session with `Lower` after parsing.
|
|
|
+That is byte-comparable against the legacy session image and becomes the
|
|
|
+flip once the inline emit is removed.
|
|
|
+
|
|
|
+## Started (`d30abfd`, tag `v3-lower7-scaffold`)
|
|
|
+
|
|
|
+- `Lower.LowerSession/LowerOneUnit/MaterializeGlobals`.
|
|
|
+- Driver (`compiler.frm`) collects `GetUnit()` per file and calls
|
|
|
+ `Lower.LowerSession` under `-lower`.
|
|
|
+- `SymTab.Materialize` makes a unit's own VAR/CONST visible in
|
|
|
+ `globScope`, so `GlobalRef` resolves `"<unit>_<name>"` at session end
|
|
|
+ (the unit scopes are closed by then).
|
|
|
+- Removed `Lower.Reset` from the `M2` root so the owned tables persist
|
|
|
+ across a session.
|
|
|
+
|
|
|
+Still scaffolding (inline emit untouched); suite **200/200**, FIXPOINT OK
|
|
|
+(3,401,129 bytes).
|
|
|
+
|
|
|
+## Gaps found (all fixable, all required for the flip)
|
|
|
+
|
|
|
+1. **`DefUnit` builds no AST.** Its `ConstBlock/TypeBlock/VarBlock/
|
|
|
+ ProcHeading` loop never `AstAppend`s, so a definition module's AST has
|
|
|
+ no decls; its proc *headings* (which consume backend temps) cannot be
|
|
|
+ replayed. Fix: append to `astDecl` in `DefUnit`.
|
|
|
+2. **Owned-table size.** `MaxProc=64` / `MaxSym=512` are sized for one
|
|
|
+ unit; a full-session re-emit needs every module's procs/vars. Growing
|
|
|
+ them grows the compiler image (watch the 4 MiB `sessBuf`).
|
|
|
+3. **Nested-module globals.** `QualNode(outer, name)` does not see a
|
|
|
+ nested scope's non-exported globals; `ReenterGlobals` re-enters them
|
|
|
+ but with `curMod = -1` (empty `mod`), so `GlobalRef` falls back to
|
|
|
+ `$name` instead of `$<outer>_<name>`.
|
|
|
+4. **Definition-module proc replay** must emit only the heading
|
|
|
+ (`BeginFunc`/`FuncParam`/`AbortFunc`), like `LowerMethodHeadings`.
|
|
|
+5. Possibly more, revealed once a full session is compared.
|
|
|
+
|
|
|
+## Plan
|
|
|
+
|
|
|
+1. Fix (1) and (4); grow tables (2) within the image budget.
|
|
|
+2. Compare `Lower.LowerSession`'s image against the legacy session image
|
|
|
+ for the compiler's own sources (the real test).
|
|
|
+3. Fix the remaining gaps until the session image byte-matches.
|
|
|
+4. Flip: remove the inline emit; keep `Lower` per unit; the fixpoint
|
|
|
+ becomes the gate.
|