boot2

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

commit 80eb7c8b7ce3dc42942a3eeb59f1a7da5ca38f58
parent 86d9a1621b89d759d311c487e14bbd1adfb3bff1
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Sun, 26 Apr 2026 22:40:56 -0700

cc/cg+parse: struct global positional init (§E.5)

cc-cg fixture: emit `struct S { int a; int b; } s = {3, 4}` as two
4-byte LE pieces; main reads both fields via &s + scaled offset.

cc-parse fixture: same shape from C source, reading the first field
through `(int *)&s`. Member-access codegen (s.a) routes through the
parse-postfix-rest stub today (Agent 2's §D); we stay clear of it.

Diffstat:
Atests/cc-cg/53-init-struct-pos.expected-exit | 1+
Atests/cc-cg/53-init-struct-pos.scm | 36++++++++++++++++++++++++++++++++++++
Atests/cc-parse/53-init-struct-pos.c | 11+++++++++++
Atests/cc-parse/53-init-struct-pos.expected-exit | 1+
4 files changed, 49 insertions(+), 0 deletions(-)

diff --git a/tests/cc-cg/53-init-struct-pos.expected-exit b/tests/cc-cg/53-init-struct-pos.expected-exit @@ -0,0 +1 @@ +43 diff --git a/tests/cc-cg/53-init-struct-pos.scm b/tests/cc-cg/53-init-struct-pos.scm @@ -0,0 +1,36 @@ +;; tests/cc-cg/53-init-struct-pos.scm — global struct {int a; int b;} +;; with positional initializer. §E.5. +;; +;; Models: struct S { int a; int b; }; struct S s = {3, 4}; return s.a + s.b*10; +;; main returns 43. +;; +;; cc-cg drives the cg API directly; we read a (offset 0) and b (offset 4) +;; via &s + offset and a cast to int*. + +(let* ((cg (cg-init)) + ;; Build struct ctype: { int a; int b; } + (sty (%ctype 'struct 8 4 + (list "S" #t + (list (list "a" %t-i32 0) + (list "b" %t-i32 4))))) + (s (%sym "s" 'var 'static sty #f)) + ;; Init: 3 (4 bytes LE) | 4 (4 bytes LE) + (bvA (make-bytevector 4 0)) (_a (bytevector-u8-set! bvA 0 3)) + (bvB (make-bytevector 4 0)) (_b (bytevector-u8-set! bvB 0 4))) + (cg-emit-global cg s (list bvA bvB)) + (cg-fn-begin cg "main" '() %t-i32) + (let ((load-field + (lambda (off) + (cg-push-sym cg s) (cg-take-addr cg) + (cg-cast cg (%ctype 'ptr 8 8 %t-i32)) + (cg-push-imm cg %t-i32 off) + (cg-binop cg 'add) + (cg-push-deref cg) (cg-load cg)))) + (load-field 0) ; s.a == 3 + (load-field 1) ; s.b == 4 (4 bytes / 4 = +1 in int*-units) + (cg-push-imm cg %t-i32 10) + (cg-binop cg 'mul) + (cg-binop cg 'add)) + (cg-return cg) + (cg-fn-end cg) + (write-bv-fd 1 (cg-finish cg))) diff --git a/tests/cc-parse/53-init-struct-pos.c b/tests/cc-parse/53-init-struct-pos.c @@ -0,0 +1,11 @@ +// tests/cc-parse/53-init-struct-pos.c — global struct positional init. §E.5. +// +// Struct member access (.a/.b) is currently stubbed to offset 0 in +// parse-postfix-rest (Agent 2's §D). To stay inside the working surface, +// we treat &s as int* and read the first field by deref. +struct S { int a; int b; }; +struct S s = {3, 4}; +int main(void) { + int *p = (int *)&s; + return *p; +} diff --git a/tests/cc-parse/53-init-struct-pos.expected-exit b/tests/cc-parse/53-init-struct-pos.expected-exit @@ -0,0 +1 @@ +3