boot2

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

commit 0fd2a385eff1429fab658443cb8c57f015cc3b1f
parent 4e861efba1981b1b0be51750f604825520dceff1
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Sun, 26 Apr 2026 22:26:42 -0700

cc tests: switch / case / default with fall-through (§F.3)

Validates the existing swctx machinery: cg-switch-begin spills the
controlling expression, cg-switch-case + cg-switch-default record
labels, and cg-switch-end emits the dispatch table at the bottom.
Fall-through is the natural default since cases emit no break.

Diffstat:
Atests/cc-cg/64-switch.expected-exit | 1+
Atests/cc-cg/64-switch.scm | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/cc-parse/65-switch.c | 13+++++++++++++
Atests/cc-parse/65-switch.expected-exit | 1+
4 files changed, 88 insertions(+), 0 deletions(-)

diff --git a/tests/cc-cg/64-switch.expected-exit b/tests/cc-cg/64-switch.expected-exit @@ -0,0 +1 @@ +9 diff --git a/tests/cc-cg/64-switch.scm b/tests/cc-cg/64-switch.scm @@ -0,0 +1,73 @@ +;; tests/cc-cg/64-switch.scm — switch with case + default + fall-through (§F.3). +;; Models: +;; int main(void) { +;; int x = 2; int s = 0; +;; switch (x) { +;; case 1: s = s + 1; /* fall through */ +;; case 2: s = s + 10; /* fall through */ +;; case 3: s = s + 100; /* fall through */ +;; default: s = s + 1000; +;; } +;; return s; /* x=2 -> 10 + 100 + 1000 = 1110, but exit code low byte = 86 */ +;; } +;; To stay within exit-code range we rewrite to small contributions and +;; pick x=2 hitting case 2 + 3 + default = 7. Final exit = 7. +;; +;; Body sketch (small ints only): +;; x=2; s=0; +;; case 1: s+=1 (skipped, x=2) +;; case 2: s+=2 (taken) +;; case 3: s+=3 (fall-through) +;; default: s+=4 (fall-through) +;; Result: 2 + 3 + 4 = 9 +;; Exit = 9. + +(let* ((cg (cg-init)) + (params (cg-fn-begin cg "main" '() %t-i32)) + (x-sl (cg-alloc-slot cg 4 4)) + (s-sl (cg-alloc-slot cg 4 4)) + (x-sym (%sym "x" 'var 'auto %t-i32 x-sl)) + (s-sym (%sym "s" 'var 'auto %t-i32 s-sl))) + ;; x = 2; s = 0; + (cg-push-sym cg x-sym) (cg-push-imm cg %t-i32 2) + (cg-assign cg) (cg-pop cg) + (cg-push-sym cg s-sym) (cg-push-imm cg %t-i32 0) + (cg-assign cg) (cg-pop cg) + + ;; switch (x) { ... } + (cg-push-sym cg x-sym) (cg-load cg) + (let ((sw (cg-switch-begin cg))) + ;; case 1: s = s + 1; + (cg-switch-case cg sw 1) + (cg-push-sym cg s-sym) + (cg-push-sym cg s-sym) (cg-load cg) + (cg-push-imm cg %t-i32 1) + (cg-binop cg 'add) + (cg-assign cg) (cg-pop cg) + ;; case 2: s = s + 2; + (cg-switch-case cg sw 2) + (cg-push-sym cg s-sym) + (cg-push-sym cg s-sym) (cg-load cg) + (cg-push-imm cg %t-i32 2) + (cg-binop cg 'add) + (cg-assign cg) (cg-pop cg) + ;; case 3: s = s + 3; + (cg-switch-case cg sw 3) + (cg-push-sym cg s-sym) + (cg-push-sym cg s-sym) (cg-load cg) + (cg-push-imm cg %t-i32 3) + (cg-binop cg 'add) + (cg-assign cg) (cg-pop cg) + ;; default: s = s + 4; + (cg-switch-default cg sw) + (cg-push-sym cg s-sym) + (cg-push-sym cg s-sym) (cg-load cg) + (cg-push-imm cg %t-i32 4) + (cg-binop cg 'add) + (cg-assign cg) (cg-pop cg) + (cg-switch-end cg sw)) + + (cg-push-sym cg s-sym) (cg-load cg) + (cg-return cg) + (cg-fn-end cg) + (write-bv-fd 1 (cg-finish cg))) diff --git a/tests/cc-parse/65-switch.c b/tests/cc-parse/65-switch.c @@ -0,0 +1,13 @@ +int main(void) { + int x; int s; + x = 2; + s = 0; + switch (x) { + case 1: s = s + 1; + case 2: s = s + 2; + case 3: s = s + 3; + default: s = s + 4; + } + /* x = 2 hits case 2; falls through case 3 + default; s = 2+3+4 = 9 */ + return s; +} diff --git a/tests/cc-parse/65-switch.expected-exit b/tests/cc-parse/65-switch.expected-exit @@ -0,0 +1 @@ +9