commit 6f39189e57b48699aab8e681d4c6426219a970c0
parent 0941b72ae2a2fe737f7a9affa37553da2bb78287
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Sun, 26 Apr 2026 22:36:34 -0700
cc/cg: lock in struct member store fixture (§D.2)
Three u8 fields at offsets 0..2; distinct *1, *10, *100 multipliers
in the readback isolate each field's contribution, so a width bug
or offset bug surfaces as a wrong sum. No new cg primitive — this
is §D.1's cg-push-field composed with the width-aware store path
from §A.1. The fixture exists separately so the §D.2 row in the
punchlist has its own runtime witness.
Diffstat:
2 files changed, 57 insertions(+), 0 deletions(-)
diff --git a/tests/cc-cg/37-struct-store.expected-exit b/tests/cc-cg/37-struct-store.expected-exit
@@ -0,0 +1 @@
+1
diff --git a/tests/cc-cg/37-struct-store.scm b/tests/cc-cg/37-struct-store.scm
@@ -0,0 +1,56 @@
+;; tests/cc-cg/37-struct-store.scm — struct member store via cg-push-field
+;; (§D.2 of docs/CC-PUNCHLIST.md). Uses char-typed fields to ensure the
+;; width-correct store path from §A.1 cooperates with field offsets.
+;;
+;; struct B { unsigned char a; unsigned char b; unsigned char c; };
+;; b.a = 3; b.b = 5; b.c = 7;
+;; If field stores ignored offsets (or used 8-byte writes), adjacent
+;; bytes would clobber each other. Reading back a*1 + b*10 + c*100
+;; isolates each field's contribution: 3 + 50 + 700 = 753. (Truncated
+;; to a u8 by the exit-code path: 753 & 255 = 241.)
+
+(let* ((cg (cg-init))
+ (st-ty (%ctype 'struct 3 1
+ (list "B" #t
+ (list (list "a" %t-u8 0)
+ (list "b" %t-u8 1)
+ (list "c" %t-u8 2))))))
+ (cg-fn-begin cg "main" '() %t-i32)
+ (let* ((off-b (cg-alloc-slot cg 3 1))
+ (sym-b (%sym "b" 'var 'auto st-ty off-b)))
+ ;; b.a = 3
+ (cg-push-sym cg sym-b)
+ (cg-push-field cg "a")
+ (cg-push-imm cg %t-u8 3)
+ (cg-assign cg) (cg-pop cg)
+ ;; b.b = 5
+ (cg-push-sym cg sym-b)
+ (cg-push-field cg "b")
+ (cg-push-imm cg %t-u8 5)
+ (cg-assign cg) (cg-pop cg)
+ ;; b.c = 7
+ (cg-push-sym cg sym-b)
+ (cg-push-field cg "c")
+ (cg-push-imm cg %t-u8 7)
+ (cg-assign cg) (cg-pop cg)
+ ;; return (b.a + b.b*10 + b.c*100) == 753
+ (cg-push-sym cg sym-b)
+ (cg-push-field cg "a")
+ (cg-load cg)
+ (cg-push-sym cg sym-b)
+ (cg-push-field cg "b")
+ (cg-load cg)
+ (cg-push-imm cg %t-i32 10)
+ (cg-binop cg 'mul)
+ (cg-binop cg 'add)
+ (cg-push-sym cg sym-b)
+ (cg-push-field cg "c")
+ (cg-load cg)
+ (cg-push-imm cg %t-i32 100)
+ (cg-binop cg 'mul)
+ (cg-binop cg 'add)
+ (cg-push-imm cg %t-i32 753)
+ (cg-binop cg 'eq)
+ (cg-return cg))
+ (cg-fn-end cg)
+ (write-bv-fd 1 (cg-finish cg)))