(define (codegen-add xs si env)
(define (go ys)
(if (null? ys)
- (emit "movq %rbx, %rax")
+ (emit "movq ~a(%rsp), %rax" si)
(begin
(let ((y (car ys)))
(if (integer? y)
- (emit "addq $~a, %rbx" y)
+ (emit "addq $~a, ~a(%rsp)" y si)
(begin
- (codegen-expr y si env)
- (emit "addq %rax, %rbx"))))
+ (codegen-expr y (- si wordsize) env)
+ (emit "addq %rax, ~a(%rsp)" si))))
(go (cdr ys)))))
(begin
- (emit "movq $0, %rbx")
+ ; use si(%rsp) as the accumulator
+ (emit "movq $0, ~a(%rsp)" si)
(go xs)))
+(define (codegen-binop opcode)
+ (lambda (a b si env)
+ (codegen-expr b si env)
+ (emit "movq %rax, ~a(%rsp)" si)
+ (codegen-expr a (- si wordsize) env)
+ (emit "~a ~a(%rsp), %rax" opcode si)))
+
+(define codegen-sub (codegen-binop "sub"))
+(define codegen-mul (codegen-binop "imul"))
+
+(define (codegen-not x si env)
+ (codegen-expr x si env)
+ (emit "xorq $-1, %rax")
+ (emit "andq $1, %rax"))
+
(define (range s n)
(if (= 0 n) '()
(append (range s (- n 1))
(emit "movq ~a(%rsp), %rax" offset)))
(define (codegen-expr e si env)
- (cond ((and (list? e) (eq? (car e) '+))
- (codegen-add (cdr e) si env))
+ (cond ((app? e)
+ (case (car e)
+ ('+ (codegen-add (cdr e) si env))
+ ('- (codegen-sub (cadr e) (caddr e) si env))
+ ('* (codegen-mul (cadr e) (caddr e) si env))
+ ('! (codegen-not (cadr e) si env))
+ ('bool->int (codegen-expr (cadr e) si env))
+ (else (error #f "can't handle anything else yet"))))
((let? e) (codegen-let
(let-bindings e)
(let-body e)
si
env))
((var? e) (codegen-var e si env))
+ ((boolean? e) (emit "movq $~a, %rax" (if e 1 0)))
(else (emit "movq $~a, %rax" e))))
(define (codegen program)
(map normalize (let-body prog))))
(else prog)))
+(define (builtin-type x)
+ (case x
+ ('+ '(abs int (abs int int)))
+ ('- '(abs int (abs int int)))
+ ('* '(abs int (abs int int)))
+ ('! '(abs bool bool))
+ ('bool->int '(abs bool int))
+ (else #f)))
; we typecheck the lambda calculus only (only single arg lambdas)
(define (typecheck prog)
(cond
((integer? x) (list '() 'int))
((boolean? x) (list '() 'bool))
- ((eq? x 'inc) (list '() '(abs int int)))
- ((eq? x '+) (list '() '(abs int (abs int int))))
+ ((builtin-type x) (list '() (builtin-type x)))
((symbol? x) (list '() (env-lookup env x)))
-
((let? x)
(let ((new-env (fold-left
(lambda (acc bind)