# V3 self-hosting fixpoint reached Tag `v3-fixpoint`. Main suite 111/111. ## The milestone V3, **compiled by V3 itself**, compiles the whole compiler source set to a **byte-identical** `gen_ssa/M2.ssa`: ``` M2 (built by gm2 -fiso) compiles SymTab QbeGen M2S M2P M2(driver) -> gen_ssa/M2.ssa (1,991,439 bytes) M2self (built by V3 from that image) compiles the same set -> gen_ssa/M2.ssa cmp: *** IDENTICAL (FULL FIXPOINT) *** ``` So Stage 2 (V3 compiling itself) reproduces Stage 1's image exactly — the self-hosting fixpoint. ## The last fix `QbeGen.InitHeap`, for a nested array (`ARRAY … OF ARRAY …`) on the heap/stack, allocated each element sub-array with `NewHeap` but never **initialised its descriptor header**. A local `ARRAY [0..15] OF Name` therefore had sub-descriptors with garbage headers, and passing `names[i]` to an `ARRAY OF CHAR` formal trapped in the scanner's `GetName`. Fix: call `InitHeap(eb, elem)` on each sub-array. Repro: ```modula2 TYPE Name = ARRAY [0..63] OF CHAR; PROCEDURE P; VAR names: ARRAY [0..3] OF Name; i: CARDINAL; PROCEDURE Set (VAR s: ARRAY OF CHAR); BEGIN s[0] := 'x' END Set; BEGIN i := 0; Set(names[i]) END P; ``` ## How we got here (this arc) From "sources compile and link" to the fixpoint, each step a real V3 runtime/ABI bug with a minimal repro: nested modules; inline record array fields; the NUL-terminated string model; `p^` as a `VAR` actual; de-eagered NIL guards; off-by-one string scans; short-circuit `AND`/`OR`; and now nested-array heap initialisation. ## Remaining (bootstrap polish) - `bootstrap/fixpoint.sh`: automate Stage1 gm2 → Stage2 V3 → Stage3 V3 and `cmp` the images (the manual chain above already shows Stage2 == Stage1). Stage-aware CR flag: `-m` for gm2, no `-m` for V3. - Cross-stage `FileIO` selection (stage 1 uses the host `FileIO`; stage 2+ the self-hosted `runtime/syslib/FileIO`). ## Files `compiler/src/{QbeGen.mod,M2.lst}`.