(print-gensym #f) (define inline-primitives (make-parameter #f)) (define signal-error-on-undefined-pcb (make-parameter #t)) (load "record-case.ss") (load "set-operations.ss") (load "tests-driver.ss") ;(load "tests-5.3-req.scm") ;(load "tests-5.2-req.scm") ;(load "tests-5.1-req.scm") ;(load "tests-4.3-req.scm") ;(load "tests-4.2-req.scm") ;(load "tests-4.1-req.scm") ;(load "tests-3.4-req.scm") ;(load "tests-3.3-req.scm") ;(load "tests-3.2-req.scm") ;(load "tests-3.1-req.scm") ;(load "tests-2.9-req.scm") ;(load "tests-2.8-req.scm") ;(load "tests-2.6-req.scm") ;(load "tests-2.4-req.scm") ;(load "tests-2.3-req.scm") ;(load "tests-2.2-req.scm") ;(load "tests-2.1-req.scm") ;(load "tests-1.9-req.scm") ;(load "tests-1.8-req.scm") ;(load "tests-1.7-req.scm") ;(load "tests-1.6-req.scm") ;(load "tests-1.5-req.scm") ;(load "tests-1.4-req.scm") ;(load "tests-1.3-req.scm") ;(load "tests-1.2-req.scm") ;(load "tests-1.1-req.scm") ; (define scheme-library-files '( ["libsymboltable-4.4.ss" "libsymboltable-4.4.s" "libsymboltable"] ["libhandlers-3.3.ss" "libhandlers-3.3.s" "libhandlers" ] ["libcontrol-5.3.ss" "libcontrol-5.3.s" "libcontrol" ] ["libcollect-5.3.ss" "libcollect-5.3.s" "libcollect" ] ["libcore-4.4.ss" "libcore-4.4.s" "libcore" ] ["libio-4.2.ss" "libio-4.2.s" "libio" ] ["libwriter-4.4.ss" "libwriter-4.4.s" "libwriter" ] ["libtokenizer-4.3.ss" "libtokenizer-4.3.s" "libtokenizer" ] ["libeval-5.3.ss" "libeval-5.3.s" "libeval" ] ["libcafe-5.3.ss" "libcafe-5.3.s" "libcafe" ] ["libtrace-5.3.ss" "libtrace-5.3.s" "libtrace" ] ;["psyntax.pp" "psyntax.pp.s" "psyntax" ] )) (define open-coded-primitives ;;; these primitives, when found in operator position with the correct ;;; number of arguments, will be open-coded by the generator. If an ;;; incorrect number of args is detected, or if they appear in non-operator ;;; position, then they cannot be open-coded, and the pcb-primitives table ;;; is consulted for a reference of the pcb slot containing the primitive. ;;; If it's not found there, an error is signalled. ;;; ;;; prim-name args '([$constant-ref 1 value] [$constant-set! 2 effect] [$pcb-ref 1 value] [$pcb-set! 2 effect] ;;; type predicates [fixnum? 1 pred] [boolean? 1 pred] [char? 1 pred] [pair? 1 pred] [symbol? 1 pred] [vector? 1 pred] [string? 1 pred] [procedure? 1 pred] [null? 1 pred] [eof-object? 1 pred] [$unbound-object? 1 pred] [not 1 pred] [eq? 2 pred] ;;; fixnum primitives [$fxadd1 1 value] [$fxsub1 1 value] [$fx+ 2 value] [$fx- 2 value] [$fx* 2 value] [$fxsll 2 value] [$fxsra 2 value] [$fxlogand 2 value] [$fxlogor 2 value] [$fxlogxor 2 value] [$fxlognot 1 value] [$fxquotient 2 value] ;;; fixnum predicates [$fxzero? 1 pred] [$fx= 2 pred] [$fx< 2 pred] [$fx<= 2 pred] [$fx> 2 pred] [$fx>= 2 pred] ;;; character predicates [$char= 2 pred] [$char< 2 pred] [$char<= 2 pred] [$char> 2 pred] [$char>= 2 pred] ;;; character conversion [$fixnum->char 1 value] [$char->fixnum 1 value] ;;; lists/pairs [cons 2 value] [$car 1 value] [$cdr 1 value] [$set-car! 2 effect] [$set-cdr! 2 effect] ;;; vectors [$make-vector 1 value] [vector any value] [$vector-length 1 value] [$vector-ref 2 value] [$vector-set! 3 effect] ;;; strings [$make-string 1 value] [$string any value] [$string-length 1 value] [$string-ref 2 value] [$string-set! 3 effect] ;;; symbols [$make-symbol 1 value] [$symbol-value 1 value] [$symbol-string 1 value] [$set-symbol-value! 2 effect] ;;; misc [eof-object 0 value] [void 0 value] [$exit 1 effect] [$fp-at-base 0 pred] [$current-frame 0 value] [$set-current-frame! 1 effect] [$seal-frame-and-call 1 tail] [$underflow-and-return 1 tail] ;[values any values] )) (define (primitive-context x) (cond [(assq x open-coded-primitives) => caddr] [else (error 'primitive-context "unknown prim ~s" x)])) ;;; pcb table section (define pcb-table '(;;; system locations used by the C/Scheme interface [$system-stack system "system_stack"] [$stack-top system "stack_top"] ; top of stack [$stack-size system "stack_size"] ; its size [$frame-base system "frame_base"] ; base of the frame [$frame-redline system "frame_redline"] ; top + 2 pages [$frame-pointer system "frame_pointer"] ; [$heap-base system "heap_base"] [$heap-size system "heap_size"] [$allocation-redline system "allocation_redline"] [$allocation-pointer system "allocation_pointer"] [$roots system "roots"] [$string-base system "string_base"] [$string-ap system "string_ap"] [$string-eap system "string_eap"] [$string-pages system "string_pages"] [$allocated-megs system "allocated_megs"] [$allocated-bytes system "allocated_bytes"] [$reclaimed-megs system "reclaimed_megs"] [$reclaimed-bytes system "reclaimed_bytes"] ;;; scheme_objects comes before all scheme objects [$scheme-objects system "scheme_objects"] [$next-continuation system "next_continuation"] ;;; error handling procedures used by the codegen [$apply-nonprocedure-error-handler library] [$incorrect-args-error-handler library] [$intern library] [do-overflow library] [do-overflow-with-byte-count library] [do-stack-overflow library] ;;; type predicates [fixnum? public] [boolean? public] [char? public] [null? public] [pair? public] [symbol? public] [vector? public] [string? public] [procedure? public] [eof-object? public] [not public] [eq? public] [equal? public] ;;; fixnum primitives [fxadd1 public] [fxsub1 public] [fx+ public] [fx- public] [fx* public] [fxsll public] [fxsra public] [fxlogor public] [fxlogand public] [fxlogxor public] [fxlognot public] [fxquotient public] [fxremainder public] ;;; fixnum predicates [fxzero? public] [fx= public] [fx< public] [fx<= public] [fx> public] [fx>= public] ;;; characters [char= public] [char< public] [char<= public] [char> public] [char>= public] [fixnum->char public] [char->fixnum public] ;;; lists [cons public] [car public] [cdr public] [caar public] [cadr public] [cdar public] [cddr public] [caddr public] [cadddr public] [cddddr public] [set-car! public] [set-cdr! public] [list public] [list* ADDME] [list? public] [length public] [make-list public] [reverse public] [append public] [list-ref ADDME] [memq public] [assq public] [map public] [for-each public] [andmap public] [ormap ADDME] ;;; vectors [make-vector public] [vector public] [vector-length public] [vector-ref public] [vector-set! public] [list->vector public] [vector->list public] ;;; strings [make-string public] [string public] [string-length public] [string-ref public] [string-set! public] [list->string public] [string->list ADDME] ;;; symbols [gensym public] [symbol->string public] [string->symbol public] [top-level-value public] [top-level-bound? public] [set-top-level-value! public] [oblist public] ;;; eof [eof-object public] [void public] ;;; control/debugging [print-error public] [error public] [current-error-handler public] [exit public] [apply public] [make-parameter public] ;;; output [output-port? public] [console-output-port public] [current-output-port public] [standard-output-port public] [standard-error-port public] [open-output-file public] [close-output-port public] [flush-output-port public] [write-char public] [output-port-name public] [newline public] ;;; input [input-port? public] [standard-input-port public] [console-input-port public] [current-input-port public] [open-input-file public] [close-input-port public] [read-char public] [peek-char public] [unread-char public] [input-port-name public] [write public] [display public] [read-token public] [read public] ;;; evaluation [eval public] [current-eval public] [load public] [new-cafe public] [collect public] [call/cc public] [call/cf library] [dynamic-wind public] [make-traced-procedure library] [trace-symbol! library] [untrace-symbol! library] [$scheme-objects-end system "scheme_objects_end"] )) (define (public-primitives) (let f ([ls pcb-table]) (cond [(null? ls) '()] [(eq? (cadar ls) 'public) (cons (caar ls) (f (cdr ls)))] [else (f (cdr ls))]))) (define (pcb-system-loc? x) (cond [(assq x pcb-table) => (lambda (x) (eq? (cadr x) 'system))] [else (error 'pcb-system-loc? "not in table ~s" x)])) (define *pcb-set-marker* (gensym)) (define *pcb-ref-marker* (gensym)) (define (mark-pcb-set-found x) (putprop x *pcb-set-marker* #t)) (define (mark-pcb-ref-found x) ;;(when (and (signal-error-on-undefined-pcb) ;; (not (getprop x *pcb-set-marker*)) ;; (not (pcb-system-loc? x))) ;; (error 'compile "found reference to unset primitive ~s" x)) (putprop x *pcb-ref-marker* #t)) (define (pcb-referenced? x) (getprop x *pcb-ref-marker*)) (define (pcb-assigned? x) (getprop x *pcb-set-marker*)) (define (pcb-index x) (mark-pcb-ref-found x) (let f ([i 0] [ls pcb-table]) (cond [(null? ls) (error 'pcb-index "not in table ~s" x)] [(eq? x (caar ls)) i] [else (f (add1 i) (cdr ls))]))) (define (pcb-offset x) (* (pcb-index x) wordsize)) (define (primitive? x) (cond [(assq x pcb-table) #t] [(assq x open-coded-primitives) #t] [else #f])) (define (open-codeable? x) (cond [(assq x open-coded-primitives) #t] [(assq x pcb-table) #f] [else (error 'open-codeable "invalid primitive ~s" x)])) (define (open-coded-primitive-args x) (cond [(assq x open-coded-primitives) => cadr] [else (error 'open-coded-primitive-args "invalid ~s" x)])) (define (pcb-cnames) (define (cname x i) (cond [(eq? (cadr x) 'system) (caddr x)] [else (format "prim_~a" i)])) (let f ([ls pcb-table] [i 0]) (cond [(null? ls) '()] [else (cons (cname (car ls) i) (f (cdr ls) (add1 i)))]))) ;;; end of pcb table section (define-record constant (value)) (define-record constant-loc (label)) (define-record code-loc (label)) (define-record foreign-label (label)) (define-record var (name)) (define-record cp-var (idx)) (define-record frame-var (idx)) (define-record new-frame (base-idx size body)) (define-record save-cp (loc)) (define-record eval-cp (check body)) (define-record return (value)) (define-record call-cp (convention base-idx arg-count live-mask)) (define-record primcall (op arg*)) (define-record primref (name)) (define-record conditional (test conseq altern)) (define-record bind (lhs* rhs* body)) (define-record seq (e0 e1)) (define-record function (arg* proper body)) (define-record closure (code free*)) (define-record funcall (op rand*)) (define-record appcall (op rand*)) (define-record forcall (op rand*)) (define-record code (arg* proper free* body)) (define-record codes (lhs* rhs* body)) (define-record constants (name* body)) (define-record assign (lhs rhs)) (define unique-var (let ([counter 0]) (lambda (x) (let ([g (string->symbol (format "~a:~a" x counter))]) (set! counter (add1 counter)) (make-var g))))) (define (make-bind^ lhs* rhs* body) (if (null? lhs*) body (make-bind lhs* rhs* body))) (define (recordize x) (define who 'recordize) (define (self-evaluating? x) (or (number? x) (boolean? x) (null? x) (char? x) (string? x))) (define (verify-proper-bindings b* expr) (unless (list? b*) (error 'parse "invalid bindings in expression ~s" expr)) (for-each (lambda (x) (unless (and (list? x) (= (length x) 2) (symbol? (car x))) (error 'parse "invalid binding ~a in expresison ~a" x expr))) b*)) (define (Internal body* r x) (when (null? body*) (error 'compile "No body in ~s" x)) (let f ([fst (car body*)] [body* (cdr body*)] [bind* '()]) (cond [(and (pair? fst) (eq? (car fst) 'define) (not (assq 'define bind*)) (not (assq 'define r))) (unless (and (list? fst) (= (length fst) 3)) (error 'parse "malformed internal definition ~s in ~s" fst x)) (unless (symbol? (cadr fst)) (error 'parse "invalid name in ~s" fst)) (when (null? body*) (error 'parse "no expression in body of ~s" x)) (f (car body*) (cdr body*) (cons (cdr fst) bind*))] [(and (pair? fst) (eq? (car fst) 'begin) (not (assq 'begin bind*)) (not (assq 'begin r))) (let ([b* (cdr fst)]) (unless (list? b*) (error 'parse "invalid begin ~s" fst)) (let ([body* (append b* body*)]) (when (null? body*) (error 'parse "no expression in body of ~s" x)) (f (car body*) (cdr body*) bind*)))] [else (let ([lhs* (map car bind*)] [rhs* (map cadr bind*)]) (let ([name* (map unique-var lhs*)]) (let ([r (append (map cons lhs* name*) r)]) (let ([rhs* (let f ([rhs* rhs*] [ac '()]) (cond [(null? rhs*) ac] [else (f (cdr rhs*) (cons (Expr (car rhs*) r) ac))]))]) (build-letrec (reverse name*) rhs* (list->seq (Expr* (cons fst body*) r)))))))]))) (define (build-letrec lhs* rhs* body) (if (null? lhs*) body (let ([tmp* (map (lambda (x) (make-var 'tmp)) lhs*)]) (make-bind lhs* (map (lambda (x) (make-primcall 'void '())) lhs*) (make-bind tmp* rhs* (make-seq (list->seq (map make-assign lhs* tmp*)) body)))))) (define (list->seq e*) (let f ([ac (car e*)] [e* (cdr e*)]) (cond [(null? e*) ac] [else (f (make-seq ac (car e*)) (cdr e*))]))) (define (Expr* x* r) (cond [(null? x*) '()] [else (cons (Expr (car x*) r) (Expr* (cdr x*) r))])) (define (Expr x r) (cond [(self-evaluating? x) (make-constant x)] [(symbol? x) (cond [(assq x r) => cdr] [(primitive? x) (make-primref x)] [else (error 'recordize "unbound variable ~s" x)])] [(not (list? x)) (error 'recordize "invalid expression ~s" x)] [(and (symbol? (car x)) (assq (car x) r)) => (lambda (b) (make-funcall (cdr b) (Expr* (cdr x) r)))] [(eq? (car x) 'quote) (unless (= (length x) 2) (error who "invalid syntax ~s" 'quote)) (make-constant (cadr x))] [(and (>= (length x) 2) (eq? (car x) 'begin)) (list->seq (Expr* (cdr x) r))] [(eq? (car x) 'if) (unless (= (length x) 4) (error who "invalid syntax ~s" x)) (make-conditional (Expr (cadr x) r) (Expr (caddr x) r) (Expr (cadddr x) r))] [(and (eq? (car x) 'let) (pair? (cdr x)) (symbol? (cadr x))) ;; named let (unless (>= (length x) 4) (error 'compile "invalid let ~s" x)) (let ([name (cadr x)] [bindings (caddr x)] [body* (cdddr x)]) (verify-proper-bindings bindings x) (let ([lhs* (map car bindings)] [rhs* (map cadr bindings)]) (let ([n-name (make-var name)] [nrhs* (Expr* rhs* r)]) (let ([r (cons (cons name n-name) r)]) (let ([nlhs* (map make-var lhs*)]) (let ([r (append (map cons lhs* nlhs*) r)]) (make-funcall (make-bind (list n-name) (list (make-primcall 'void '())) (make-seq (make-assign n-name (make-function nlhs* #t (Internal body* r x))) n-name)) nrhs*)))))))] [(eq? (car x) 'let) (unless (>= (length x) 3) (error 'compile "invalid let ~s" x)) (let ([bindings (cadr x)] [body* (cddr x)]) (verify-proper-bindings bindings x) (let ([lhs* (map car bindings)] [rhs* (map cadr bindings)]) (let ([nlhs* (map make-var lhs*)] [nrhs* (Expr* rhs* r)]) (let ([r (append (map cons lhs* nlhs*) r)]) (make-bind nlhs* nrhs* (Internal body* r x))))))] [(and (>= (length x) 3) (eq? (car x) 'let*)) (let ([bindings (cadr x)] [body* (cddr x)]) (verify-proper-bindings bindings x) (let ([lhs* (map car bindings)] [rhs* (map cadr bindings)]) (let ([nlhs* (map make-var lhs*)]) (let f ([lhs* lhs*] [nlhs* nlhs*] [rhs* rhs*] [r r]) (cond [(null? lhs*) (Internal body* r x)] [else (make-bind (list (car nlhs*)) (list (Expr (car rhs*) r)) (f (cdr lhs*) (cdr nlhs*) (cdr rhs*) (cons (cons (car lhs*) (car nlhs*)) r)))])))))] [(and (>= (length x) 3) (eq? (car x) 'letrec)) (let ([bindings (cadr x)] [body* (cddr x)]) (verify-proper-bindings bindings x) (cond [(null? bindings) (list->seq (Expr* body* r))] [else (let ([lhs* (map car bindings)] [rhs* (map cadr bindings)]) (let ([nlhs* (map make-var lhs*)] [tmp* (map make-var lhs*)]) (let ([r (append (map cons lhs* nlhs*) r)]) (make-bind nlhs* (map (lambda (x) (make-primcall 'void '())) nlhs*) (make-seq (make-bind tmp* (Expr* rhs* r) (list->seq (map make-assign nlhs* tmp*))) (Internal body* r x))))))]))] [(and (>= (length x) 3) (eq? (car x) 'letrec*)) (let ([bindings (cadr x)] [body* (cddr x)]) (verify-proper-bindings bindings x) (cond [(null? bindings) (list->seq (Expr* body* r))] [else (let ([lhs* (map car bindings)] [rhs* (map cadr bindings)]) (let ([nlhs* (map make-var lhs*)]) (let ([r (append (map cons lhs* nlhs*) r)]) (make-bind nlhs* (map (lambda (x) (make-primcall 'void '())) nlhs*) (make-seq (list->seq (map make-assign nlhs* (Expr* rhs* r))) (Internal body* r x))))))]))] [(and (>= (length x) 3) (eq? (car x) 'lambda)) (let ([arg* (cadr x)] [body* (cddr x)]) (define (new-arg* arg*) (cond [(null? arg*) '()] [(symbol? arg*) (list (make-var arg*))] [else (cons (make-var (car arg*)) (new-arg* (cdr arg*)))])) (define (verify-proper-args args expr) (define (proper-args args) (or (null? args) (symbol? args) (and (pair? args) (symbol? (car args)) (proper-args (cdr args))))) (unless (proper-args args) (error 'parse "invalid arguments in ~s" expr))) (define (extend-args lhs* rhs* r) (cond [(null? lhs*) r] [(symbol? lhs*) (cons (cons lhs* (car rhs*)) r)] [else (extend-args (cdr lhs*) (cdr rhs*) (cons (cons (car lhs*) (car rhs*)) r))])) (verify-proper-args arg* x) (let ([narg* (new-arg* arg*)]) (let ([r (extend-args arg* narg* r)]) (make-function narg* (list? arg*) (Internal body* r x)))))] [(eq? (car x) 'and) (if (null? (cdr x)) (make-constant #t) (let f ([a (cadr x)] [d (cddr x)]) (cond [(null? d) (Expr a r)] [else (make-conditional (Expr a r) (f (car d) (cdr d)) (make-constant #f))])))] [(eq? (car x) 'or) (if (null? (cdr x)) (make-constant #f) (let f ([a (cadr x)] [d (cddr x)]) (cond [(null? d) (Expr a r)] [else (let ([t (make-var 'tmp)]) (make-bind (list t) (list (Expr a r)) (make-conditional t t (f (car d) (cdr d)))))])))] [(and (>= (length x) 3) (eq? (car x) 'when)) (let ([test (cadr x)] [body* (cddr x)]) (make-conditional (Expr test r) (list->seq (Expr* body* r)) (make-primcall 'void '())))] [(and (>= (length x) 3) (eq? (car x) 'unless)) (let ([test (cadr x)] [body* (cddr x)]) (make-conditional (Expr test r) (make-primcall 'void '()) (list->seq (Expr* body* r))))] [(and (>= (length x) 2) (eq? (car x) 'cond)) (let f ([cls (cadr x)] [cls* (cddr x)]) (cond [(not (list? cls)) (error who "malformed cond clause ~s in ~s" cls x)] [(not (pair? cls)) (error who "malformed cond clause ~s in ~s" cls x)] [(null? cls*) (cond [(and (eq? (car cls) 'else) (not (assq 'else r))) (unless (>= (length cls) 2) (error who "malformed cond else clause ~s in ~s" cls x)) (list->seq (Expr* (cdr cls) r))] [(and (>= (length cls) 2) (eq? (cadr cls) '=>) (not (assq '=> r))) (unless (= (length cls) 3) (error who "malformed cond last => clause ~s in ~s" cls x)) (let ([t (make-var 'tmp)]) (make-bind (list t) (list (Expr (car cls) r)) (make-conditional t (make-funcall (Expr (caddr cls) r) (list t)) (make-primcall 'void '()))))] [(= (length cls) 1) (let ([t (make-var 'tmp)]) (make-bind (list t) (list (Expr (car cls) r)) (make-conditional t t (make-primcall 'void '()))))] [else (make-conditional (Expr (car cls) r) (list->seq (Expr* (cdr cls) r)) (make-primcall 'void '()))])] [else (cond [(and (>= (length cls) 2) (eq? (cadr cls) '=>) (not (assq '=> r))) (unless (= (length cls) 3) (error who "malformed cond => clause ~s in ~s" cls x)) (let ([t (make-var 'tmp)]) (make-bind (list t) (list (Expr (car cls) r)) (make-conditional t (make-funcall (Expr (caddr cls) r) (list t)) (f (car cls*) (cdr cls*)))))] [(= (length cls) 1) (let ([t (make-var 'tmp)]) (make-bind (list t) (list (Expr (car cls) r)) (make-conditional t t (f (car cls*) (cdr cls*)))))] [else (make-conditional (Expr (car cls) r) (list->seq (Expr* (cdr cls) r)) (f (car cls*) (cdr cls*)))])]))] [(and (= (length x) 3) (eq? (car x) 'set!)) (let ([var (cadr x)] [val (caddr x)]) (unless (symbol? var) (error who "invalid syntax in ~s" x)) (cond [(assq var r) => (lambda (p) (make-assign (cdr p) (Expr val r)))] [else (error who "unbound variable ~s in ~s" var x)]))] [(and (eq? (car x) '$apply)) (unless (>= (length (cdr x)) 2) (error who "insufficient arguments to $apply in ~s" x)) (let ([rator (cadr x)] [rand* (cddr x)]) (make-appcall (Expr rator r) (Expr* rand* r)))] [(eq? (car x) 'foreign-call) (unless (and (>= (length x) 2) (string? (cadr x))) (error who "invalid syntax ~s" x)) (make-forcall (cadr x) (Expr* (cddr x) r))] [(eq? (car x) '$pcb-set!) (unless (= (length x) 3) (error who "incorrect number of args in ~s" x)) (mark-pcb-set-found (cadr x)) (make-primcall '$pcb-set! (list (make-constant (pcb-index (cadr x))) (Expr (caddr x) r)))] [else (make-funcall (Expr (car x) r) (Expr* (cdr x) r))])) (Expr x '())) (define (unparse x) (define (E-args proper x) (if proper (map E x) (let f ([a (car x)] [d (cdr x)]) (cond [(null? d) (E a)] [else (cons (E a) (f (car d) (cdr d)))])))) (define (E x) (record-case x [(constant c) `(quote ,c)] [(constant-loc x) `(constant-loc ,x)] [(var x) (string->symbol (format "v:~a" x))] [(primref x) x] [(conditional test conseq altern) `(if ,(E test) ,(E conseq) ,(E altern))] [(primcall op arg*) `(,op . ,(map E arg*))] [(bind lhs* rhs* body) `(let ,(map (lambda (lhs rhs) (list (E lhs) (E rhs))) lhs* rhs*) ,(E body))] [(seq e0 e1) `(begin ,(E e0) ,(E e1))] [(function args proper body) `(lambda ,(E-args proper args) ,(E body))] [(closure code free*) `(closure ,(E code) ,(map E free*))] [(code arg* proper free* body) `(code [arg: ,(E-args proper arg*)] [free: ,(map E free*)] ,(E body))] [(codes lhs* rhs* body) `(codes ,(map (lambda (lhs rhs) (list (E lhs) (E rhs))) lhs* rhs*) ,(E body))] [(funcall rator rand*) `(funcall ,(E rator) . ,(map E rand*))] [(appcall rator rand*) `(appcall ,(E rator) . ,(map E rand*))] [(forcall rator rand*) `(foreign-call ,rator . ,(map E rand*))] [(assign lhs rhs) `(set! ,(E lhs) ,(E rhs))] [(constants lhs* body) `(constants ,(map E lhs*) ,(E body))] [else (error 'unparse "invalid record ~s" x)])) (E x)) (define (optimize-direct-calls x) (define who 'optimize-direct-calls) (define (make-conses ls) (cond [(null? ls) (make-constant '())] [else (make-primcall 'cons (list (car ls) (make-conses (cdr ls))))])) (define (properize lhs* rhs*) (cond [(null? lhs*) (error who "improper improper")] [(null? (cdr lhs*)) (list (make-conses rhs*))] [else (cons (car rhs*) (properize (cdr lhs*) (cdr rhs*)))])) (define (inline rator rand*) (record-case rator [(function fml* proper body) (cond [proper (if (= (length fml*) (length rand*)) (make-bind fml* rand* body) (begin (warning 'compile "possible application error in ~s" (unparse (make-funcall rator rand*))) (make-funcall rator rand*)))] [else (if (<= (length fml*) (length rand*)) (make-bind fml* (properize fml* rand*) body) (begin (warning 'compile "possible application error in ~s" (unparse (make-funcall rator rand*))) (make-funcall rator rand*)))])] [else (make-funcall rator rand*)])) (define (Expr x) (record-case x [(constant) x] [(var) x] [(primref) x] [(bind lhs* rhs* body) (make-bind lhs* (map Expr rhs*) (Expr body))] [(conditional test conseq altern) (make-conditional (Expr test) (Expr conseq) (Expr altern))] [(seq e0 e1) (make-seq (Expr e0) (Expr e1))] [(function fml* proper body) (make-function fml* proper (Expr body))] [(primcall rator rand*) (make-primcall rator (map Expr rand*))] [(funcall rator rand*) (inline (Expr rator) (map Expr rand*))] [(appcall rator rand*) (make-appcall (Expr rator) (map Expr rand*))] [(forcall rator rand*) (make-forcall rator (map Expr rand*))] [(assign lhs rhs) (make-assign lhs (Expr rhs))] [else (error who "invalid expression ~s" (unparse x))])) (Expr x)) (define (uncover-assigned x) (define who 'uncover-assigned) (define (Expr* x*) (cond [(null? x*) '()] [else (union (Expr (car x*)) (Expr* (cdr x*)))])) (define (Expr x) (record-case x [(constant) '()] [(var) '()] [(primref) '()] [(bind lhs* rhs* body) (union (Expr body) (Expr* rhs*))] [(conditional test conseq altern) (union (Expr test) (union (Expr conseq) (Expr altern)))] [(seq e0 e1) (union (Expr e0) (Expr e1))] [(function fml* proper body) (Expr body)] [(primcall rator rand*) (Expr* rand*)] [(funcall rator rand*) (union (Expr rator) (Expr* rand*))] [(appcall rator rand*) (union (Expr rator) (Expr* rand*))] [(forcall rator rand*) (Expr* rand*)] [(assign lhs rhs) (union (singleton lhs) (Expr rhs))] [else (error who "invalid expression ~s" (unparse x))])) (Expr x)) (define (rewrite-assignments assigned x) (define who 'rewrite-assignments) (define (fix lhs*) (cond [(null? lhs*) (values '() '() '())] [else (let ([x (car lhs*)]) (let-values ([(lhs* a-lhs* a-rhs*) (fix (cdr lhs*))]) (cond [(memq x assigned) (let ([t (make-var 'assignment-tmp)]) (values (cons t lhs*) (cons x a-lhs*) (cons t a-rhs*)))] [else (values (cons x lhs*) a-lhs* a-rhs*)])))])) (define (bind-assigned lhs* rhs* body) (cond [(null? lhs*) body] [else (make-bind lhs* (map (lambda (rhs) (make-primcall 'vector (list rhs))) rhs*) body)])) (define (Expr x) (record-case x [(constant) x] [(var) (cond [(memq x assigned) (make-primcall '$vector-ref (list x (make-constant 0)))] [else x])] [(primref) x] [(bind lhs* rhs* body) (let-values ([(lhs* a-lhs* a-rhs*) (fix lhs*)]) (make-bind lhs* (map Expr rhs*) (bind-assigned a-lhs* a-rhs* (Expr body))))] [(conditional test conseq altern) (make-conditional (Expr test) (Expr conseq) (Expr altern))] [(seq e0 e1) (make-seq (Expr e0) (Expr e1))] [(function fml* proper body) (let-values ([(fml* a-lhs* a-rhs*) (fix fml*)]) (make-function fml* proper (bind-assigned a-lhs* a-rhs* (Expr body))))] [(primcall op rand*) (make-primcall op (map Expr rand*))] [(forcall op rand*) (make-forcall op (map Expr rand*))] [(funcall rator rand*) (make-funcall (Expr rator) (map Expr rand*))] [(appcall rator rand*) (make-appcall (Expr rator) (map Expr rand*))] [(assign lhs rhs) (unless (memq lhs assigned) (error 'rewrite-assignments "not assigned ~s in ~s" lhs x)) (make-primcall '$vector-set! (list lhs (make-constant 0) (Expr rhs)))] [else (error who "invalid expression ~s" (unparse x))])) (Expr x)) (define (remove-assignments x) (let ([assigned (uncover-assigned x)]) (rewrite-assignments assigned x))) (define (convert-closures prog) (define who 'convert-closures) (define (Expr* x*) (cond [(null? x*) (values '() '())] [else (let-values ([(a a-free) (Expr (car x*))] [(d d-free) (Expr* (cdr x*))]) (values (cons a d) (union a-free d-free)))])) (define (Expr ex) (record-case ex [(constant) (values ex '())] [(var) (values ex (singleton ex))] [(primref) (values ex '())] [(bind lhs* rhs* body) (let-values ([(rhs* rhs-free) (Expr* rhs*)] [(body body-free) (Expr body)]) (values (make-bind lhs* rhs* body) (union rhs-free (difference body-free lhs*))))] [(conditional test conseq altern) (let-values ([(test test-free) (Expr test)] [(conseq conseq-free) (Expr conseq)] [(altern altern-free) (Expr altern)]) (values (make-conditional test conseq altern) (union test-free (union conseq-free altern-free))))] [(seq e0 e1) (let-values ([(e0 e0-free) (Expr e0)] [(e1 e1-free) (Expr e1)]) (values (make-seq e0 e1) (union e0-free e1-free)))] [(function fml* proper body) (let-values ([(body body-free) (Expr body)]) (let ([free (difference body-free fml*)]) (values (make-closure (make-code fml* proper free body) free) free)))] [(primcall op rand*) (let-values ([(rand* rand*-free) (Expr* rand*)]) (values (make-primcall op rand*) rand*-free))] [(forcall op rand*) (let-values ([(rand* rand*-free) (Expr* rand*)]) (values (make-forcall op rand*) rand*-free))] [(funcall rator rand*) (let-values ([(rator rat-free) (Expr rator)] [(rand* rand*-free) (Expr* rand*)]) (values (make-funcall rator rand*) (union rat-free rand*-free)))] [(appcall rator rand*) (let-values ([(rator rat-free) (Expr rator)] [(rand* rand*-free) (Expr* rand*)]) (values (make-appcall rator rand*) (union rat-free rand*-free)))] [else (error who "invalid expression ~s" (unparse ex))])) (let-values ([(prog free) (Expr prog)]) (unless (null? free) (error 'convert-closures "free vars ~s encountered in ~a" free prog)) prog)) (define (lift-codes x) (define who 'lift-codes) (define (Expr* x*) (cond [(null? x*) (values '() '())] [else (let-values ([(a a-free) (Expr (car x*))] [(d d-free) (Expr* (cdr x*))]) (values (cons a d) (append a-free d-free)))])) (define (Expr x) (record-case x [(constant) (values x '())] [(var) (values x '())] [(primref) (values x '())] [(bind lhs* rhs* body) (let-values ([(rhs* rhs-codes) (Expr* rhs*)] [(body body-codes) (Expr body)]) (values (make-bind lhs* rhs* body) (append rhs-codes body-codes)))] [(conditional test conseq altern) (let-values ([(test test-codes) (Expr test)] [(conseq conseq-codes) (Expr conseq)] [(altern altern-codes) (Expr altern)]) (values (make-conditional test conseq altern) (append test-codes conseq-codes altern-codes)))] [(seq e0 e1) (let-values ([(e0 e0-codes) (Expr e0)] [(e1 e1-codes) (Expr e1)]) (values (make-seq e0 e1) (append e0-codes e1-codes)))] [(closure c free) (let-values ([(c codes) (record-case c [(code arg* proper free* body) (let-values ([(body body-codes) (Expr body)]) (let ([g (make-code-loc 'code)]) (values g (cons (cons g (make-code arg* proper free* body)) body-codes))))] [else (error #f "invalid code ~s" c)])]) (values (make-closure c free) codes))] [(primcall op rand*) (let-values ([(rand* rand*-codes) (Expr* rand*)]) (values (make-primcall op rand*) rand*-codes))] [(forcall op rand*) (let-values ([(rand* rand*-codes) (Expr* rand*)]) (values (make-forcall op rand*) rand*-codes))] [(funcall rator rand*) (let-values ([(rator rat-codes) (Expr rator)] [(rand* rand*-codes) (Expr* rand*)]) (values (make-funcall rator rand*) (append rat-codes rand*-codes)))] [(appcall rator rand*) (let-values ([(rator rat-codes) (Expr rator)] [(rand* rand*-codes) (Expr* rand*)]) (values (make-appcall rator rand*) (append rat-codes rand*-codes)))] [else (error who "invalid expression ~s" (unparse x))])) (let-values ([(x codes) (Expr x)]) (make-codes (map car codes) (map cdr codes) x))) (define (lift-complex-constants x) (define who 'lift-complex-constants) (define complex-lhs* '()) (define complex-rhs* '()) (define symbols-lhs* '()) (define symbols-rhs* '()) (define *symbol-key* (gensym)) (define (symbol-convert x) (make-funcall (make-primcall '$pcb-ref (list (make-constant (pcb-index '$intern)))) (list (convert (symbol->string x))))) (define (convert x) (cond [(pair? x) (make-primcall 'cons (list (convert (car x)) (convert (cdr x))))] [(vector? x) (make-primcall 'vector (map convert (vector->list x)))] [(string? x) (make-primcall '$string (map make-constant (string->list x)))] [(symbol? x) (intern x)] [else (make-constant x)])) (define (intern x) (cond [(and (symbol? x) (getprop x *symbol-key*))] [(symbol? x) (let ([t (make-constant-loc 'constant)] [v (symbol-convert x)]) (set! symbols-lhs* (cons t symbols-lhs*)) (set! symbols-rhs* (cons v symbols-rhs*)) (putprop x *symbol-key* t) t)] [else (let ([t (make-constant-loc 'constant)] [v (convert x)]) (set! complex-lhs* (cons t complex-lhs*)) (set! complex-rhs* (cons v complex-rhs*)) t)])) (define (assign-complex* lhs* rhs* body) (cond [(null? lhs*) body] [else (assign-complex* (cdr lhs*) (cdr rhs*) (make-seq (make-primcall '$set-constant! (list (car lhs*) (car rhs*))) body))])) (define (Expr x) (record-case x [(constant c) (cond [(or (pair? c) (string? c) (vector? c) (symbol? c)) (intern c)] [(or (boolean? c) (integer? c) (char? c) (null? c)) x] [else (error who "what constant ~s" c)])] [(var) x] [(primref) x] [(bind lhs* rhs* body) (make-bind lhs* (map Expr rhs*) (Expr body))] [(conditional test conseq altern) (make-conditional (Expr test) (Expr conseq) (Expr altern))] [(seq e0 e1) (make-seq (Expr e0) (Expr e1))] [(closure c free) x] [(primcall op rand*) (make-primcall op (map Expr rand*))] [(forcall op rand*) (make-forcall op (map Expr rand*))] [(funcall rator rand*) (make-funcall (Expr rator) (map Expr rand*))] [(appcall rator rand*) (make-appcall (Expr rator) (map Expr rand*))] [else (error who "invalid expression ~s" (unparse x))])) (define (CodeExpr x) (record-case x [(code fml* proper free* body) (make-code fml* proper free* (Expr body))])) (record-case x [(codes lhs* rhs* body) (let ([rhs* (map CodeExpr rhs*)] [body (Expr body)]) (let ([init-lhs (make-code-loc 'init)] [init-rhs (make-code '() #t '() (assign-complex* symbols-lhs* symbols-rhs* (assign-complex* complex-lhs* complex-rhs* (make-constant #t))))]) (make-constants (append complex-lhs* symbols-lhs*) (make-codes (cons init-lhs lhs*) (cons init-rhs rhs*) (make-seq (make-funcall (make-closure init-lhs '()) '()) body)))))])) (define (syntactically-valid? op rand*) (define (valid-arg-count? op rand*) (let ([n (open-coded-primitive-args op)] [m (length rand*)]) (cond [(eq? n 'any) #t] [(eq? n 'no-code) (error 'syntactically-valid "should not primcall non codable prim ~s" op)] [(fixnum? n) (cond [(= n m) #t] [else (warning 'compile "Possible incorrect number of args in ~s" (cons op (map unparse rand*))) #f])] [else (error 'do-primcall "BUG: what ~s" n)]))) (define (check op pred?) (lambda (arg) (record-case arg [(constant c) (cond [(pred? c) #t] [else (warning 'compile "Possible argument error to primitive ~s" op) #f])] [(primref) (cond [(pred? (lambda (x) x)) #t] [else (warning 'compile "Possible argument error to primitive ~s" op) #f])] [else #t]))) (define (nonnegative-fixnum? n) (and (fixnum? n) (>= n 0))) (define (byte? n) (and (fixnum? n) (<= 0 n 127))) (define (valid-arg-types? op rand*) (case op [(fixnum? boolean? char? vector? string? procedure? null? pair? not cons eq? vector symbol? error eof-object eof-object? void $unbound-object?) '#t] [($fxadd1 $fxsub1 $fxzero? $fxlognot $fxlogor $fxlogand $fx+ $fx- $fx* $fx= $fx< $fx<= $fx> $fx>= $fxquotient $fxsll $fxsra $fxlogxor $exit) (andmap (check op fixnum?) rand*)] [($fixnum->char) (andmap (check op byte?) rand*)] [($char->fixnum $char= $char< $char<= $char> $char>= $string) (andmap (check op char?) rand*)] [($make-vector $make-string) (andmap (check op nonnegative-fixnum?) rand*)] [($car $cdr) (andmap (check op pair?) rand*)] [($vector-length) (andmap (check op vector?) rand*)] [($string-length) (andmap (check op string?) rand*)] [($set-car! $set-cdr!) ((check op pair?) (car rand*))] [($vector-ref $vector-set!) (and ((check op vector?) (car rand*)) ((check op nonnegative-fixnum?) (cadr rand*)))] [($string-ref $string-set! $string-ref-16+0 $string-ref-16+1 $string-ref-8+0 $string-ref-8+2) (and ((check op string?) (car rand*)) ((check op nonnegative-fixnum?) (cadr rand*)))] [($symbol-string) (andmap (check op symbol?) rand*)] [($constant-ref $set-constant! $intern $pcb-set! $pcb-ref $make-symbol $symbol-value $set-symbol-value! $set-current-frame! $seal-frame-and-call $underflow-and-return) #t] [else (error 'valid-arg-types? "unhandled op ~s" op)])) (and (valid-arg-count? op rand*) (or (null? rand*) (valid-arg-types? op rand*)))) ;;; the output of simplify-operands differs from the input in that the ;;; operands to primcalls are all simple (variables, primrefs, or constants). ;;; funcalls to open-codable primrefs whos arguments are "ok" are converted to ;;; primcalls. (define (introduce-primcalls x) (define who 'introduce-primcalls) (define (simple? x) (or (constant-loc? x) (constant? x) (var? x) (primref? x))) (define (Expr x) (record-case x [(constant) x] [(constant-loc) x] [(var) x] [(primref) x] [(closure) x] [(bind lhs* rhs* body) (make-bind lhs* (map Expr rhs*) (Expr body))] [(conditional test conseq altern) (make-conditional (Expr test) (Expr conseq) (Expr altern))] [(seq e0 e1) (make-seq (Expr e0) (Expr e1))] [(primcall op arg*) (case op ;[(values) ; (if (= (length arg*) 1) ; (Expr (car arg*)) ; (begin ; (warning 'compile "possible incorrect number of values") ; (make-funcall (make-primref 'values) (map Expr arg*))))] [else (make-primcall op (map Expr arg*))])] [(forcall op arg*) (make-forcall op (map Expr arg*))] [(funcall rator rand*) (cond [(and (primref? rator) (inline-primitives) (open-codeable? (primref-name rator)) (syntactically-valid? (primref-name rator) rand*)) (Expr (make-primcall (primref-name rator) rand*))] [else (make-funcall (Expr rator) (map Expr rand*))])] [(appcall op arg*) (make-appcall (Expr op) (map Expr arg*))] [else (error who "invalid expression ~s" (unparse x))])) (define (Tail x) (record-case x [(constant) (make-return x)] [(constant-loc) (make-return x)] [(var) (make-return x)] [(primref) (make-return x)] [(closure) (make-return x)] [(bind lhs* rhs* body) (make-bind lhs* (map Expr rhs*) (Tail body))] [(conditional test conseq altern) (make-conditional (Expr test) (Tail conseq) (Tail altern))] [(seq e0 e1) (make-seq (Expr e0) (Tail e1))] [(primcall op arg*) (case op ;[(values) ; (if (= (length arg*) 1) ; (make-return (Expr (car arg*))) ; (make-return* (map Expr arg*)))] [else (make-return (make-primcall op (map Expr arg*)))])] [(forcall op arg*) (make-return (make-forcall op (map Expr arg*)))] [(funcall rator rand*) (cond [(and (primref? rator) (inline-primitives) (open-codeable? (primref-name rator)) (syntactically-valid? (primref-name rator) rand*)) (Tail (make-primcall (primref-name rator) rand*))] [else (make-funcall (Expr rator) (map Expr rand*))])] [(appcall op arg*) (make-appcall (Expr op) (map Expr arg*))] [else (error who "invalid expression ~s" (unparse x))])) (define (CodeExpr x) (record-case x [(code fml* proper free* body) (make-code fml* proper free* (Tail body))])) (define (CodesExpr x) (record-case x [(codes lhs* rhs* body) (make-codes lhs* (map CodeExpr rhs*) (Tail body))])) (define (ConstantsExpr x) (record-case x [(constants lhs* body) (make-constants lhs* (CodesExpr body))])) (ConstantsExpr x)) (define (simplify-operands x) (define who 'simplify-operands) (define (simple? x) (or (constant-loc? x) (constant? x) (var? x) (primref? x))) (define (simplify arg lhs* rhs* k) (if (simple? arg) (k arg lhs* rhs*) (let ([v (unique-var 'tmp)]) (k v (cons v lhs*) (cons (Expr arg) rhs*))))) (define (simplify* arg* lhs* rhs* k) (cond [(null? arg*) (k '() lhs* rhs*)] [else (simplify (car arg*) lhs* rhs* (lambda (a lhs* rhs*) (simplify* (cdr arg*) lhs* rhs* (lambda (d lhs* rhs*) (k (cons a d) lhs* rhs*)))))])) (define (Expr x) (record-case x [(constant) x] [(constant-loc) x] [(var) x] [(primref) x] [(closure) x] [(bind lhs* rhs* body) (make-bind lhs* (map Expr rhs*) (Expr body))] [(conditional test conseq altern) (make-conditional (Expr test) (Expr conseq) (Expr altern))] [(seq e0 e1) (make-seq (Expr e0) (Expr e1))] [(primcall op arg*) (simplify* arg* '() '() (lambda (arg* lhs* rhs*) (make-bind^ lhs* rhs* (make-primcall op arg*))))] [(forcall op arg*) (make-forcall op (map Expr arg*))] [(funcall rator rand*) (make-funcall (Expr rator) (map Expr rand*))] [(appcall op arg*) (make-appcall (Expr op) (map Expr arg*))] [else (error who "invalid expression ~s" (unparse x))])) (define (Tail x) (record-case x [(return v) (make-return (Expr v))] [(bind lhs* rhs* body) (make-bind lhs* (map Expr rhs*) (Tail body))] [(conditional test conseq altern) (make-conditional (Expr test) (Tail conseq) (Tail altern))] [(seq e0 e1) (make-seq (Expr e0) (Tail e1))] [(funcall rator rand*) (make-funcall (Expr rator) (map Expr rand*))] [(appcall op arg*) (make-appcall (Expr op) (map Expr arg*))] [else (error who "invalid expression ~s" (unparse x))])) (define (CodeExpr x) (record-case x [(code fml* proper free* body) (make-code fml* proper free* (Tail body))])) (define (CodesExpr x) (record-case x [(codes lhs* rhs* body) (make-codes lhs* (map CodeExpr rhs*) (Tail body))])) (define (ConstantsExpr x) (record-case x [(constants lhs* body) (make-constants lhs* (CodesExpr body))])) (ConstantsExpr x)) (define (insert-stack-overflow-checks x) (define who 'insert-stack-overflow-checks) (define (insert-check body) (make-seq (make-conditional (make-primcall '$fp-overflow '()) (make-funcall (make-primref 'do-stack-overflow) '()) (make-primcall 'void '())) body)) (define (Expr x) (record-case x [(constant) #f] [(constant-loc) #f] [(var) #f] [(primref) #f] [(closure code free*) #f] [(bind lhs* rhs* body) (or (ormap Expr rhs*) (Expr body))] [(conditional test conseq altern) (or (Expr test) (Expr conseq) (Expr altern))] [(seq e0 e1) (or (Expr e0) (Expr e1))] [(primcall op arg*) (ormap Expr arg*)] [(forcall op arg*) (ormap Expr arg*)] [(funcall rator arg*) #t] [(appcall rator arg*) #t] [else (error who "invalid expression ~s" (unparse x))])) (define (Tail x) (record-case x [(return v) (Expr v)] [(bind lhs* rhs* body) (or (ormap Expr rhs*) (Tail body))] [(conditional test conseq altern) (or (Expr test) (Tail conseq) (Tail altern))] [(seq e0 e1) (or (Expr e0) (Tail e1))] [(funcall rator arg*) (or (Expr rator) (ormap Expr arg*))] [(appcall rator arg*) (or (Expr rator) (ormap Expr arg*))] [else (error who "invalid tail expression ~s" (unparse x))])) (define (CodeExpr x) (record-case x [(code fml* proper free* body) (if (Tail body) (make-code fml* proper free* (insert-check body)) x)])) (define (CodesExpr x) (record-case x [(codes lhs* rhs* body) (make-codes lhs* (map CodeExpr rhs*) (insert-check body))])) (define (ConstantsExpr x) (record-case x [(constants lhs* body) (make-constants lhs* (CodesExpr body))])) (ConstantsExpr x)) (define (insert-allocation-checks x) (define who 'insert-allocation-checks) (define (check-bytes n var body) (make-seq (make-conditional (make-primcall '$ap-check-bytes (list (make-constant n) var)) (make-funcall (make-primref 'do-overflow) '()) (make-primcall 'void '())) body)) (define (check-words n var body) (make-seq (make-conditional (make-primcall '$ap-check-words (list (make-constant n) var)) (make-funcall (make-primref 'do-overflow) '()) (make-primcall 'void '())) body)) (define (check-const n body) (make-seq (make-conditional (make-primcall '$ap-check-const (list (make-constant n))) (make-funcall (make-primref 'do-overflow) '()) (make-primcall 'void '())) body)) (define (Expr x) (record-case x [(constant) x] [(constant-loc) x] [(var) x] [(primref) x] [(closure code free*) (check-const (+ disp-closure-data (* (length free*) wordsize)) x)] [(bind lhs* rhs* body) (make-bind lhs* (map Expr rhs*) (Expr body))] [(conditional test conseq altern) (make-conditional (Expr test) (Expr conseq) (Expr altern))] [(seq e0 e1) (make-seq (Expr e0) (Expr e1))] [(primcall op arg*) (case op [(cons) (check-const pair-size x)] [($make-symbol) (check-const symbol-size x)] [($make-string) (record-case (car arg*) [(constant i) (check-const (+ i disp-string-data 1) x)] [else (check-bytes (add1 disp-string-data) (car arg*) x)])] [($string) (check-const (+ (length arg*) disp-string-data 1) x)] [($make-vector) (record-case (car arg*) [(constant i) (check-const (+ (* i wordsize) disp-vector-data) x)] [else (check-words (add1 disp-vector-data) (car arg*) x)])] [(vector) (check-const (+ (* (length arg*) wordsize) disp-vector-data) x)] [else x])] [(forcall op arg*) (make-forcall op (map Expr arg*))] [(funcall rator rand*) (make-funcall (Expr rator) (map Expr rand*))] [(appcall op arg*) (make-appcall (Expr op) (map Expr arg*))] [else (error who "invalid expression ~s" (unparse x))])) (define (Tail x) (record-case x [(return v) (make-return (Expr v))] [(bind lhs* rhs* body) (make-bind lhs* (map Expr rhs*) (Tail body))] [(conditional test conseq altern) (make-conditional (Expr test) (Tail conseq) (Tail altern))] [(seq e0 e1) (make-seq (Expr e0) (Tail e1))] [(funcall rator rand*) (make-funcall (Expr rator) (map Expr rand*))] [(appcall op arg*) (make-appcall (Expr op) (map Expr arg*))] [else (error who "invalid expression ~s" (unparse x))])) (define (CodeExpr x) (record-case x [(code fml* proper free* body) (make-code fml* proper free* (Tail body))])) (define (CodesExpr x) (record-case x [(codes lhs* rhs* body) (make-codes lhs* (map CodeExpr rhs*) (Tail body))])) (define (ConstantsExpr x) (record-case x [(constants lhs* body) (make-constants lhs* (CodesExpr body))])) (ConstantsExpr x)) (define (remove-local-variables x) (define who 'remove-local-variables) (define (simple* x* r) (map (lambda (x) (cond [(assq x r) => cdr] [else (when (var? x) (error who "unbound var ~s" x)) x])) x*)) (define (env->mask r sz) (let ([s (make-vector (fxsra (+ sz 7) 3) 0)]) (for-each (lambda (idx) (let ([q (fxsra idx 3)] [r (fxlogand idx 7)]) (vector-set! s q (fxlogor (vector-ref s q) (fxsll 1 r))))) r) s)) (define (do-new-frame op rand* si r convention orig-live) (make-new-frame (add1 si) (+ (length rand*) 2) (let f ([r* rand*] [nsi (+ si 2)] [live orig-live]) (cond [(null? r*) (make-seq (make-seq (make-save-cp (make-frame-var si)) (case convention [(apply normal) (make-eval-cp #t (Expr op nsi r (cons si live)))] [(foreign) (make-eval-cp #f (make-foreign-label op))] [else (error who "invalid convention ~s" convention)])) (make-call-cp convention (add1 si) (length rand*) (env->mask (cons si orig-live) (add1 si))))] [else (make-seq (make-assign (make-frame-var nsi) (Expr (car r*) nsi r live)) (f (cdr r*) (add1 nsi) (cons nsi live)))])))) (define (Tail x si r live) (record-case x [(return v) (make-return (Expr v si r live))] [(bind lhs* rhs* body) (let f ([lhs* lhs*] [rhs* rhs*] [si si] [nr r] [live live]) (cond [(null? lhs*) (Tail body si nr live)] [else (let ([v (make-frame-var si)]) (make-seq (make-assign v (Expr (car rhs*) si r live)) (f (cdr lhs*) (cdr rhs*) (add1 si) (cons (cons (car lhs*) v) nr) (cons si live))))]))] [(conditional test conseq altern) (make-conditional (Expr test si r live) (Tail conseq si r live) (Tail altern si r live))] [(seq e0 e1) (make-seq (Expr e0 si r live) (Tail e1 si r live))] [(primcall op arg*) (case op ; [(values) (make-primcall op (simple* arg* r))] [else (make-return (make-primcall op (simple* arg* r)))])] [(funcall op rand*) (do-new-frame op rand* si r 'normal live)] [(appcall op rand*) (do-new-frame op rand* si r 'apply live)] [else (error who "invalid expression ~s" (unparse x))])) (define (Expr x si r live) (record-case x [(constant) x] [(constant-loc) x] [(var) (cond [(assq x r) => cdr] [else (error who "unbound var ~s" x)])] [(primref) x] [(closure code free*) (make-closure code (simple* free* r))] [(bind lhs* rhs* body) (let f ([lhs* lhs*] [rhs* rhs*] [si si] [nr r] [live live]) (cond [(null? lhs*) (Expr body si nr live)] [else (let ([v (make-frame-var si)]) (make-seq (make-assign v (Expr (car rhs*) si r live)) (f (cdr lhs*) (cdr rhs*) (add1 si) (cons (cons (car lhs*) v) nr) (cons si live))))]))] [(conditional test conseq altern) (make-conditional (Expr test si r live) (Expr conseq si r live) (Expr altern si r live))] [(seq e0 e1) (make-seq (Expr e0 si r live) (Expr e1 si r live))] [(primcall op arg*) (make-primcall op (simple* arg* r))] [(forcall op rand*) (do-new-frame op rand* si r 'foreign live)] [(funcall op rand*) (do-new-frame op rand* si r 'normal live)] [(appcall op rand*) (do-new-frame op rand* si r 'apply live)] [else (error who "invalid expression ~s" (unparse x))])) (define (bind-fml* fml* r) (let f ([si 1] [fml* fml*]) (cond [(null? fml*) (values '() si r '())] [else (let-values ([(nfml* nsi r live) (f (add1 si) (cdr fml*))]) (let ([v (make-frame-var si)]) (values (cons v nfml*) nsi (cons (cons (car fml*) v) r) (cons si live))))]))) (define (bind-free* free*) (let f ([free* free*] [idx 0] [r '()]) (cond [(null? free*) r] [else (f (cdr free*) (add1 idx) (cons (cons (car free*) (make-cp-var idx)) r))]))) (define (CodeExpr x) (record-case x [(code fml* proper free* body) (let-values ([(fml* si r live) (bind-fml* fml* (bind-free* free*))]) (make-code fml* proper free* (Tail body si r live)))])) (define (CodesExpr x) (record-case x [(codes lhs* rhs* body) (make-codes lhs* (map CodeExpr rhs*) (Tail body 1 '() '()))])) (define (ConstantsExpr x) (record-case x [(constants lhs* body) (make-constants lhs* (CodesExpr body))])) (ConstantsExpr x)) (begin (define fx-shift 2) (define fx-mask #x03) (define fx-tag 0) (define bool-f #x2F) (define bool-t #x3F) (define bool-mask #xEF) (define bool-tag bool-f) (define bool-shift 4) (define nil #x4F) (define eof #x5F) ; double check (define unbound #x6F) ; double check (define void-object #x7F) ; double check (define wordsize 4) (define char-shift 8) (define char-tag #x0F) (define char-mask #xFF) (define pair-mask 7) (define pair-tag 1) (define disp-car 0) (define disp-cdr 4) (define pair-size 8) (define symbol-mask 7) (define symbol-tag 2) (define disp-symbol-string 0) (define disp-symbol-value 4) (define symbol-size 8) (define vector-tag 5) (define vector-mask 7) (define disp-vector-length 0) (define disp-vector-data 4) (define string-mask 7) (define string-tag 6) (define disp-string-length 0) (define disp-string-data 4) (define closure-mask 7) (define closure-tag 3) (define disp-closure-data 4) (define disp-closure-code 0) (define continuation-size 16) (define continuation-tag #x1F) (define disp-continuation-top 4) (define disp-continuation-size 8) (define disp-continuation-next 12) (define disp-frame-size -9) (define object-alignment 8) (define align-shift 3) (define pagesize 4096)) (begin (define (mem off val) (list 'mem off val)) (define (int x) (list 'integer x)) (define (byte x) (list 'byte x)) (define (byte-vector x) (list 'byte-vector x)) (define (movzbl src targ) (list 'movzbl src targ)) (define (sall src targ) (list 'sall src targ)) (define (sarl src targ) (list 'sarl src targ)) (define (shll src targ) (list 'shll src targ)) (define (shrl src targ) (list 'shrl src targ)) (define (notl src) (list 'notl src)) (define (pushl src) (list 'pushl src)) (define (popl src) (list 'popl src)) (define (orl src targ) (list 'orl src targ)) (define (xorl src targ) (list 'xorl src targ)) (define (andl src targ) (list 'andl src targ)) (define (movl src targ) (list 'movl src targ)) (define (movs src targ) (list 'movswl src targ)) (define (movb src targ) (list 'movb src targ)) (define (addl src targ) (list 'addl src targ)) (define (imull src targ) (list 'imull src targ)) (define (idivl src) (list 'idivl src)) (define (subl src targ) (list 'subl src targ)) (define (push src) (list 'push src)) (define (pop targ) (list 'pop targ)) (define (sete targ) (list 'sete targ)) (define (call targ) (list 'call targ)) (define (tail-indirect-cpr-call) (jmp (list 'indirect (mem (- disp-closure-code closure-tag) cpr)))) (define (indirect-cpr-call) (call (list 'indirect (mem (- disp-closure-code closure-tag) cpr)))) (define (negl targ) (list 'negl targ)) (define (label x) (list 'label x)) (define (label-address x) (list 'label-address x)) (define (ret) '(ret)) (define (cltd) '(cltd)) (define (cmpl arg1 arg2) (list 'cmpl arg1 arg2)) (define (je label) (list 'je label)) (define (jne label) (list 'jne label)) (define (jle label) (list 'jle label)) (define (jge label) (list 'jge label)) (define (jg label) (list 'jg label)) (define (jl label) (list 'jl label)) (define (jb label) (list 'jb label)) (define (ja label) (list 'ja label)) (define (jmp label) (list 'jmp label)) (define edi '(register %edi)) ; closure pointer (define esi '(register %esi)) ; pcb (define ebp '(register %ebp)) ; allocation pointer (define esp '(register %esp)) ; stack base pointer (define al '(register %al)) (define ah '(register %ah)) (define bh '(register %bh)) (define cl '(register %cl)) (define eax '(register %eax)) (define ebx '(register %ebx)) (define ecx '(register %ecx)) (define edx '(register %edx)) (define apr '(register %ebp)) (define fpr '(register %esp)) (define cpr '(register %edi)) (define pcr '(register %esi)) (define (argc-convention n) (- (fxsll n fx-shift))) ) (define (generate-code x main-name) (define who 'generate-code) (define (align n) (fxsll (fxsra (+ n object-alignment -1) align-shift) align-shift)) (define unique-label (let ([count 0]) (lambda () (let ([L (format "L_~a_~a" main-name count)]) (set! count (add1 count)) (label L))))) (define (constant-val x) (cond [(fixnum? x) (int (ash x fx-shift))] [(boolean? x) (int (if x bool-t bool-f))] [(null? x) (int nil)] [(char? x) (int (+ (ash (char->integer x) char-shift) char-tag))] [else (error 'constant-val "invalid immcprate ~s" x)])) (define (primref-loc op) (mem (* (pcb-index op) wordsize) pcr)) (define (immediate-rep x) (cond [(fixnum? x) (ash x fx-shift)] [(boolean? x) (if x bool-t bool-f)] [(null? x) nil] [(char? x) (+ (ash (char->integer x) char-shift) char-tag)] [else (error 'immediate-rep "invalid immediate ~s" x)])) (define (bool-bit-to-boolean ac) (list* (movzbl al eax) (shll (int bool-shift) eax) (orl (int bool-tag) eax) ac)) (define (cond-branch op Lt Lf ac) (define (opposite x) (cadr (assq x '([je jne] [jl jge] [jle jg] [jg jle] [jge jl])))) (unless (or Lt Lf) (error 'cond-branch "no labels")) (cond [(not Lf) (cons (list op Lt) ac)] [(not Lt) (cons (list (opposite op) Lf) ac)] [else (list* (list op Lt) (jmp Lf) ac)])) (define (indirect-type-pred pri-mask pri-tag sec-mask sec-tag rand* Lt Lf ac) (cond [(and Lt Lf) (list* (movl (Simple (car rand*)) eax) (movl eax ebx) (andl (int pri-mask) ebx) (cmpl (int pri-tag) ebx) (jne Lf) (movl (mem (- pri-tag) eax) ebx) (andl (int sec-mask) ebx) (cmpl (int sec-tag) ebx) (jne Lf) (jmp Lt) ac)] [Lf (list* (movl (Simple (car rand*)) eax) (movl eax ebx) (andl (int pri-mask) ebx) (cmpl (int pri-tag) ebx) (jne Lf) (movl (mem (- pri-tag) eax) ebx) (andl (int sec-mask) ebx) (cmpl (int sec-tag) ebx) (jne Lf) ac)] [Lt (let ([L_END (unique-label)]) (list* (movl (Simple (car rand*)) eax) (movl eax ebx) (andl (int pri-mask) ebx) (cmpl (int pri-tag) ebx) (jne L_END) (movl (mem (- pri-tag) eax) ebx) (andl (int sec-mask) ebx) (cmpl (int sec-tag) ebx) (je Lt) L_END ac))] [else ac])) (define (type-pred mask tag rand* Lt Lf ac) (cond [mask (list* (movl (Simple (car rand*)) eax) (andl (int mask) eax) (cmpl (int tag) eax) (cond-branch 'je Lt Lf ac))] [else (let ([v (Simple (car rand*))]) (cond [(memq (car v) '(mem register)) (list* (cmpl (int tag) (Simple (car rand*))) (cond-branch 'je Lt Lf ac))] [else (list* (movl (Simple (car rand*)) eax) (cmpl (int tag) eax) (cond-branch 'je Lt Lf ac))]))])) (define (compare-and-branch op rand* Lt Lf ac) (define (opposite x) (cadr (assq x '([je je] [jl jg] [jle jge] [jg jl] [jge jle])))) (cond [(constant? (cadr rand*)) (list* (cmpl (Simple (cadr rand*)) (Simple (car rand*))) (cond-branch op Lt Lf ac))] [(constant? (car rand*)) (list* (cmpl (Simple (car rand*)) (Simple (cadr rand*))) (cond-branch (opposite op) Lt Lf ac))] [else (list* (movl (Simple (car rand*)) eax) (cmpl (Simple (cadr rand*)) eax) (cond-branch op Lt Lf ac))])) (define (do-pred-prim op rand* Lt Lf ac) (case op [(fixnum?) (type-pred fx-mask fx-tag rand* Lt Lf ac)] [(pair?) (type-pred pair-mask pair-tag rand* Lt Lf ac)] [(char?) (type-pred char-mask char-tag rand* Lt Lf ac)] [(string?) (type-pred string-mask string-tag rand* Lt Lf ac)] [(symbol?) (type-pred symbol-mask symbol-tag rand* Lt Lf ac)] [(procedure?) (type-pred closure-mask closure-tag rand* Lt Lf ac)] [(boolean?) (type-pred bool-mask bool-tag rand* Lt Lf ac)] [(null?) (type-pred #f nil rand* Lt Lf ac)] [($unbound-object?) (type-pred #f unbound rand* Lt Lf ac)] [(not) (type-pred #f bool-f rand* Lt Lf ac)] [(eof-object?) (type-pred #f eof rand* Lt Lf ac)] [($fxzero?) (type-pred #f 0 rand* Lt Lf ac)] [($fx= $char= eq?) (compare-and-branch 'je rand* Lt Lf ac)] [($fx< $char<) (compare-and-branch 'jl rand* Lt Lf ac)] [($fx<= $char<=) (compare-and-branch 'jle rand* Lt Lf ac)] [($fx> $char>) (compare-and-branch 'jg rand* Lt Lf ac)] [($fx>= $char>=) (compare-and-branch 'jge rand* Lt Lf ac)] [(vector?) (indirect-type-pred vector-mask vector-tag fx-mask fx-tag rand* Lt Lf ac)] [($ap-check-words) (record-case (car rand*) [(constant i) (list* (movl (primref-loc '$allocation-redline) eax) (subl (Simple (cadr rand*)) eax) (subl (int i) eax) (cmpl eax apr) (cond-branch 'jge Lt Lf ac))] [else (error who "ap-check-words")])] [($ap-check-bytes) (record-case (car rand*) [(constant i) (list* (movl (Simple (cadr rand*)) eax) (negl eax) (addl (primref-loc '$allocation-redline) eax) (subl (int i) eax) (cmpl eax apr) (cond-branch 'jge Lt Lf ac))] [else (error who "ap-check-bytes")])] [($ap-check-const) (record-case (car rand*) [(constant i) (if (< i pagesize) (list* (cmpl (primref-loc '$allocation-redline) apr) (cond-branch 'jge Lt Lf ac)) (list* (movl (primref-loc '$allocation-redline) eax) (subl (int i) eax) (cmpl eax apr) (cond-branch 'jge Lt Lf ac)))] [else (error who "ap-check-const")])] [($fp-at-base) (list* (cmpl (mem (pcb-offset '$frame-base) pcr) fpr) (cond-branch 'je Lt Lf ac))] [($fp-overflow) (list* (cmpl (mem (pcb-offset '$frame-redline) pcr) fpr) (cond-branch 'jle Lt Lf ac))] [($vector-ref) (do-value-prim op rand* (do-simple-test eax Lt Lf ac))] [(cons void) ;;; always true (do-effect-prim op rand* (cond [(not Lt) ac] [else (cons (jmp Lt) ac)]))] [else (error 'pred-prim "HERE unhandled ~s" op)])) (define (do-pred->value-prim op rand* ac) (case op [else (let ([Lf (unique-label)] [Lj (unique-label)]) (do-pred-prim op rand* #f Lf (list* (movl (constant-val #t) eax) (jmp Lj) Lf (movl (constant-val #f) eax) Lj ac)))])) (define (indirect-ref arg* off ac) (list* (movl (Simple (car arg*)) eax) (movl (mem off eax) eax) ac)) (define (do-value-prim op arg* ac) (case op [(eof-object) (cons (movl (int eof) eax) ac)] [(void) (cons (movl (int void-object) eax) ac)] [($fxadd1) (list* (movl (Simple (car arg*)) eax) (addl (constant-val 1) eax) ac)] [($fxsub1) (list* (movl (Simple (car arg*)) eax) (addl (constant-val -1) eax) ac)] [($fx+) (list* (movl (Simple (car arg*)) eax) (addl (Simple (cadr arg*)) eax) ac)] [($fx-) (list* (movl (Simple (car arg*)) eax) (subl (Simple (cadr arg*)) eax) ac)] [($fx*) (cond [(constant? (car arg*)) (record-case (car arg*) [(constant c) (unless (integer? c) (error who "invalid arg ~s to fx*" c)) (list* (movl (Simple (cadr arg*)) eax) (imull (int c) eax) ac)])] [(constant? (cadr arg*)) (record-case (cadr arg*) [(constant c) (unless (integer? c) (error who "invalid arg ~s to fx*" c)) (list* (movl (Simple (car arg*)) eax) (imull (int c) eax) ac)])] [else (list* (movl (Simple (car arg*)) eax) (shrl (int fx-shift) eax) (imull (simple (cadr arg*)) eax) ac)])] [($fxquotient) (list* (movl (Simple (car arg*)) eax) (cltd) (idivl (Simple (cadr arg*))) (sall (int fx-shift) eax) ac)] [($fxlogor) (list* (movl (Simple (car arg*)) eax) (orl (Simple (cadr arg*)) eax) ac)] [($fxlogand) (list* (movl (Simple (car arg*)) eax) (andl (Simple (cadr arg*)) eax) ac)] [($fxlogxor) (list* (movl (Simple (car arg*)) eax) (xorl (Simple (cadr arg*)) eax) ac)] [($fxsra) (record-case (cadr arg*) [(constant i) (unless (fixnum? i) (error who "invalid arg to fxsra")) (list* (movl (Simple (car arg*)) eax) (sarl (int (+ i fx-shift)) eax) (sall (int fx-shift) eax) ac)] [else (list* (movl (Simple (car arg*)) eax) (movl (Simple (cadr arg*)) ecx) (sarl (int fx-shift) ecx) (sarl (int fx-shift) eax) (sarl cl eax) (sall (int fx-shift) eax) ac)])] [($fxsll) (record-case (cadr arg*) [(constant i) (unless (fixnum? i) (error who "invalid arg to fxsll")) (list* (movl (Simple (car arg*)) eax) (sall (int i) eax) ac)] [else (list* (movl (Simple (car arg*)) eax) (movl (Simple (cadr arg*)) ecx) (sarl (int fx-shift) ecx) (sall cl eax) ac)])] [($fixnum->char) (list* (movl (Simple (car arg*)) eax) (shll (int (- char-shift fx-shift)) eax) (orl (int char-tag) eax) ac)] [($char->fixnum) (list* (movl (Simple (car arg*)) eax) (shrl (int (- char-shift fx-shift)) eax) ac)] [($fxlognot) (list* (movl (Simple (car arg*)) eax) (orl (int fx-mask) eax) (notl eax) ac)] [($car) (indirect-ref arg* (- disp-car pair-tag) ac)] [($cdr) (indirect-ref arg* (- disp-cdr pair-tag) ac)] [($vector-length) (indirect-ref arg* (- disp-vector-length vector-tag) ac)] [($string-length) (indirect-ref arg* (- disp-string-length string-tag) ac)] [($symbol-string) (indirect-ref arg* (- disp-symbol-string symbol-tag) ac)] [($symbol-value) (indirect-ref arg* (- disp-symbol-value symbol-tag) ac)] [($constant-ref) (list* (movl (Simple (car arg*)) eax) ac)] [($vector-ref) (list* (movl (Simple (car arg*)) ebx) (addl (Simple (cadr arg*)) ebx) (movl (mem (- disp-vector-data vector-tag) ebx) eax) ac)] [($string-ref) (list* (movl (Simple (cadr arg*)) ebx) (shrl (int fx-shift) ebx) (addl (Simple (car arg*)) ebx) (movl (int char-tag) eax) (movb (mem (- disp-string-data string-tag) ebx) ah) ac)] [($string-ref-8+0) (list* (movl (Simple (cadr arg*)) ebx) (addl (Simple (car arg*)) ebx) (movl (int 0) eax) (movb (mem (- disp-string-data string-tag) ebx) ah) (sall (int fx-shift) eax) ac)] [($string-ref-8+2) (list* (movl (Simple (cadr arg*)) ebx) (addl (Simple (car arg*)) ebx) (movl (int 0) eax) (movb (mem (- (+ 16 disp-string-data) string-tag) ebx) ah) (sall (int fx-shift) eax) ac)] [($string-ref-16+0) (list* (movl (Simple (cadr arg*)) ebx) (addl (Simple (car arg*)) ebx) (movs (mem (- disp-string-data string-tag) ebx) eax) (sall (int fx-shift) eax) ac)] [($string-ref-16+1) (list* (movl (Simple (cadr arg*)) ebx) (addl (Simple (car arg*)) ebx) (movs (mem (- (+ 16 disp-string-data) string-tag) ebx) eax) (sall (int fx-shift) eax) ac)] [($make-string) (list* (movl (Simple (car arg*)) eax) (movl eax (mem disp-string-length apr)) (movl eax ebx) (movl apr eax) (addl (int string-tag) eax) (sarl (int fx-shift) ebx) (addl ebx apr) (addl (int (+ disp-string-data object-alignment)) apr) (sarl (int align-shift) apr) (sall (int align-shift) apr) ac)] [($make-vector) (list* (movl (Simple (car arg*)) eax) (movl eax (mem disp-vector-length apr)) (movl apr eax) (addl (int vector-tag) eax) (addl (mem disp-vector-length apr) apr) (addl (int (+ disp-vector-data object-alignment -1)) apr) (sarl (int align-shift) apr) (sall (int align-shift) apr) ac)] [(cons) (list* (movl (Simple (car arg*)) eax) (movl (Simple (cadr arg*)) ebx) (movl eax (mem disp-car apr)) (movl apr eax) (movl ebx (mem disp-cdr apr)) (addl (int pair-tag) eax) (addl (int (align pair-size)) apr) ac)] [($make-symbol) (list* (movl (Simple (car arg*)) eax) (movl (int unbound) (mem disp-symbol-value apr)) (movl eax (mem disp-symbol-string apr)) (movl apr eax) (addl (int symbol-tag) eax) (addl (int (align symbol-size)) apr) ac)] [(vector) (let f ([arg* arg*] [idx disp-vector-data]) (cond [(null? arg*) (list* (movl apr eax) (addl (int vector-tag) eax) (movl (int (- idx disp-vector-data)) (mem disp-vector-length apr)) (addl (int (align idx)) apr) ac)] [else (list* (movl (Simple (car arg*)) eax) (movl eax (mem idx apr)) (f (cdr arg*) (+ idx wordsize)))]))] [($pcb-ref) (let ([loc (car arg*)]) (record-case loc [(constant i) (unless (fixnum? i) (error who "invalid loc ~s" loc)) (list* (movl (mem (* i wordsize) pcr) eax) ac)] [else (error who "invalid loc ~s" loc)]))] [($string) (let f ([arg* arg*] [idx disp-string-data]) (cond [(null? arg*) (list* (movl apr eax) (addl (int string-tag) eax) (movl (int (* (- idx disp-string-data) wordsize)) (mem disp-string-length apr)) (addl (int (align (add1 idx))) apr) ac)] [else (record-case (car arg*) [(constant c) (unless (char? c) (error who "invalid arg to string ~s" x)) (list* (movb (int (char->integer c)) (mem idx apr)) (f (cdr arg*) (add1 idx)))] [else (list* (movl (Simple (car arg*)) ebx) (movb bh (mem idx apr)) (f (cdr arg*) (add1 idx)))])]))] [($underflow-and-return) (list* (movl (Simple (car arg*)) eax) (movl (mem (pcb-offset '$frame-base) pcr) fpr) (ret) ac)] [($current-frame) (list* (movl (mem (pcb-offset '$next-continuation) pcr) eax) ac)] [($seal-frame-and-call) (list* (movl (Simple (car arg*)) cpr) ; proc (movl (mem (pcb-offset '$frame-base) pcr) eax) ; eax=baseofstack (movl (mem 0 eax) ebx) ; underflow handler (movl ebx (mem (- wordsize) fpr)) ; set ; create a new cont record (movl (int continuation-tag) (mem 0 apr)) (movl fpr (mem disp-continuation-top apr)) ; compute the size of the captured frame (movl eax ebx) (subl fpr ebx) ; and store it (movl ebx (mem disp-continuation-size apr)) ; load next cont (movl (mem (pcb-offset '$next-continuation) pcr) ebx) ; and store it (movl ebx (mem disp-continuation-next apr)) ; adjust ap (movl apr eax) (addl (int vector-tag) eax) (addl (int continuation-size) apr) ; store new cont in current-cont (movl eax (mem (pcb-offset '$next-continuation) pcr)) ; adjust fp (subl (int wordsize) fpr) (movl fpr (mem (pcb-offset '$frame-base) pcr)) ; tail-call f (movl eax (mem (- wordsize) fpr)) (movl (int (argc-convention 1)) eax) (tail-indirect-cpr-call) ac)] [($pcb-set! $set-car! $set-cdr! $vector-set! $string-set! $exit $set-symbol-value!) (do-effect-prim op arg* (cons (movl (int void-object) eax) ac))] [(fixnum? $fxzero? boolean? char? pair? vector? string? symbol? procedure? null? not eof-object? $fx= $fx< $fx<= $fx> $fx>= eq? $char= $char< $char<= $char> $char>= $unbound-object?) (do-pred->value-prim op arg* ac)] [else (error 'value-prim "unhandled ~s" op)])) (define (do-effect-prim op arg* ac) (case op [($vector-set!) (list* (movl (Simple (car arg*)) ebx) (addl (Simple (cadr arg*)) ebx) (movl (Simple (caddr arg*)) eax) (movl eax (mem (- disp-vector-data vector-tag) ebx)) ac)] [($string-set!) (list* (movl (Simple (cadr arg*)) eax) (shrl (int fx-shift) eax) (addl (Simple (car arg*)) eax) (movl (Simple (caddr arg*)) ebx) (movb bh (mem (- disp-string-data string-tag) eax)) ac)] [($set-constant!) (NonTail (cadr arg*) (list* (movl eax (Simple (car arg*))) ac))] [($pcb-set!) (let ([loc (car arg*)] [val (cadr arg*)]) (record-case loc [(constant i) (unless (fixnum? i) (error who "invalid loc ~s" loc)) (list* (movl (Simple val) eax) (movl eax (mem (* i wordsize) pcr)) ac)] [else (error who "invalid loc ~s" loc)]))] [($set-car!) (list* (movl (Simple (car arg*)) eax) (movl (Simple (cadr arg*)) ebx) (movl ebx (mem (- disp-car pair-tag) eax)) ac)] [($set-cdr!) (list* (movl (Simple (car arg*)) eax) (movl (Simple (cadr arg*)) ebx) (movl ebx (mem (- disp-cdr pair-tag) eax)) ac)] [($set-symbol-value!) (list* (movl (Simple (car arg*)) eax) (movl (Simple (cadr arg*)) ebx) (movl ebx (mem (- disp-symbol-value symbol-tag) eax)) ac)] [($exit) (list* (movl (Simple (car arg*)) eax) (movl (mem (pcb-offset '$frame-base) pcr) fpr) (movl (int 0) (mem (pcb-offset '$next-continuation) pcr)) (jmp (label "SL_scheme_exit")) ac)] [($set-current-frame!) (list* (movl (Simple (car arg*)) eax) (movl eax (mem (pcb-offset '$next-continuation) pcr)) ac)] [(cons void) (let f ([arg* arg*]) (cond [(null? arg*) ac] [else (Effect (car arg*) (f (cdr arg*)))]))] [else (error 'do-effect-prim "unhandled op ~s" op)])) (define (do-simple-test x Lt Lf ac) (unless (or Lt Lf) (error 'Pred "no labels")) (cond [(not Lt) (list* (cmpl (int bool-f) x) (je Lf) ac)] [(not Lf) (list* (cmpl (int bool-f) x) (jne Lt) ac)] [else (list* (cmpl (int bool-f) x) (je Lf) (jmp Lt) ac)])) (define (Simple x) (record-case x [(cp-var i) (mem (+ (* i wordsize) (- disp-closure-data closure-tag)) cpr)] [(frame-var i) (mem (* i (- wordsize)) fpr)] [(constant c) (constant-val c)] [(constant-loc label) label] [(code-loc label) (label-address (label-name label))] [(primref op) (primref-loc op)] [else (error 'Simple "what ~s" x)])) (define (frame-adjustment offset) (* (sub1 offset) wordsize -1)) (define (NonTail x ac) (record-case x [(constant c) (cons (movl (constant-val c) eax) ac)] [(frame-var) (cons (movl (Simple x) eax) ac)] [(cp-var) (cons (movl (Simple x) eax) ac)] [(constant-loc label) (cons (movl label eax) ac)] [(foreign-label L) (cons (movl (label-address L) eax) ac)] [(primref c) (cons (movl (primref-loc c) eax) ac)] [(closure label arg*) (let f ([arg* arg*] [off disp-closure-data]) (cond [(null? arg*) (list* (movl (Simple label) (mem 0 apr)) (movl apr eax) (addl (int (align off)) apr) (addl (int closure-tag) eax) ac)] [else (list* (movl (Simple (car arg*)) eax) (movl eax (mem off apr)) (f (cdr arg*) (+ off wordsize)))]))] [(conditional test conseq altern) (let ([Lj (unique-label)] [Lf (unique-label)]) (Pred test #f Lf (NonTail conseq (list* (jmp Lj) Lf (NonTail altern (cons Lj ac))))))] [(seq e0 e1) (Effect e0 (NonTail e1 ac))] [(primcall op rand*) (do-value-prim op rand* ac)] [(new-frame base-idx size body) (NonTail body ac)] [(call-cp convention offset size mask) (let ([L_CALL (unique-label)]) (case convention [(normal) (list* (addl (int (frame-adjustment offset)) fpr) (movl (int (argc-convention size)) eax) (jmp L_CALL) (byte-vector mask) (int (* offset wordsize)) (byte 0) ; padding for indirect calls only (byte 0) ; direct calls are ok L_CALL (indirect-cpr-call) (movl (mem 0 fpr) cpr) (subl (int (frame-adjustment offset)) fpr) ac)] [(apply) (list* (addl (int (frame-adjustment offset)) fpr) (movl (int (argc-convention size)) eax) (jmp L_CALL) (byte-vector mask) (int (* offset wordsize)) L_CALL (call (label "SL_apply")) (movl (mem 0 fpr) cpr) (subl (int (frame-adjustment offset)) fpr) ac)] [(foreign) (list* (addl (int (frame-adjustment offset)) fpr) (movl (int (argc-convention size)) eax) (jmp L_CALL) (byte-vector mask) (int (* offset wordsize)) L_CALL (call (label "SL_foreign_call")) (movl (mem 0 fpr) cpr) (subl (int (frame-adjustment offset)) fpr) ac)] [else (error who "invalid convention ~s for call-cp" convention)]))] [else (error 'NonTail "invalid expression ~s" x)])) (define (Pred x Lt Lf ac) (record-case x [(frame-var i) (do-simple-test (idx->frame-loc i) Lt Lf ac)] [(cp-var i) (do-simple-test (Simple x) Lt Lf ac)] [(constant-loc) (if Lt (cons (jmp Lt) ac) ac)] [(constant c) (if c (if Lt (cons (jmp Lt) ac) ac) (if Lf (cons (jmp Lf) ac) ac))] [(primcall op rand*) (do-pred-prim op rand* Lt Lf ac)] [(conditional test conseq altern) (cond [(not Lt) (let ([Lj^ (unique-label)] [Lf^ (unique-label)]) (Pred test #f Lf^ (Pred conseq Lj^ Lf (cons Lf^ (Pred altern #f Lf (cons Lj^ ac))))))] [(not Lf) (let ([Lj^ (unique-label)] [Lf^ (unique-label)]) (Pred test #f Lf^ (Pred conseq Lt Lj^ (cons Lf^ (Pred altern Lt #f (cons Lj^ ac))))))] [else (let ([Lf^ (unique-label)]) (Pred test #f Lf^ (Pred conseq Lt Lf (cons Lf^ (Pred altern Lt Lf ac)))))])] [(seq e0 e1) (Effect e0 (Pred e1 Lt Lf ac))] [(new-frame) (NonTail x (do-simple-test eax Lt Lf ac))] [else (error 'Pred "invalid expression ~s" x)])) (define (idx->frame-loc i) (mem (* i (- wordsize)) fpr)) (define (Effect x ac) (record-case x [(constant) ac] [(constant-loc) ac] [(primcall op rand*) (do-effect-prim op rand* ac)] [(conditional test conseq altern) (let ([Lf (unique-label)] [Ljoin (unique-label)]) (Pred test #f Lf (Effect conseq (list* (jmp Ljoin) Lf (Effect altern (cons Ljoin ac))))))] [(seq e0 e1) (Effect e0 (Effect e1 ac))] [(assign loc val) (record-case loc [(frame-var i) (NonTail val (cons (movl eax (idx->frame-loc i)) ac))] [else (error who "invalid assign loc ~s" loc)])] [(eval-cp check body) (NonTail body (cond [check (list* (movl eax cpr) (andl (int closure-mask) eax) (cmpl (int closure-tag) eax) (jne (label "SL_nonprocedure")) ac)] [else (list* (movl eax cpr) ac)]))] [(save-cp loc) (record-case loc [(frame-var i) (cons (movl cpr (idx->frame-loc i)) ac)] [else (error who "invalid cpr loc ~s" x)])] [(new-frame) (NonTail x ac)] [else (error 'Effect "invalid expression ~s" x)])) (define (Tail x ac) (record-case x [(return x) (NonTail x (cons (ret) ac))] [(conditional test conseq altern) (let ([L (unique-label)]) (Pred test #f L (Tail conseq (cons L (Tail altern ac)))))] [(seq e0 e1) (Effect e0 (Tail e1 ac))] [(new-frame idx size body) (Tail body ac)] [(call-cp convention idx argc mask) (let f ([i 0]) (cond [(= i argc) (case convention [(normal) (list* (movl (int (argc-convention argc)) eax) (tail-indirect-cpr-call) ac)] [(apply) (list* (movl (int (argc-convention argc)) eax) (jmp (label "SL_apply")) ac)] [else (error who "invalid conv ~s in tail call-cpr" convention)])] [else (list* (movl (mem (* (+ idx i 1) (- wordsize)) fpr) eax) (movl eax (mem (* (+ i 1) (- wordsize)) fpr)) (f (add1 i)))]))] [else (error 'Tail "invalid expression ~s" x)])) (define (handle-vararg fml-count ac) (define CONTINUE_LABEL (unique-label)) (define DONE_LABEL (unique-label)) (define CONS_LABEL (unique-label)) (define LOOP_HEAD (unique-label)) (define L_CALL (unique-label)) (list* (cmpl (int (argc-convention (sub1 fml-count))) eax) (jg (label "SL_invalid_args")) (jl CONS_LABEL) (movl (int nil) ebx) (jmp DONE_LABEL) CONS_LABEL (movl (primref-loc '$allocation-redline) ebx) (addl eax ebx) (addl eax ebx) (cmpl ebx apr) (jle LOOP_HEAD) (addl eax esp) ; advance esp to cover args (pushl cpr) ; push current cp (pushl eax) ; push argc (negl eax) ; make argc positive (addl (int (* 4 wordsize)) eax) ; add 4 words to adjust frame size (pushl eax) ; push frame size (addl eax eax) ; double the number of args (movl eax (mem (* -2 wordsize) fpr)) ; pass it as first arg (movl (int (argc-convention 1)) eax) ; setup argc (movl (primref-loc 'do-overflow-with-byte-count) cpr) ; load handler (jmp L_CALL) ; go to overflow handler (int 0) ; if the framesize=0, then the framesize is dynamic (byte 0) (byte 0) L_CALL (indirect-cpr-call) (popl eax) ; pop framesize and drop it (popl eax) ; reload argc (popl cpr) ; reload cp (subl eax esp) ; readjust fp LOOP_HEAD (movl (int nil) ebx) CONTINUE_LABEL (movl ebx (mem disp-cdr apr)) (movl (mem fpr eax) ebx) (movl ebx (mem disp-car apr)) (movl apr ebx) (addl (int pair-tag) ebx) (addl (int pair-size) apr) (addl (int (fxsll 1 fx-shift)) eax) (cmpl (int (- (fxsll fml-count fx-shift))) eax) (jle CONTINUE_LABEL) DONE_LABEL (movl ebx (mem (- (fxsll fml-count fx-shift)) fpr)) ac)) (define (handle-procedure-entry proper fml-count ac) (cond [proper (list* (cmpl (int (argc-convention fml-count)) eax) (jne (label "SL_invalid_args")) ac)] [else (handle-vararg fml-count ac)])) (define emit-code (lambda (label x) (record-case x [(code fml* proper free* body) (list* 'local-function (label-name label) (+ disp-closure-data (* wordsize (length free*))) (handle-procedure-entry proper (length fml*) (Tail body '())))]))) (define (emit-codes prog) (record-case prog [(codes lhs* rhs* body) (let ([label* (map (lambda (x) (unique-label)) lhs*)]) (for-each set-code-loc-label! lhs* label*) (let ([procs (map emit-code label* rhs*)] [main-proc (list* 'local-function "L_scheme_entry" 0 (Tail body '()))]) (cons main-proc procs)))])) (define label-name cadr) (define (emit-constants prog) (record-case prog [(constants lhs* body) (let ([label* (map (lambda (x) (unique-label)) lhs*)]) (for-each set-constant-loc-label! lhs* label*) (cons (list 'global-data (string-append main-name "_constant_count") (length lhs*)) (append (map (lambda (x) (list 'data (label-name x) 0)) label*) (emit-codes body))))])) (define (emit-prog prog main-name) (list* (list 'public-function (format "~a_entry" main-name) 0 (movl (mem 4 esp) eax) ; pcb (push ebx) (push esi) (push edi) (push ebp) (movl eax pcr) (movl (mem (pcb-offset '$allocation-pointer) pcr) apr) (movl esp (mem (pcb-offset '$system-stack) pcr)) (movl (mem (pcb-offset '$frame-base) pcr) fpr) (movl (label-address "SL_underflow_handler") (mem 0 fpr)) (jmp (label "L_scheme_entry"))) (emit-constants prog))) (emit-prog x main-name)) (define (asm-helper-code) (list (list 'public-function "SL_scheme_exit" 0 (movl apr (mem (pcb-offset '$allocation-pointer) pcr)) (cmpl (mem (pcb-offset '$frame-base) pcr) fpr) (jne (label "L_scheme_exit_fp_mismatch")) (movl (mem (pcb-offset '$system-stack) pcr) esp) (pop ebp) (pop edi) (pop esi) (pop ebx) (ret) (label "L_scheme_exit_fp_mismatch") (movl (int 0) eax) (movl (mem 0 eax) eax)) (list 'public-function "SL_underflow_handler" 0 ; since we underflow with a call to (ret), the current fp ; is below the valid stack, so we advance it up to point ; to the underflow handler that caused the ret (subl (int wordsize) fpr) ; load next continuation into ebx, and if ebx=0, exit ; since the computation is complete (movl (mem (pcb-offset '$next-continuation) pcr) ebx) (cmpl (int 0) ebx) (je (label "SL_scheme_exit")) ; sanity check that fpr *is* where it should be (cmpl (mem (pcb-offset '$frame-base) pcr) fpr) (jne (label "L_underflow_misaligned")) (label "L_underflow_frame_ok") ;(movl (int 0) eax) ;(movl (mem 0 eax) eax) ; sanity check that 0(fpr) does contain underflow hander (cmpl (label-address "SL_underflow_handler") (mem 0 fpr)) (jne (label "L_underflow_no_rp")) ; save the value of eax (pushl eax) ; now ebx=next_cont (movl (mem (- disp-continuation-top vector-tag) ebx) ecx) ; ebx=cc, ecx=cont_top (movl (mem (- disp-continuation-size vector-tag) ebx) eax) ; ebx=cc, ecx=cont_top, eax=cont_size (movl (mem 0 ecx) edx) ; return point is in edx ; ebx=cc, ecx=cont_top, eax=cont_size, edx=rp (movl (mem disp-frame-size edx) edx) ; size ; ebx=cc, ecx=cont_top, eax=cont_size, edx=top_frame_size (cmpl (int 0) edx) (jne (label "L_underflow_normal_frame")) (label "L_underflow_special_frame") (movl (int 0) eax) (movl (mem 0 eax) eax) (label "L_underflow_normal_frame") ; ebx=cc, ecx=cont_top, eax=cont_size, edx=top_frame_size (cmpl eax edx) (je (label "L_underflow_single_frame")) (label "L_underflow_multiple_frames") (cmpl (mem (pcb-offset '$allocation-redline) pcr) apr) (jge (label "L_underflow_heap_overflow")) ; ebx=cc, ecx=cont_top, eax=cont_size, edx=top_frame_size (movl (int continuation-tag) (mem 0 apr)) (subl edx eax) ; ebx=cc, ecx=cont_top, eax=remaining_size, edx=top_frame_size (movl eax (mem disp-continuation-size apr)) (movl edx (mem (- disp-continuation-size vector-tag) ebx)) (addl edx ecx) ; ebx=cc, ecx=next_cont_top, eax=remaining_size, edx=top_frame_size (movl ecx (mem disp-continuation-top apr)) (subl edx ecx) ; ebx=cc, ecx=cont_top, eax=next_cont, edx=top_frame_size (movl (mem (- disp-continuation-next vector-tag) ebx) eax) (movl eax (mem disp-continuation-next apr)) (movl apr eax) (addl (int vector-tag) eax) (addl (int continuation-size) apr) (movl eax (mem (- disp-continuation-next vector-tag) ebx)) ; framesize=edx, top=ecx, cc=ebx (label "L_underflow_single_frame") ; advance cc (movl (mem (- disp-continuation-next vector-tag) ebx) eax) (movl eax (mem (pcb-offset '$next-continuation) pcr)) (popl eax) ; pop the return value (label "L_underflow_copy_loop") (subl (int wordsize) edx) (movl (mem ecx edx) ebx) (pushl ebx) (cmpl (int 0) edx) (jg (label "L_underflow_copy_loop")) (ret) (label "L_underflow_no_rp") (movl (int 0) eax) (movl (mem 0 eax) eax) (label "L_underflow_misaligned") (movl (mem (pcb-offset '$frame-base) pcr) ebx) (movl (int 0) eax) (movl (mem 0 eax) eax) (label "L_underflow_heap_overflow") ; the return value that was in %eax was pushed previously ; so, we push the frame size next (pushl (int (* 3 wordsize))) (movl (mem (pcb-offset 'do-overflow) pcr) cpr) (movl (int (argc-convention 0)) eax) (jmp (label "L_underflow_overflow_call")) (int 0) (byte 0) (byte 0) (label "L_underflow_overflow_call") (indirect-cpr-call) (popl eax) ; pop framesize (popl eax) ; actual return value and underflow again (ret)) (list 'public-function "SL_foreign_call" 0 (movl fpr (mem (pcb-offset '$frame-pointer) pcr)) (movl apr (mem (pcb-offset '$allocation-pointer) pcr)) (movl fpr ebx) (movl (mem (pcb-offset '$system-stack) pcr) esp) (pushl pcr) (cmpl (int 0) eax) (je (label "L_foreign_call_set")) (label "L_foreign_call_loop") (movl (mem ebx eax) ecx) (pushl ecx) (addl (int 4) eax) (cmpl (int 0) eax) (jne (label "L_foreign_call_loop")) (label "L_foreign_call_set") (call (list 'indirect cpr)) (movl (mem (pcb-offset '$frame-pointer) pcr) fpr) (movl (mem (pcb-offset '$allocation-pointer) pcr) apr) (ret)) (list 'public-function "SL_apply" 0 (movl (mem fpr eax) ebx) (cmpl (int nil) ebx) (je (label "L_apply_done")) (label "L_apply_loop") (movl (mem (- disp-car pair-tag) ebx) ecx) (movl (mem (- disp-cdr pair-tag) ebx) ebx) (movl ecx (mem fpr eax)) (subl (int wordsize) eax) (cmpl (int nil) ebx) (jne (label "L_apply_loop")) (label "L_apply_done") (addl (int wordsize) eax) (tail-indirect-cpr-call)) (list 'public-function "SL_nonprocedure" 0 ;;; (movl cpr (mem (- wordsize) fpr)) ; first arg (movl (mem (pcb-offset '$apply-nonprocedure-error-handler) pcr) cpr) (movl (int (argc-convention 1)) eax) (tail-indirect-cpr-call)) (list 'public-function "SL_invalid_args" 0 ;;; (movl cpr (mem (- wordsize) fpr)) ; first arg (negl eax) (movl eax (mem (- (* 2 wordsize)) fpr)) (movl (mem (pcb-offset '$incorrect-args-error-handler) pcr) cpr) (movl (int (argc-convention 2)) eax) (tail-indirect-cpr-call)))) (define (emit-linear-code obj*) (define who 'emit-linear-code) (define (arg x) (cond [(not (pair? x)) (error who "invalid arg ~s" x)] [else (case (car x) [(register) (cadr x)] [(label) (cadr x)] [(label-address) (format "$~a" (cadr x))] [(integer) (format "$~a" (cadr x))] [(mem) (cond [(integer? (cadr x)) (format "~a(~a)" (cadr x) (arg (caddr x)))] [else (format "(~a,~a)" (arg (cadr x)) (arg (caddr x)))])] [(indirect) (format "*~a" (arg (cadr x)))] [else (error who "invalid arg ~s" x)])])) (define (emit-generic x) (case (length x) [(1) (emit " ~a" (car x))] [(2) (emit " ~a ~a" (car x) (arg (cadr x)))] [(3) (emit " ~a ~a, ~a" (car x) (arg (cadr x)) (arg (caddr x)))] [else (error 'emit-generic "invalid format ~s" x)])) (define (emit-instruction x) (case (car x) [(pop movl movswl movb push call ret cltd cmpl je jne jl jle jg jge jb jbe ja jae jmp sete setl setle setg setge movzbl pushl popl addl subl orl xorl andl notl shll shrl sall sarl imull idivl negl) (emit-generic x)] [(label) (emit "~a:" (cadr x))] [(comment) (emit "/* ~s */" (cadr x))] [(integer) (emit ".long ~s" (cadr x))] [(byte) (emit ".byte ~s" (cadr x))] [(byte-vector) (let f ([v (cadr x)] [i 0]) (unless (= i (vector-length v)) (emit ".byte ~s" (vector-ref v i)) (f v (add1 i))))] [else (error 'emit-instruction "unsupported instruction ~s" (car x))])) (define (emit-function-header x) (let ([t (car x)] [label (cadr x)] [closure-size (caddr x)]) (emit ".text") (when (eq? t 'public-function) (emit ".globl ~a" label)) (emit ".type ~a @function" label) (emit ".align 8") (emit ".long 0") (emit ".long ~s" closure-size) (emit "~a:" label))) (define (emit-function x) (emit-function-header x) (for-each emit-instruction (cdddr x))) (define (emit-data x) (let ([t (car x)] [label (cadr x)] [value (caddr x)]) (emit ".data") (emit ".align 4") (when (eq? t 'global-data) (emit ".globl ~a" label)) (emit ".type ~a, @object" label) (emit ".size ~a, 4" label) (emit "~a:" label) (emit ".long ~s" value))) (define (emit-object x) (case (car x) [(public-function local-function) (emit-function x)] [(data global-data) (emit-data x)] [else (error who "invalid object ~s" (car x))])) (for-each emit-object obj*)) (define (compile-program-with-entry original-program scheme-entry) (let* (;;; [p (recordize original-program)] [p (optimize-direct-calls p)] [p (remove-assignments p)] [p (convert-closures p)] [p (lift-codes p)] [p (lift-complex-constants p)] [p (introduce-primcalls p)] [p (simplify-operands p)] [p (insert-stack-overflow-checks p)] [p (insert-allocation-checks p)] [p (remove-local-variables p)] [p (generate-code p scheme-entry)]) (emit-linear-code p))) (define (compile-program x) (compile-program-with-entry x "scheme")) (define (file-content x) (let ([p (open-input-file x)]) (let f () (let ([x (read p)]) (cond [(eof-object? x) (close-input-port p) '()] [else (cons x (f))]))))) (define (generate-library x) (let ([input-file-name (car x)] [output-file-name (cadr x)] [entry-name (caddr x)]) (printf "compiling ~s\n" input-file-name) (let ([prog (cons 'begin (file-content input-file-name))]) (let ([op (open-output-file output-file-name 'replace)]) (parameterize ([compile-port op] [inline-primitives #t] [signal-error-on-undefined-pcb #f]) (compile-program-with-entry prog entry-name)) (close-output-port op))))) (define (generate-top-level) (printf "compiling top-level\n") (let ([prog (cons 'begin (map (lambda (x) `($set-symbol-value! ',x ,x)) (public-primitives)))]) (let ([op (open-output-file "libtoplevel.s" 'replace)]) (parameterize ([compile-port op] [inline-primitives #t]) (compile-program-with-entry prog "libtoplevel")) (close-output-port op)))) (define (generate-scheme-h) (let ([p (open-output-file "scheme.h" 'replace)]) (define (def name val) (fprintf p "#define ~a ~a\n" name val)) (define (defp name val) (fprintf p "#define ~a ((ptr)~a)\n" name val)) (fprintf p "/* automatically generated, do not edit */\n") (fprintf p "#ifndef SCHEME_H\n") (fprintf p "#define SCHEME_H\n") (fprintf p "typedef char* ptr;\n") (def "fx_shift" fx-shift) (def "fx_mask" fx-mask) (def "fx_tag" fx-tag) (defp "bool_f" bool-f) (defp "bool_t" bool-t) (def "bool_mask" bool-mask) (def "bool_tag" bool-tag) (def "bool_shift" bool-shift) (defp "empty_list" nil) (def "wordsize" wordsize) (def "char_shift" char-shift) (def "char_tag" char-tag) (def "char_mask" char-mask) (def "pair_mask" pair-mask) (def "pair_tag" pair-tag) (def "disp_car" disp-car) (def "disp_cdr" disp-cdr) (def "pair_size" pair-size) (def "symbol_mask" symbol-mask) (def "symbol_tag" symbol-tag) (def "disp_symbol_string" disp-symbol-string) (def "disp_symbol_value" disp-symbol-value) (def "symbol_size" symbol-size) (def "vector_tag" vector-tag) (def "vector_mask" vector-mask) (def "disp_vector_length" disp-vector-length) (def "disp_vector_data" disp-vector-data) (def "string_mask" string-mask) (def "string_tag" string-tag) (def "disp_string_length" disp-string-length) (def "disp_string_data" disp-string-data) (def "closure_mask" closure-mask) (def "closure_tag" closure-tag) (def "disp_closure_data" disp-closure-data) (def "disp_closure_code" disp-closure-code) (def "continuation_tag" continuation-tag) (def "disp_continuation_top" disp-continuation-top) (def "disp_continuation_size" disp-continuation-size) (def "disp_continuation_next" disp-continuation-next) (def "continuation_size" continuation-size) (def "disp_frame_size" disp-frame-size) (def "object_alignment" object-alignment) (def "align_shift" align-shift) (fprintf p "typedef struct {\n") (for-each (lambda (x) (fprintf p " ptr ~a;\n" x)) (pcb-cnames)) (fprintf p "} pcb_t;\n") (fprintf p "ptr scheme_entry(pcb_t* pcb);\n") (fprintf p "extern ptr scheme_main(pcb_t* pcb);\n") (fprintf p "#endif /* SCHEME_H */\n") (close-output-port p))) (define (generate-scheme-c) (let ([p (open-output-file "scheme.c" 'replace)]) (fprintf p "/* automatically generated, do not edit */\n") (fprintf p "#include \"scheme.h\"\n") (fprintf p "#include \n") (fprintf p "ptr scheme_main(pcb_t* pcb){\n") (fprintf p "extern void S_add_roots(pcb_t*,int*);\n") (fprintf p "extern void S_check_roots(pcb_t*,int*);\n") (for-each (lambda (x) (let ([name (caddr x)]) (fprintf p "extern void ~a_entry(pcb_t*);\n" name) (fprintf p "extern int ~a_constant_count;\n" name))) scheme-library-files) (fprintf p "extern void ~a_entry(pcb_t*);\n" "libtoplevel") (for-each (lambda (x) (let ([name (caddr x)]) ;(fprintf p " fprintf(stderr, \"intered ~a\\n\");\n" name) (fprintf p " S_add_roots(pcb, &~a_constant_count);\n" name) (fprintf p " ~a_entry(pcb);\n" name) (fprintf p " S_check_roots(pcb, &~a_constant_count);\n" name) ;(fprintf p " fprintf(stderr, \"exited ~a\\n\");\n" name) )) scheme-library-files) (fprintf p " libtoplevel_entry(pcb);\n"); (fprintf p " return scheme_entry(pcb);\n"); (fprintf p "}\n") (close-output-port p))) (define (generate-scheme-asm) (let ([p (open-output-file "scheme_asm.s" 'replace)]) (parameterize ([compile-port p]) (emit "# AUTOMATICALLY GENERATED, DO NOT EDIT") (emit-linear-code (asm-helper-code))) (close-output-port p))) (define (generate-scheme-runtime-helpers) (generate-scheme-h) (generate-scheme-c) (generate-scheme-asm)) (define (string-join sep str*) (cond [(null? str*) ""] [(null? (cdr str*)) (car str*)] [else (string-append (car str*) sep (string-join sep (cdr str*)))])) (printf "Generating C Helpers\n") (generate-scheme-runtime-helpers) (printf "Generating libraries\n") (for-each generate-library scheme-library-files) (generate-top-level) ;;; ensure that we did not emit a reference to an unset pcb cell. (printf "Checking PCB\n") (let ([undefined '()]) (for-each (lambda (x) (when (and (pcb-referenced? (car x)) (not (pcb-assigned? (car x))) (not (pcb-system-loc? (car x)))) (set! undefined (cons (car x) undefined)))) pcb-table) (unless (null? undefined) ((if (signal-error-on-undefined-pcb) error warning) 'compile "undefined primitives found ~s" undefined))) (runtime-file (string-join " " (list* "scheme.c" "scheme_asm.s" "runtime-5.4.c" "collect-5.4.c" "libtoplevel.s" (map cadr scheme-library-files)))) (with-output-to-file "Makefile" (lambda () (printf "stst: stst.s ~a\n" (runtime-file)) (printf "\tgcc -Wall -o stst stst.s ~a\n" (runtime-file))) 'replace) (printf "Testing ...\n") ;(test-all) ;(parameterize ([inline-primitives #f]) (test-all)) ;(parameterize ([inline-primitives #t]) (test-all)) (parameterize ([inline-primitives #t] [input-filter (lambda (x) `(begin (write ,x) (newline) (exit) ))]) (test-all)) ; (parameterize ([inline-primitives #t] ; [input-filter ; (lambda (x) ; `(let ([expr ',x]) ; (let ([p (open-output-file "stst.tmp" 'replace)]) ; (write expr p) ; (close-output-port p)) ; (let ([p (open-input-file "stst.tmp")]) ; (let ([t (read p)]) ; (unless (equal? t expr) ; (error 'test ; "not equal: got ~s, should be ~s" ; t expr))) ; (close-input-port p)) ; (write ,x) ; as usual ; (newline) ; (exit)))]) ; (test-all)) ;(parameterize ([inline-primitives #t] ; [input-filter ; (lambda (x) ; `(begin ; (write (eval ',x)) ; (newline) ; (exit 0) ; ))]) ; (test-all)) ; (define (get-date) (let ([ls (process "date +\"%F\"")]) (let ([ip (car ls)]) (list->string (let f () (let ([x (read-char ip)]) (if (char=? x #\newline) '() (cons x (f))))))))) (build-program `(begin (display ,(format "Petite Ikarus Scheme (Build ~a)\n" (get-date))) (display "Copyright (c) 2006 Abdulaziz Ghuloum\n\n") (new-cafe))) (system "cp stst petite-ikarus")