|
|
@@ -0,0 +1,86 @@
|
|
|
+# Session save — 2026-09-25 (part b): V3 self-compiles; short-circuit WIP
|
|
|
+
|
|
|
+`master` @ `757f518` (`v3-selfcompiles`) — suite **111/111**, tree clean
|
|
|
+(except the user's uncommitted `compiler/toto.mod` edit).
|
|
|
+
|
|
|
+## Headline
|
|
|
+
|
|
|
+The **self-compiled V3** (V3 compiled by V3) runs, parses, and emits
|
|
|
+code; for `tests/t_constfold.mod` its `.ssa` is **byte-identical** to
|
|
|
+the gm2-built V3's:
|
|
|
+
|
|
|
+```
|
|
|
+./M2 tests/t_constfold.mod -> gen_ssa/TConstFold.ssa
|
|
|
+/tmp/M2self tests/t_constfold.mod -> gen_ssa/TConstFold.ssa (cmp: IDENTICAL)
|
|
|
+```
|
|
|
+
|
|
|
+That is a stage-2 self-hosting fixpoint for a test file.
|
|
|
+
|
|
|
+## Fixed today (each with a minimal repro)
|
|
|
+
|
|
|
+1. Nested modules (`ListHandler`) — lowered + export hoisting.
|
|
|
+2. Inline record array fields (standard M2) — heap records' array fields
|
|
|
+ now have a descriptor header.
|
|
|
+3. NUL-terminated string model (terminator slot at index = count);
|
|
|
+ stdlib `Strings` + C shim NUL-based.
|
|
|
+4. `p^` / `a[i]^` as a `VAR` actual → pass the pointee address.
|
|
|
+5. De-eagered NIL guards in `SymTab` and the driver's `PrintListing`.
|
|
|
+6. Off-by-one string scans in `QbeGen` (`Len`/`Cpy`/`App`/`ParseInt`
|
|
|
+ used `i < HIGH(s)`; a literal's last char was dropped →
|
|
|
+ `"gen_ssa/"` became `"gen_ssa"`).
|
|
|
+
|
|
|
+## Current blocker (full self-image)
|
|
|
+
|
|
|
+Compiling the **whole compiler source set** with `/tmp/M2self` still
|
|
|
+aborts, in `SymTab.Resolve`:
|
|
|
+
|
|
|
+```modula2
|
|
|
+WHILE (n < ResDepth) AND (t >= 0) AND (t < VAL(INTEGER, nTypes))
|
|
|
+ AND (tform[t] = FAlias) DO (* eager AND evaluates tform[-1] when t < 0 *)
|
|
|
+```
|
|
|
+
|
|
|
+V3 evaluates both sides of `AND`/`OR`; gm2 short-circuits. The compiler
|
|
|
+sources rely on short-circuit in ~25 places (`(r = InvalidType) OR
|
|
|
+(tform[r] # …)`, NIL guards, etc.). Two ways forward:
|
|
|
+
|
|
|
+- **(A) short-circuit `AND`/`OR` in V3** — the principled fix (matches
|
|
|
+ gm2), done in the `wip/short-circuit` branch but **14 tests fail**; needs
|
|
|
+ debugging.
|
|
|
+- **(B) de-eager every guard site** in the compiler sources (rewrite the
|
|
|
+ ~25 `(idx = Invalid) OR …` patterns as sequential checks) — mechanical
|
|
|
+ but fragile.
|
|
|
+
|
|
|
+## WIP: `wip/short-circuit` (branch @ `26c01d0`)
|
|
|
+
|
|
|
+Implements short-circuit `AND`/`OR` via **deferred-output buffering**:
|
|
|
+`QbeGen.DelayBegin` buffers the RHS operand's code, `DelayEnd` restores
|
|
|
+output, `DelayFlush` replays it inside the branch; `SimExpr` (OR) and
|
|
|
+`Term` (AND) emit `if a { result = 1/0 } else { <RHS>; result = b }`.
|
|
|
+Currently **14 tests fail** (e.g. `t_bool`, `t_set`, `t_pointer`), so the
|
|
|
+branch logic/labels or the buffer replay is wrong. Do not merge as-is.
|
|
|
+
|
|
|
+## Next steps
|
|
|
+
|
|
|
+1. Debug `wip/short-circuit` until 111/111 (likely the branch/label or
|
|
|
+ `Jnz`-with-immediate handling) — or take route (B).
|
|
|
+2. Fix the remaining self-image abort(s); get `/tmp/M2self` to compile
|
|
|
+ the whole set to a byte-identical `M2.ssa` (full fixpoint).
|
|
|
+3. Cross-stage `FileIO` selection and `bootstrap/fixpoint.sh`
|
|
|
+ (Stage1 gm2 → Stage2 V3 → Stage3 V3), with the stage-aware CR flag
|
|
|
+ (`-m` for gm2, no `-m` for V3).
|
|
|
+
|
|
|
+## Resume
|
|
|
+
|
|
|
+```sh
|
|
|
+cd .../m2compiler-V3/compiler
|
|
|
+./build.sh && ./run_tests.sh # 111/111 on master
|
|
|
+
|
|
|
+# WIP branch:
|
|
|
+git checkout wip/short-circuit # short-circuit experiment (14 failing)
|
|
|
+
|
|
|
+# self-image check (from master):
|
|
|
+(cd src && CRFRAMES="$(pwd)" .../CocoGm2/CR -C M2.atg >/dev/null)
|
|
|
+./M2 <full session> # writes gen_ssa/M2.ssa
|
|
|
+qbe -o /tmp/M2self.s gen_ssa/M2.ssa; cc /tmp/M2self.s ../runtime/syslib/shim.c -o /tmp/M2self -lm
|
|
|
+/tmp/M2self tests/t_constfold.mod # byte-identical output
|
|
|
+```
|