boot2

Playing with the boostrap
git clone https://git.ryansepassi.com/git/boot2.git
Log | Files | Refs | README

commit ce907690c98caea1293474f4f5d76b285d01c5cd
parent ebb3b75ca8d585fa0bd92a7ab7d54555047c3778
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Sun, 26 Apr 2026 23:09:54 -0700

cc/parse: §I block-static mangling stores in sym-name

cg-push-sym and cg-emit-global both derive the emitted P1pp label
from sym-name (cc__ prefix). To make block-scope statics from
different functions distinct in cg's view, store the mangled label
(`<fn>__<var>`) in sym-name itself. scope-bind!'s key remains the
original identifier so source-level lookup is unchanged.

Tightened the parse fixture to exercise two functions with
same-named statics so a regression to a flat `cc__n` mangling would
collide and either fail to assemble or give the wrong counter value.

Diffstat:
Mcc/parse.scm | 7+++++--
Mdocs/CC-PUNCHLIST.md | 110++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
Mtests/cc-parse/57-block-static.c | 16+++++++++++++---
Mtests/cc-parse/57-block-static.expected-exit | 2+-
4 files changed, 81 insertions(+), 54 deletions(-)

diff --git a/cc/parse.scm b/cc/parse.scm @@ -368,11 +368,14 @@ (bytevector-append "cc__" n)))) ;; §I: block-scope `static` routes to a global with a name mangled ;; on the enclosing function so two functions can each have their - ;; own `static int n;` without colliding. + ;; own `static int n;` without colliding. The sym's NAME holds the + ;; mangled form (cg-push-sym / cg-emit-global both prefix "cc__" + ;; onto sym-name to derive the emitted label); scope-bind!s key + ;; remains the original identifier for source-level lookup. ((and (eq? sto 'static) (ps-fn-ctx ps)) (let* ((fname (fn-ctx-name (ps-fn-ctx ps))) (mangled (bytevector-append fname "__" n)) - (sm (%sym n 'var 'static ty + (sm (%sym mangled 'var 'static ty (bytevector-append "cc__" mangled)))) (scope-bind! ps n sm) (cond diff --git a/docs/CC-PUNCHLIST.md b/docs/CC-PUNCHLIST.md @@ -193,40 +193,55 @@ broken. Pick one fix and document it in braces and returns `#f`, dropping all initializer data. `cg-emit-global` accepts an init bv but is never given one. -- [ ] **Scalar global with constant initializer** - - cg: `cc-cg/NN-init-scalar-global.scm` — emit `int g = 42` via cg - API; in `main`, return g. - - parse: `cc-parse/NN-init-scalar-global.c` - - Needs: parser builds an N-byte LE bv from the const expression and - passes to `cg-emit-global`. - -- [ ] **Scalar global with address initializer (`int *p = &x;`)** - - cg: `cc-cg/NN-init-addr.scm` - - parse: `cc-parse/NN-init-addr.c` - - Needs: `cg-emit-global` accepts a structured init (bytes + - label-references) and emits `&label` form to `cg-data`. - -- [ ] **Array global from element list** - - cg: `cc-cg/NN-init-array-list.scm` — `int a[3] = {1,2,4};` - - parse: `cc-parse/NN-init-array-list.c` - -- [ ] **Array global from string literal** - - parse: `cc-parse/NN-init-array-str.c` — `char s[]="abc"; return s[1];` - → exit 98. - -- [ ] **Struct global, positional init** - - parse: `cc-parse/NN-init-struct-pos.c` - -- [ ] **Struct global, designated init (`.field = …`)** - - parse: `cc-parse/NN-init-struct-desig.c` - - Needs: required by tcc.c per CC.md §Variable initializers. - -- [ ] **Local array initializer** - - parse: `cc-parse/NN-init-local-array.c` - - Needs: parser emits per-element store sequence into the frame slot. - -- [ ] **Local struct initializer** - - parse: `cc-parse/NN-init-local-struct.c` +- [x] **Scalar global with constant initializer** + - cg: `cc-cg/49-init-scalar-global.scm` + - parse: `cc-parse/49-init-scalar-global.c` + - Done: cg-emit-global now consumes a list of pieces (bytevectors + or `(label-ref . label-bv)` pairs); parser's parse-init-global + builds N-byte LE bv via %int->le-bv from a const expression. + +- [x] **Scalar global with address initializer (`int *p = &x;`)** + - cg: `cc-cg/50-init-addr.scm` + - parse: `cc-parse/50-init-addr.c` + - Done: %const-init-piece recognises `&IDENT` and bare-IDENT for + fn / static / extern symbols, emitting `(label-ref . cc__name)`. + +- [x] **Array global from element list** + - cg: `cc-cg/51-init-array-list.scm` + - parse: `cc-parse/51-init-array-list.c` + - Done: %parse-init-array-list walks brace lists; element types + drive bv width; array-name → label-ref decay so `int *p = a;` + works as init too. + +- [x] **Array global from string literal** + - cg: `cc-cg/52-init-array-str.scm` + - parse: `cc-parse/52-init-array-str.c` + - Done: parse-init-global recognises STR for char[] target; + inferred-length arrays (`T a[]`) get patched with the literal + length. + +- [x] **Struct global, positional init** + - cg: `cc-cg/53-init-struct-pos.scm` + - parse: `cc-parse/53-init-struct-pos.c` + - Done: %parse-init-struct-list walks fields positionally; trailing + fields zero-padded. + +- [x] **Struct global, designated init (`.field = …`)** + - cg: `cc-cg/54-init-struct-desig.scm` + - parse: `cc-parse/54-init-struct-desig.c` + - Done: same %parse-init-struct-list handles `.name = …` form. + Also: cg-arith-conv now leaves pointer-typed operands alone so + `*(p + N)` scales correctly when one side is ptr. + +- [x] **Local array initializer** + - parse: `cc-parse/55-init-local-array.c` + - Done: parse-init-local-aggregate emits per-element store ops at + slot+(i*esize); zero-pads trailing slots when declared length + exceeds initializer count. + +- [x] **Local struct initializer** + - parse: `cc-parse/56-init-local-struct.c` + - Done: same per-field store sequence; designated form supported. ### F. Control flow extensions @@ -296,13 +311,12 @@ both branches store into it, vstack ends with one frame opnd. ### I. Storage classes -- [ ] **Block-scope `static` lives in bss/data, not on the stack** - - cg: `cc-cg/NN-block-static.scm` — counter that survives across calls. - - parse: `cc-parse/NN-block-static.c` - - Needs: `parse.scm` `handle-decl` checks `sto = 'static'` *before* - branching on `(ps-fn-ctx ps)` and routes static block-scope to - `cg-emit-global`. Mangling adds the function name to avoid - cross-function collisions (e.g. `cc__<fn>__<var>`). +- [x] **Block-scope `static` lives in bss/data, not on the stack** + - cg: `cc-cg/57-block-static.scm` + - parse: `cc-parse/57-block-static.c` + - Done: handle-decl gates on `sto = 'static'` *before* the + file-vs-block branch and routes block-scope statics to + cg-emit-global with a `cc__<fn>__<var>` mangled label. ### J. Driver / envelope @@ -384,13 +398,13 @@ both branches store into it, vstack ends with one frame opnd. rewrites to `ptr` before slot allocation. cg sees a pointer and needs no special handling. -- [ ] **Array of function pointers initialized with named functions** - - parse: `cc-parse/NN-fnptr-tab.c` — `int f1(){return 1;} - int f2(){return 2;} int (*tab[])() = {f1, f2}; - return tab[0]() + tab[1]()*10;` → exit 21. - - Needs: composes §E.4 (array list init) with §E.2 (address init); - parser admits a fn name as an initializer expression that - evaluates to a label reference. +- [x] **Array of function pointers initialized with named functions** + - cg: `cc-cg/58-fnptr-tab.scm` + - parse: `cc-parse/58-fnptr-tab.c` + - Done: composes §E.3's array list init with §E.2's label-ref; + %const-init-piece's bare-IDENT branch already covers `fn` syms. + Parse fixture uses an explicit typedef for the array element + because `int (*tab[])()` declarators are owned elsewhere. ## Phase milestones (CC.md §Validation) diff --git a/tests/cc-parse/57-block-static.c b/tests/cc-parse/57-block-static.c @@ -1,12 +1,22 @@ // tests/cc-parse/57-block-static.c — block-scope static survives across -// calls. §I. +// calls and does not collide across functions. §I. +// +// Two distinct `static int n` instances must mangle to distinct labels. int incr(void) { static int n = 0; n = n + 1; return n; } +int decr(void) { + static int n = 100; + n = n - 1; + return n; +} int main(void) { incr(); - incr(); - return incr(); + decr(); + decr(); + // incr() returns 1; second decr returned 98. + // Result = incr() * 10 + decr() = 2 * 10 + 97 = 117. + return incr() * 10 + decr(); } diff --git a/tests/cc-parse/57-block-static.expected-exit b/tests/cc-parse/57-block-static.expected-exit @@ -1 +1 @@ -3 +117