Can now pass about adts stored on the stack
authorLuke Lau <luke_lau@icloud.com>
Wed, 14 Aug 2019 13:09:54 +0000 (14:09 +0100)
committerLuke Lau <luke_lau@icloud.com>
Wed, 14 Aug 2019 13:09:54 +0000 (14:09 +0100)
abi.md
codegen.scm
tests.scm

diff --git a/abi.md b/abi.md
index c2ff16575c1da283f8c4d9c63a06d24c5ebe96ce..0dbbcc4942b21515229a11ad8f1945f1c22163a6 100644 (file)
--- a/abi.md
+++ b/abi.md
@@ -62,3 +62,8 @@ e.g.
 
 * param 0: pointer to the value of `x`
 * param 1: the value of`y`
+
+# inter-function and stack values
+
+ints, bools and closures are passed around within functions in `%rax`.
+adts are passed on the stack, at whatever stack index the code generation was called with.
\ No newline at end of file
index dededbec01e0856b19703d8945e096e49b316aa5..9c692e7c1835c337fa9b9fc66812345e36e89c08 100644 (file)
           (adt-size adt)
           (error #f "unknown size" type)))]))
 
+                                       ; returns the size of an expression's result in bytes
+(define (expr-size e)
+  (if (eqv? (ast-type e) 'stack)
+      (cadr e)
+      wordsize))
+
 (define (on-stack? expr)
   (case (ast-type expr)
     ['stack (cadr expr)]
     (and (eqv? (ast-type expr) 'closure)
         (memv name (caddr expr))))
 
-
   ;; (define (emit-scc scc env)
   ;;   ; acc is a pair of the env and list of touchups
   ;;   (define (emit-binding acc binding)
   ;;   ))
 
   ;;   (fold-left emit-binding (cons env '()) scc))))
-  
-  (let* ([stack-offsets (map (lambda (name x) ; assoc map of binding name to offset
-                              (cons name (- si (* x wordsize))))
-                            (map car bindings)
-                            (range 0 (length bindings)))]
-        [inner-si (- si (* (length bindings) wordsize))]
+                                       ; assoc map of binding name to size
+  (define stack-sizes
+    (map (lambda (binding) (cons (car binding) (expr-size (cadr binding))))
+        bindings))
+
+                                       ; assoc map of binding name to offset
+  (define stack-offsets
+                                       ; 2  4  2  8  6
+    (let* ([totals                      ; 2  6  8  16 22
+           (reverse (fold-left (lambda (acc x)
+                                 (if (null? acc)
+                                     (list x)
+                                     (cons (+ x (car acc)) acc)))
+                               '()
+                               (map cdr stack-sizes)))]
+                                       ; 0  2  6  8  16
+          [relative-offsets (map - totals (map cdr stack-sizes))]
+          [absolute-offsets (map (lambda (x) (- si x)) b)])
+      (map cons (map car stack-sizes) absolute-offsets)))
+  
+  (let* (
+                                       ; the stack index used when codegening binding body and main body
+                                       ; -> stack ->
+                                       ; [stack-offsets | inner-si]
+        [inner-si (- si (fold-left + 0 (map cdr stack-sizes)))]
 
         [get-offset (lambda (n) (cdr (assoc n stack-offsets)))]
         
                    [scc-env (make-env (env-data-layouts env) scc-binding-offsets)])
               (for-each 
                (lambda (name)
-                 (let ([expr (cadr (assoc name bindings))])
+                 (let* ([expr (cadr (assoc name bindings))]
+                        [size (expr-size expr)])
                    (emit "## generating ~a with scc-env ~a" name scc-env)
                    (if (self-captive-closure? name expr)
                                        ; if self-captive, insert a flag into the environment to let
                                       (cons (cons name 'self-captive)
                                             (env-bindings scc-env))))
                        (codegen-expr expr inner-si scc-env))
-                   (emit "movq %rax, ~a(%rbp)" (get-offset name))))
+
+                   (if (on-stack? expr)
+                       (begin
+                         ; copy over whatevers on the stack
+                         (emit "leaq ~a(%rbp), %rsi" (- inner-si size))
+                         (emit "leaq ~a(%rbp), %rdi" (- (get-offset name) size))
+                         (emit "movq $~a, %rcx" (/ size wordsize))
+                         (emit "rep movsq"))
+                       
+                       (emit "movq %rax, ~a(%rbp)" (get-offset name)))))
                comps)
               scc-env))
           env
                (codegen-expr form inner-si inner-env))
              body)))
 
-(define (codegen-var name si env)
-  (let ([binding (assoc name (env-bindings env))])
-    (if (not binding)
-       (error #f (format "Variable ~a is not bound" name))
-       (emit "movq ~a(%rbp), %rax" (cdr binding)))))
+(define (codegen-var e si env)
+  (let* ([stack-size (on-stack? e)]
+        [name (if (on-stack? e) (caddr e) e)]
+        [stack-offset (cdr (assoc name (env-bindings env)))])
+    (when (not stack-offset)
+      (error #f (format "Variable ~a is not bound" name)))
+
+    (if (on-stack? e)
+       (begin
+         (emit "leaq ~a(%rbp), %rsi" (- stack-offset stack-size))
+         (emit "leaq ~a(%rbp), %rdi" (- si stack-size))
+         (emit "movq $~a, %rcx" (/ stack-size wordsize))
+         (emit "rep movsq"))
+       (emit "movq ~a(%rbp), %rax" stack-offset))))
 
 (define cur-lambda 0)
 (define (fresh-lambda)
           [index (caddr info)]
           [type (car info)]
           [sum (cadr info)])
-      (when (not (stack-expr? res))
-       (error #f "codegened something that wasn't a stack expression"))
-                                       ;TODO handle stack types
+      (when (not (on-stack? (cadr e)))
+       (error #f "trying to destruct something that isn't a stack expression"))
+      (emit "# deconstructing")
       (emit "movq ~a(%rbp), %rax"
            (- si (data-product-offset (env-data-layouts env) type sum index)))))                                     
 
                    [stack-offset (- si (data-product-offset (env-data-layouts env)
                                                             type sum
                                                             i))])
-               (if (stack-expr? res)
+               (if (on-stack? res)
                    (error #f "todo: handle stack-exprs in stack exprs")
                    (emit "movq %rax, ~a(%rbp)" stack-offset))))])
 
        (codegen-constructor tor)
        (codegen-destructor tor))))
 
-(define stack-expr? number?)
-
-                                       ; returns a number if result was stored on stack 
 (define (codegen-expr e si env)
   (emit "# ~a" e)
   (case (ast-type e)
     ('static-string (emit "movq ~a@GOTPCREL(%rip), %rax"
                          (cadr e)))
 
-    ('stack (codegen-expr (caddr e) si env))
+    ('stack (case (ast-type (caddr e))
+             ['var (codegen-var e si env)]
+             [else (codegen-expr (caddr e) si env)]))
 
     (else (error #f "don't know how to codegen this"))))
 
                                        ; takes in a expr annotated with types and returns a type-less AST
                                        ; with stack values wrapped
-(define (annotate-stack-values data-layout ann-e)
+(define (annotate-stack-values data-layouts ann-e)
   (define (stack-type? type)
-    (assoc type data-layout))
+    (assoc type data-layouts))
   (define (strip e)
     (ast-traverse strip (ann-expr e)))
   (let* ([e (ann-expr ann-e)]
         [type (ann-type ann-e)])
     (if (stack-type? type)
-       `(stack ,type ,(ast-traverse strip e))
+       `(stack ,(type-size data-layouts type) ,(ast-traverse strip e))
        (ast-traverse (lambda (x)
-                       (annotate-stack-values data-layout x))
+                       (annotate-stack-values data-layouts x))
                      e))))
 
 (define (free-vars prog)
index ecee99eed962aa94ea39ed8c0f16f4b9c32bc4fa..cdd60bd92730df41c4d15077ddee7ffc61bf7f17 100644 (file)
--- a/tests.scm
+++ b/tests.scm
 (test-prog '((data A [foo Int])
             (let ([x (foo 42)])
               (let ([(foo y) x])
-                (+ 1 y))))
-          43)
+                (+ 2 y))))
+          44)
+
+(test-prog '((data A [foo Bool Int Int])
+            (let ([x (foo (= 2 1) 123 45)]
+                  [(foo a b c) x])
+              (+ b c)))
+          (+ 123 45))
 
 (test-prog '((data A [foo Int])
             (data B [bar A])