boot2

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

070-struct-ret-1word.scm (2358B)


      1 ;; tests/cc-cg/70-struct-ret-1word.scm — one-word direct struct return.
      2 ;;
      3 ;; Models:
      4 ;;   struct S { int a; int b; };
      5 ;;   struct S make(int a, int b) { struct S s; s.a = a; s.b = b; return s; }
      6 ;;   int main(void) {
      7 ;;     struct S r = make(7, 9);
      8 ;;     return r.a + r.b * 10;     /* 97 */
      9 ;;   }
     10 ;;
     11 ;; Exercises Stream A1's one-word direct return convention (P1.md
     12 ;; §Arguments and return values): result word 0 in a0; cg-fn-end emits
     13 ;; LD a0, [sp + ret-slot] at exit; cg-call's receive side allocates a
     14 ;; fresh frame slot sized to the return ctype, stores back from a0,
     15 ;; and pushes a struct frame-lval so chained .field works.
     16 
     17 (let* ((cg     (cg-init))
     18        (st-ty  (%ctype 'struct 8 4
     19                        (list "S" #t
     20                              (list (list "a" %t-i32 0)
     21                                    (list "b" %t-i32 4)))))
     22        (fn-ty  (%ctype 'fn 8 8
     23                        (cons st-ty (cons (list %t-i32 %t-i32) #f))))
     24        (make-sym (%sym "make" 'fn 'extern fn-ty #f)))
     25   ;; struct S make(int a, int b) { ... return s; }
     26   (let* ((params (cg-fn-begin cg "make"
     27                               (list (cons "a" %t-i32) (cons "b" %t-i32))
     28                               st-ty))
     29          (a*     (cdr (car params)))
     30          (b*     (cdr (cadr params)))
     31          (s-off  (cg-alloc-slot cg 8 4))
     32          (s-sym  (%sym "s" 'var 'auto st-ty s-off)))
     33     ;; s.a = a
     34     (cg-push-sym cg s-sym) (cg-push-field cg "a")
     35     (cg-push-sym cg a*)    (cg-load cg)
     36     (cg-assign cg) (cg-pop cg)
     37     ;; s.b = b
     38     (cg-push-sym cg s-sym) (cg-push-field cg "b")
     39     (cg-push-sym cg b*)    (cg-load cg)
     40     (cg-assign cg) (cg-pop cg)
     41     ;; return s   — struct-typed return
     42     (cg-push-sym cg s-sym)
     43     (cg-return cg)
     44     (cg-fn-end cg))
     45   ;; int main(void) { struct S r = make(7, 9); return r.a + r.b * 10; }
     46   (cg-fn-begin cg "main" '() %t-i32)
     47   (cg-push-sym cg make-sym)
     48   (cg-push-imm cg %t-i32 7)
     49   (cg-push-imm cg %t-i32 9)
     50   (cg-call cg 2 #t)              ; pushes struct lval (recv slot)
     51   ;; The result is a struct lval. Read .a and .b.
     52   (let ((r-lval (cg-pop cg)))
     53     (cg-push cg r-lval) (cg-push-field cg "a") (cg-load cg)
     54     (cg-push cg r-lval) (cg-push-field cg "b") (cg-load cg)
     55     (cg-push-imm cg %t-i32 10) (cg-binop cg 'mul)
     56     (cg-binop cg 'add))
     57   (cg-return cg)
     58   (cg-fn-end cg)
     59   (write-bv-fd 1 (cg-finish cg)))