boot2

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

commit 9c40bcc14c1d4d7eed39d4da9dbe8fc53006a1c2
parent 0fd2a385eff1429fab658443cb8c57f015cc3b1f
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Sun, 26 Apr 2026 22:31:45 -0700

cc/cg: add cg-emit-label / cg-goto for goto+labels (§F.4)

cg-emit-label name-bv drops `::user_<name>` so libp1pp's %scope
mechanism prefixes it to `<fn>__user_<name>`. cg-goto emits
`%b(&::user_<name>)`. Forward refs work because resolution is at
emit time.

Drive-by: cg-binop 'le/'ge previously emitted %xori, which is not
defined anywhere in P1/. Replaced with %li(t1,1) %xor(t0,t0,t1).
The first fixture to exercise these cmps is 65-goto.

Diffstat:
Mcc/cg.scm | 17+++++++++++++++--
Atests/cc-cg/65-goto.expected-exit | 1+
Atests/cc-cg/65-goto.scm | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 73 insertions(+), 2 deletions(-)

diff --git a/cc/cg.scm b/cc/cg.scm @@ -589,10 +589,10 @@ ((eq? op 'gt) (%cg-emit-cmp cg (if unsigned? "ltu" "lt") 'a1 'a0 't0)) ((eq? op 'le) (%cg-emit-cmp cg (if unsigned? "ltu" "lt") 'a1 'a0 't0) - (%cg-emit-many cg (list "%xori(t0, t0, 1)\n"))) + (%cg-emit-many cg (list "%li(t1, 1)\n%xor(t0, t0, t1)\n"))) ((eq? op 'ge) (%cg-emit-cmp cg (if unsigned? "ltu" "lt") 'a0 'a1 't0) - (%cg-emit-many cg (list "%xori(t0, t0, 1)\n"))) + (%cg-emit-many cg (list "%li(t1, 1)\n%xor(t0, t0, t1)\n"))) (else (die #f "cg-binop: unknown op" op))) (%cg-spill-reg cg 't0 result-ty))))) @@ -735,6 +735,19 @@ (%cg-emit-many cg (list "%continue(" tag ")\n"))) ;; -------------------------------------------------------------------- +;; Labels and unconditional goto (§F.4 / CC-CONTRACTS §5.3). +;; user_<name> namespace keeps the user's label space disjoint from +;; the compiler-internal ::ret and ::lbl_<n>. Labels resolve through +;; libp1pp's %scope mechanism, so forward references inside the same +;; %fn block work without explicit forward declaration. +;; -------------------------------------------------------------------- +(define (cg-emit-label cg name-bv) + (%cg-emit-many cg (list "::user_" name-bv "\n"))) + +(define (cg-goto cg name-bv) + (%cg-emit-many cg (list "%b(&::user_" name-bv ")\n"))) + +;; -------------------------------------------------------------------- ;; switch ;; -------------------------------------------------------------------- (define-record-type swctx diff --git a/tests/cc-cg/65-goto.expected-exit b/tests/cc-cg/65-goto.expected-exit @@ -0,0 +1 @@ +3 diff --git a/tests/cc-cg/65-goto.scm b/tests/cc-cg/65-goto.scm @@ -0,0 +1,57 @@ +;; tests/cc-cg/65-goto.scm — goto + labelled statements, forward and back (§F.4). +;; Models a counter that uses goto for both forward skip and backward jump: +;; int main(void) { +;; int s = 0; +;; int i = 0; +;; loop: +;; if (i >= 3) goto done; +;; s = s + 1; +;; i = i + 1; +;; goto loop; +;; done: +;; return s; /* 3 */ +;; } +;; +;; Exercises cg-emit-label (drops ::user_<name>) and cg-goto (emits +;; %b(&::user_<name>)). Forward refs work because libp1pp's %scope +;; resolves labels at emit time. + +(let* ((cg (cg-init)) + (params (cg-fn-begin cg "main" '() %t-i32)) + (s-sl (cg-alloc-slot cg 4 4)) + (i-sl (cg-alloc-slot cg 4 4)) + (s-sym (%sym "s" 'var 'auto %t-i32 s-sl)) + (i-sym (%sym "i" 'var 'auto %t-i32 i-sl))) + ;; s = 0; i = 0; + (cg-push-sym cg s-sym) (cg-push-imm cg %t-i32 0) + (cg-assign cg) (cg-pop cg) + (cg-push-sym cg i-sym) (cg-push-imm cg %t-i32 0) + (cg-assign cg) (cg-pop cg) + + ;; loop: + (cg-emit-label cg "loop") + ;; if (i >= 3) goto done; + (cg-push-sym cg i-sym) (cg-load cg) + (cg-push-imm cg %t-i32 3) + (cg-binop cg 'ge) + (cg-if cg (lambda () (cg-goto cg "done"))) + ;; s = s + 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) + ;; i = i + 1; + (cg-push-sym cg i-sym) + (cg-push-sym cg i-sym) (cg-load cg) + (cg-push-imm cg %t-i32 1) + (cg-binop cg 'add) + (cg-assign cg) (cg-pop cg) + ;; goto loop; + (cg-goto cg "loop") + ;; done: + (cg-emit-label cg "done") + (cg-push-sym cg s-sym) (cg-load cg) + (cg-return cg) + (cg-fn-end cg) + (write-bv-fd 1 (cg-finish cg)))