+
+ (emit "push %rbp") ; preserve caller's base pointer
+
+ (emit "movq %rsp, %rbp") ; set up our own base pointer
+ (emit "subq $8, %rbp")
+
+ ; load the captured vars onto the stack
+ (for-each
+ (lambda (i)
+ (begin
+ (emit "movq ~a(~a), %rbx" i (param-register 0))
+ (emit "movq %rbx, ~a(%rbp)" (* (- wordsize) i))))
+ (range 0 (length captured)))
+
+ ; load the args onto the stack
+ (for-each
+ (lambda (i)
+ (begin
+ (emit "movq ~a, %rbx" (param-register (+ 1 i)))
+ (emit "movq %rbx, ~a(%rbp)"
+ (* (- wordsize)
+ (+ (length captured) i)))))
+ (range 0 (length args)))
+
+ (codegen-expr body (* (- wordsize) (+ 1 (length params))) env)
+
+ (emit "pop %rbp") ; restore caller's base pointer
+ (emit "ret")))
+
+(define (codegen-string label)
+ (case target
+ ('darwin (emit "movq ~a@GOTPCREL(%rip), %rax" label))
+ ('linux (emit "lea $~a, %rax" label))))
+
+(define cur-label 0)
+(define (fresh-label)
+ (set! cur-label (+ 1 cur-label))
+ (format "label~a" (- cur-label 1)))
+
+(define (codegen-if cond then else si env)
+ (codegen-expr cond si env)
+ (emit "cmpq $0, %rax")
+ (let ((exit-label (fresh-label))
+ (else-label (fresh-label)))
+ (emit "je ~a" else-label)
+ (codegen-expr then si env)
+ (emit "jmp ~a" exit-label)
+ (emit "~a:" else-label)
+ (codegen-expr else si env)
+ (emit "~a:" exit-label)))