X-Git-Url: http://git.lukelau.me/?p=scheme.git;a=blobdiff_plain;f=compiler.scm;h=d79a37a26f77babdd28040991efa8003ca25ecc1;hp=351e11b7695f927121d574baef27924ed2d31f67;hb=3ce93ef63f164f8dc63c89f1a97f46e200c71d02;hpb=b5fad4a5e1ad7d15dc440089edc9e137bc377be9 diff --git a/compiler.scm b/compiler.scm index 351e11b..d79a37a 100644 --- a/compiler.scm +++ b/compiler.scm @@ -1,11 +1,12 @@ (load "typecheck.scm") +(load "ast.scm") (define (emit . s) (begin (apply printf s) (display "\n"))) -(define (compile-add xs) +(define (codegen-add xs) (define (go ys) (if (null? ys) (emit "movq %rbx, %rax") @@ -16,12 +17,42 @@ (emit "movq $0, %rbx") (go xs))) -(define (compile-expr e) - (if (and (list? e) (eq? (car e) '+)) - (compile-add (cdr e)) - (emit "movq $~a, %rax" e))) +(define (range s n) + (if (= 0 n) '() + (append (range s (- n 1)) + (list (+ s (- n 1)))))) -(define (compile-program program) +(define wordsize 8) + +(define (codegen-let bindings body si env) + (let* ((stack-offsets (map (lambda (x) (- si (* x wordsize))) + (range 0 (length bindings)))) + (inner-si (- si (* (length bindings) wordsize))) + (names (map car bindings)) + (exprs (map cadr bindings)) + (inner-env (append (map cons names stack-offsets) env))) + (for-each (lambda (expr offset) + (codegen-expr expr inner-si env) + (emit "movq %rax, ~a(%rsp)" offset)) + exprs stack-offsets) + (for-each (lambda (form) (codegen-expr form inner-si inner-env)) body))) + +(define (codegen-var name si env) + (let ((offset (cdr (assoc name env)))) + (emit "movq ~a(%rsp), %rax" offset))) + +(define (codegen-expr e si env) + (cond ((and (list? e) (eq? (car e) '+)) + (codegen-add (cdr e))) + ((let? e) (codegen-let + (let-bindings e) + (let-body e) + si + env)) + ((var? e) (codegen-var e si env)) + (else (emit "movq $~a, %rax" e)))) + +(define (codegen program) (emit ".text") (emit ".p2align 4,,15") (emit ".globl _scheme_entry") @@ -37,7 +68,7 @@ '(12 13 14 15)) ; our code goes here - (compile-expr program) + (codegen-expr program 0 '()) ; restore preserved registers (for-each (lambda (i) @@ -55,5 +86,5 @@ (let ([tmp-path "/tmp/a.s"]) (when (file-exists? tmp-path) (delete-file tmp-path)) (with-output-to-file tmp-path - (lambda () (compile-program program))) + (lambda () (codegen program))) (system "clang -fomit-frame-pointer /tmp/a.s rts.c")))