commit db4d877362e9b952d72f15507e5e5fa481cd7b5d
parent 1609330a4c15372a20e6e3478499d792aaf66f9e
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Sun, 26 Apr 2026 22:39:33 -0700
cc/cg: lock in p->x arrow access via cg fixture (§D.3)
cg-push-deref + cg-push-field already supported the indirect path:
the ptr-rval is push-deref'd to a struct lval (frame-indirect),
then cg-push-field's indirect-frame branch loads the address, adds
the field offset, and stashes it in a new indirect slot. The
fixture composes the existing primitives end-to-end so any
regression in either lands here.
Diffstat:
2 files changed, 60 insertions(+), 0 deletions(-)
diff --git a/tests/cc-cg/38-arrow.expected-exit b/tests/cc-cg/38-arrow.expected-exit
@@ -0,0 +1 @@
+5
diff --git a/tests/cc-cg/38-arrow.scm b/tests/cc-cg/38-arrow.scm
@@ -0,0 +1,59 @@
+;; tests/cc-cg/38-arrow.scm — pointer-to-struct field access via cg
+;; (§D.3 of docs/CC-PUNCHLIST.md). Models p->a / p->b through:
+;; cg-push-sym sym-p ; lval (frame), holds ptr-value
+;; cg-load ; rval ptr
+;; cg-push-deref ; lval struct (indirect)
+;; cg-push-field "a" ; lval int at p+0
+;;
+;; struct S { int a; int b; }; struct S s;
+;; struct S *p = &s; p->a = 4; p->b = 9; return p->b - p->a;
+;; (The cg fixture takes &s into a frame slot directly so we don't
+;; depend on parser-only address-of plumbing.)
+;;
+;; Expected: 9 - 4 == 5.
+
+(let* ((cg (cg-init))
+ (st-ty (%ctype 'struct 8 4
+ (list "S" #t
+ (list (list "a" %t-i32 0)
+ (list "b" %t-i32 4)))))
+ (pt-ty (%ctype 'ptr 8 8 st-ty)))
+ (cg-fn-begin cg "main" '() %t-i32)
+ (let* ((off-s (cg-alloc-slot cg 8 4))
+ (off-p (cg-alloc-slot cg 8 8))
+ (sym-s (%sym "s" 'var 'auto st-ty off-s))
+ (sym-p (%sym "p" 'var 'auto pt-ty off-p)))
+ ;; p = &s
+ (cg-push-sym cg sym-p)
+ (cg-push-sym cg sym-s)
+ (cg-take-addr cg)
+ (cg-assign cg) (cg-pop cg)
+ ;; p->a = 4
+ (cg-push-sym cg sym-p)
+ (cg-load cg)
+ (cg-push-deref cg)
+ (cg-push-field cg "a")
+ (cg-push-imm cg %t-i32 4)
+ (cg-assign cg) (cg-pop cg)
+ ;; p->b = 9
+ (cg-push-sym cg sym-p)
+ (cg-load cg)
+ (cg-push-deref cg)
+ (cg-push-field cg "b")
+ (cg-push-imm cg %t-i32 9)
+ (cg-assign cg) (cg-pop cg)
+ ;; return p->b - p->a
+ (cg-push-sym cg sym-p)
+ (cg-load cg)
+ (cg-push-deref cg)
+ (cg-push-field cg "b")
+ (cg-load cg)
+ (cg-push-sym cg sym-p)
+ (cg-load cg)
+ (cg-push-deref cg)
+ (cg-push-field cg "a")
+ (cg-load cg)
+ (cg-binop cg 'sub)
+ (cg-return cg))
+ (cg-fn-end cg)
+ (write-bv-fd 1 (cg-finish cg)))