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:
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