boot2

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

commit 07aa6dbc034fab8c9f43999169b2192e7569e0d5
parent bc60420d39eb7005a0f28306a697d40171461f43
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Mon, 27 Apr 2026 11:54:47 -0700

cc/cg: use pmatch record patterns for opnd/sym dispatch

Migrates 6 opnd-kind / sym-kind dispatch sites from cond+(eq? (opnd-kind p)
'frame) chains to pmatch with ($ opnd? (kind ...) (ext ...) ...) patterns:
%cg-load-opnd-into, cg-push-sym, cg-push-field, cg-decay-array,
cg-take-addr, cg-assign, cg-va-arg. cg-va-arg shrinks the most since the
same dispatch ran twice (load ap, store ap). cg-push-sym's nested
sym-kind/sym-storage cond flattens into one pattern per kind+storage pair.

Pure refactor; no behavior change.

Diffstat:
Mcc/cg.scm | 201+++++++++++++++++++++++++++++++++++++------------------------------------------
1 file changed, 95 insertions(+), 106 deletions(-)

diff --git a/cc/cg.scm b/cc/cg.scm @@ -182,25 +182,21 @@ (else (%cg-emit-st cg reg base off))))) (define (%cg-load-opnd-into cg op reg) - (let ((kind (opnd-kind op)) (lv? (opnd-lval? op)) - (ext (opnd-ext op)) (ty (opnd-type op))) - (cond - ((eq? kind 'imm) (%cg-emit-li cg reg ext)) - ;; frame lval: load value at type width. frame rval is a spilled - ;; word (alloc-slot 8 8 in %cg-spill-reg) — always 8-byte load. - ((eq? kind 'frame) - (cond (lv? (%cg-emit-ld-slot-typed cg reg ty ext)) - (else (%cg-emit-ld-slot cg reg ext)))) - ((eq? kind 'global) - (cond - ((not lv?) (%cg-emit-la cg reg ext)) - (else - ;; Width > 1 byte-gathers must not alias dest with base — - ;; the first %lb would otherwise clobber the address before - ;; subsequent byte loads. Stage the address in t2. - (%cg-emit-la cg 't2 ext) - (%cg-emit-ld-typed cg reg ty 't2 0)))) - (else (die #f "cg internal: unknown opnd-kind" kind))))) + ;; frame lval: load at type width. frame rval is a spilled word + ;; (alloc-slot 8 8 in %cg-spill-reg) — always 8-byte load. + ;; global lval width > 1 byte-gathers must not alias dest with base — + ;; the first %lb would otherwise clobber the address before subsequent + ;; byte loads. Stage the address in t2. + (pmatch op + (($ opnd? (kind imm) (ext ,n)) (%cg-emit-li cg reg n)) + (($ opnd? (kind frame) (lval? #t) (type ,ty) (ext ,off)) + (%cg-emit-ld-slot-typed cg reg ty off)) + (($ opnd? (kind frame) (ext ,off)) (%cg-emit-ld-slot cg reg off)) + (($ opnd? (kind global) (lval? #f) (ext ,lbl)) (%cg-emit-la cg reg lbl)) + (($ opnd? (kind global) (type ,ty) (ext ,lbl)) + (%cg-emit-la cg 't2 lbl) + (%cg-emit-ld-typed cg reg ty 't2 0)) + (else (die #f "cg internal: unknown opnd-kind" (opnd-kind op))))) (define (%cg-spill-reg cg reg ty) (let* ((off (cg-alloc-slot cg 8 8)) @@ -455,24 +451,20 @@ (cg-push cg (%opnd 'global cp-ty label #f)))) (define (cg-push-sym cg sym) - (let ((k (sym-kind sym)) (ty (sym-type sym))) - (cond - ((eq? k 'fn) - (cg-push cg (%opnd 'global ty (%cg-mangle-global (sym-name sym)) #f))) - ((eq? k 'enum-const) - (cg-push cg (%opnd 'imm ty (sym-slot sym) #f))) - ((eq? k 'var) - (let ((stg (sym-storage sym))) - (cond - ((eq? stg 'extern) - (cg-push cg (%opnd 'global ty (%cg-mangle-global (sym-name sym)) #t))) - ((eq? stg 'static) - (cg-push cg (%opnd 'global ty (%cg-mangle-global (sym-name sym)) #t))) - (else - (cg-push cg (%opnd 'frame ty (sym-slot sym) #t)))))) - ((eq? k 'param) - (cg-push cg (%opnd 'frame ty (sym-slot sym) #t))) - (else (die #f "cg-push-sym: unsupported sym-kind" k))))) + (pmatch sym + (($ sym? (kind fn) (type ,ty) (name ,nm)) + (cg-push cg (%opnd 'global ty (%cg-mangle-global nm) #f))) + (($ sym? (kind enum-const) (type ,ty) (slot ,v)) + (cg-push cg (%opnd 'imm ty v #f))) + (($ sym? (kind var) (storage extern) (type ,ty) (name ,nm)) + (cg-push cg (%opnd 'global ty (%cg-mangle-global nm) #t))) + (($ sym? (kind var) (storage static) (type ,ty) (name ,nm)) + (cg-push cg (%opnd 'global ty (%cg-mangle-global nm) #t))) + (($ sym? (kind var) (type ,ty) (slot ,off)) + (cg-push cg (%opnd 'frame ty off #t))) + (($ sym? (kind param) (type ,ty) (slot ,off)) + (cg-push cg (%opnd 'frame ty off #t))) + (else (die #f "cg-push-sym: unsupported sym-kind" (sym-kind sym))))) ;; A cg-push-deref result is a frame-lval whose slot HOLDS THE ADDRESS ;; (not the value). To distinguish from ordinary frame-lvals (whose @@ -543,15 +535,15 @@ ((not f) (die #f "cg-push-field: no such field" fname)) (else (let* ((fty (cadr f)) (fo (car (cddr f)))) - (cond + (pmatch s ;; direct frame lval: just shift the slot offset. - ((and (eq? (opnd-kind s) 'frame) - (not (%cg-indirect? cg (opnd-ext s)))) - (cg-push cg (%opnd 'frame fty (+ (opnd-ext s) fo) #t))) + (($ opnd? (kind frame) (ext ,off)) + (guard (not (%cg-indirect? cg off))) + (cg-push cg (%opnd 'frame fty (+ off fo) #t))) ;; indirect frame lval: addr lives in the slot. Compute ;; addr+fo into a new indirect slot. - ((eq? (opnd-kind s) 'frame) - (%cg-emit-ld-slot cg 't0 (opnd-ext s)) + (($ opnd? (kind frame) (ext ,off)) + (%cg-emit-ld-slot cg 't0 off) (cond ((> fo 0) (%cg-emit-many cg (list "%addi(t0, t0, " (%n fo) ")\n")))) @@ -560,8 +552,8 @@ (%cg-mark-indirect! cg no) (cg-push cg (%opnd 'frame fty no #t)))) ;; global lval: load addr, add offset, indirect slot. - ((eq? (opnd-kind s) 'global) - (%cg-emit-la cg 't0 (opnd-ext s)) + (($ opnd? (kind global) (ext ,lbl)) + (%cg-emit-la cg 't0 lbl) (cond ((> fo 0) (%cg-emit-many cg (list "%addi(t0, t0, " (%n fo) ")\n")))) @@ -581,25 +573,25 @@ (let ((tp (cg-top cg))) (cond ((and (opnd-lval? tp) (eq? (ctype-kind (opnd-type tp)) 'arr)) - (let* ((p (cg-pop cg)) - (et (car (ctype-ext (opnd-type p)))) + (let* ((p (cg-pop cg)) + (et (car (ctype-ext (opnd-type p)))) (pty (%ctype 'ptr 8 8 et))) - (cond + (pmatch p ;; direct frame lval: address is sp+off. - ((and (eq? (opnd-kind p) 'frame) - (not (%cg-indirect? cg (opnd-ext p)))) + (($ opnd? (kind frame) (ext ,off)) + (guard (not (%cg-indirect? cg off))) (%cg-emit-many cg (list "%mov(t0, sp)\n" "%addi(t0, t0, " - (%cg-slot-expr cg (opnd-ext p)) ")\n")) + (%cg-slot-expr cg off) ")\n")) (%cg-spill-reg cg 't0 pty)) ;; indirect frame lval (rare for arrays, but support it): ;; the slot holds the address already. - ((eq? (opnd-kind p) 'frame) - (%cg-emit-ld-slot cg 't0 (opnd-ext p)) + (($ opnd? (kind frame) (ext ,off)) + (%cg-emit-ld-slot cg 't0 off) (%cg-spill-reg cg 't0 pty)) ;; global array: la(label) is the address. - ((eq? (opnd-kind p) 'global) - (%cg-emit-la cg 't0 (opnd-ext p)) + (($ opnd? (kind global) (ext ,lbl)) + (%cg-emit-la cg 't0 lbl) (%cg-spill-reg cg 't0 pty)) (else (die #f "cg-decay-array: unsupported lval kind" (opnd-kind p)))))) @@ -616,24 +608,22 @@ ;; &arr + 1 is one-past-end. Array-to-pointer decay happens ;; on use via cg-decay-array, not at the & operator. (pty (%ctype 'ptr 8 8 ty))) - (cond - ((not (opnd-lval? p)) - (die #f "cg-take-addr: not an lvalue")) - ((eq? (opnd-kind p) 'frame) - (cond - ((%cg-indirect? cg (opnd-ext p)) - ;; The address itself lives at sp+slot — &*p degenerates to p. - (%cg-emit-ld-slot cg 't0 (opnd-ext p)) - (%cg-spill-reg cg 't0 pty)) - (else - ;; %mov(rd, sp) gives the portable-sp pointer (the backend - ;; handles any hidden frame-header offset). Then add slot. - (%cg-emit-many cg (list "%mov(t0, sp)\n" - "%addi(t0, t0, " - (%cg-slot-expr cg (opnd-ext p)) ")\n")) - (%cg-spill-reg cg 't0 pty)))) - ((eq? (opnd-kind p) 'global) - (%cg-emit-la cg 't0 (opnd-ext p)) + (pmatch p + (($ opnd? (lval? #f)) (die #f "cg-take-addr: not an lvalue")) + ;; The address itself lives at sp+slot — &*p degenerates to p. + (($ opnd? (kind frame) (ext ,off)) + (guard (%cg-indirect? cg off)) + (%cg-emit-ld-slot cg 't0 off) + (%cg-spill-reg cg 't0 pty)) + ;; %mov(rd, sp) gives the portable-sp pointer (the backend + ;; handles any hidden frame-header offset). Then add slot. + (($ opnd? (kind frame) (ext ,off)) + (%cg-emit-many cg (list "%mov(t0, sp)\n" + "%addi(t0, t0, " + (%cg-slot-expr cg off) ")\n")) + (%cg-spill-reg cg 't0 pty)) + (($ opnd? (kind global) (ext ,lbl)) + (%cg-emit-la cg 't0 lbl) (%cg-spill-reg cg 't0 pty)) (else (die #f "cg-take-addr: non-addressable" (opnd-kind p)))))) @@ -873,20 +863,19 @@ (cg-push cg rhs0) (cg-cast cg ty) (let ((rhs (cg-pop cg))) - (%cg-load-opnd-into cg rhs 'a0) - (cond - ((eq? (opnd-kind lhs) 'frame) - (cond - ((%cg-indirect? cg (opnd-ext lhs)) - (%cg-emit-ld-slot cg 't0 (opnd-ext lhs)) - (%cg-emit-st-typed cg 'a0 ty 't0 0)) - (else - (%cg-emit-st-slot-typed cg 'a0 ty (opnd-ext lhs))))) - ((eq? (opnd-kind lhs) 'global) - (%cg-emit-la cg 't0 (opnd-ext lhs)) - (%cg-emit-st-typed cg 'a0 ty 't0 0)) - (else (die #f "cg-assign: unsupported lhs kind" (opnd-kind lhs)))) - (%cg-spill-reg cg 'a0 ty)))) + (%cg-load-opnd-into cg rhs 'a0) + (pmatch lhs + (($ opnd? (kind frame) (ext ,off)) + (guard (%cg-indirect? cg off)) + (%cg-emit-ld-slot cg 't0 off) + (%cg-emit-st-typed cg 'a0 ty 't0 0)) + (($ opnd? (kind frame) (ext ,off)) + (%cg-emit-st-slot-typed cg 'a0 ty off)) + (($ opnd? (kind global) (ext ,lbl)) + (%cg-emit-la cg 't0 lbl) + (%cg-emit-st-typed cg 'a0 ty 't0 0)) + (else (die #f "cg-assign: unsupported lhs kind" (opnd-kind lhs)))) + (%cg-spill-reg cg 'a0 ty)))) ;; -------------------------------------------------------------------- ;; Calls @@ -1059,19 +1048,19 @@ ;; Pop ap-lval. Load ap into a0. Read 8 bytes at [a0] into a1. ;; Advance a0 by 8 and store back through ap-lval. Push a1 as rval ;; of type ctype (caller cg-cast's if needed). - (let* ((ap-lv (cg-pop cg))) + (let ((ap-lv (cg-pop cg))) (cond ((not (opnd-lval? ap-lv)) (die #f "cg-va-arg: ap not lvalue"))) ;; Load ap into a0. - (cond - ((eq? (opnd-kind ap-lv) 'frame) - (cond - ((%cg-indirect? cg (opnd-ext ap-lv)) - (%cg-emit-ld-slot cg 't0 (opnd-ext ap-lv)) - (%cg-emit-ld cg 'a0 't0 0)) - (else (%cg-emit-ld-slot cg 'a0 (opnd-ext ap-lv))))) - ((eq? (opnd-kind ap-lv) 'global) - (%cg-emit-la cg 't0 (opnd-ext ap-lv)) + (pmatch ap-lv + (($ opnd? (kind frame) (ext ,off)) + (guard (%cg-indirect? cg off)) + (%cg-emit-ld-slot cg 't0 off) + (%cg-emit-ld cg 'a0 't0 0)) + (($ opnd? (kind frame) (ext ,off)) + (%cg-emit-ld-slot cg 'a0 off)) + (($ opnd? (kind global) (ext ,lbl)) + (%cg-emit-la cg 't0 lbl) (%cg-emit-ld cg 'a0 't0 0)) (else (die #f "cg-va-arg: bad ap kind" (opnd-kind ap-lv)))) ;; Load value at [a0] into a1 (full 8 bytes; cg-cast on the rval @@ -1080,15 +1069,15 @@ ;; Advance ap by 8. (%cg-emit-many cg (list "%addi(a0, a0, 8)\n")) ;; Store advanced ap back. - (cond - ((eq? (opnd-kind ap-lv) 'frame) - (cond - ((%cg-indirect? cg (opnd-ext ap-lv)) - (%cg-emit-ld-slot cg 't0 (opnd-ext ap-lv)) - (%cg-emit-st cg 'a0 't0 0)) - (else (%cg-emit-st-slot cg 'a0 (opnd-ext ap-lv))))) - ((eq? (opnd-kind ap-lv) 'global) - (%cg-emit-la cg 't0 (opnd-ext ap-lv)) + (pmatch ap-lv + (($ opnd? (kind frame) (ext ,off)) + (guard (%cg-indirect? cg off)) + (%cg-emit-ld-slot cg 't0 off) + (%cg-emit-st cg 'a0 't0 0)) + (($ opnd? (kind frame) (ext ,off)) + (%cg-emit-st-slot cg 'a0 off)) + (($ opnd? (kind global) (ext ,lbl)) + (%cg-emit-la cg 't0 lbl) (%cg-emit-st cg 'a0 't0 0)) (else 0)) ;; Spill the loaded value (a1) to a fresh frame slot under ctype.