* made assembler accept integers (instead of fixnums) as immediates.

This commit is contained in:
Abdulaziz Ghuloum 2007-02-05 14:19:03 -05:00
parent d04dd79b81
commit f5d870f23b
4 changed files with 349 additions and 316 deletions

Binary file not shown.

View File

@ -172,6 +172,7 @@
[(jmpcall label rator arg*)
(make-jmpcall label (Expr rator) (map Expr arg*))]
[(appcall rator arg*)
(error 'new-cogen "appcall not supported yet")
(make-appcall (Expr rator) (map Expr arg*))]
[(mvcall rator k)
(make-mvcall (Expr rator) (Clambda k))]
@ -197,336 +198,214 @@
;;;
(Program x))
;;;
;;; So, what do we want to do here?
;;; 1. we eliminate all variables:
;;; bind should become a sequence of (setfv i <value>) statements
;;; variable refs should befome (fv i) where i is the index of
;;; the var on the stack.
;;; 2. we need to keep track of the maximum stack size used; and
;;; whether we made a procedure call so that we can insert a
;;; stack overflow check with an appropriate size check.
;;; 3. as we generate code, we need to keep track of which stack
;;; locations contain pointers so that procedure calls can
;;; set an appropriate mask.
;;; 4. primitives that allocate, as well as closures and fixes
;;; should insert an appropriate alloc-check marks as well as
;;; keep the live masks for the later generation of trap handlers
;;; 5. primcalls should also keep track of liveness information
;;; and frame size just in case the primitive needs to make a
;;; procedure call.
(define-record move (src dst))
(define-record alloc-check (n si live))
(define-record fvar (idx))
(define acr '%acr)
(define-record cpvar (idx))
(define-record cmp (op v0 v1))
(define false-object 'false-object)
(define (new-cogen-pass1 x)
(define (eliminate-fix x)
;;;
(define who 'new-cogen-pass-1)
(define who 'eliminate-fix)
;;;
(define (fxeven? x)
(if (fixnum? x)
($fxzero? ($fxlogand x 1))
(error 'fxeven? "~s is not a fixnum" x)))
;;;
(define (sum ls)
(let f ([ls ls] [n 0])
(cond
[(null? ls) n]
[else (f (cdr ls) (fx+ (car ls) n))])))
;;;
(define fxmax
(case-lambda
[(x y) (if (fx> x y) x y)]
[(x y z) (fxmax x (fxmax y z))]
[_ (error 'fxmax "unhandled")]))
;;;
(define (do-seq e0 si live env e1 k)
(let-values ([(e0 msi0 call0?)
(Effect e0 si live env)])
(let-values ([(e1 msi1 call1?)
(k e1 si live env)])
(values (make-seq e0 e1)
(fxmax msi0 msi1)
(or call0? call1?)))))
;;;
(define (do-cond e0 si live env e1 e2 k)
(let-values ([(e0 msi0 call0?)
(Pred e0 si live env)])
(let-values ([(e1 msi1 call1?)
(k e1 si live env)]
[(e2 msi2 call2?)
(k e2 si live env)])
(values (make-conditional e0 e1 e2)
(fxmax msi0 msi1 msi2)
(or call0? call1? call2?)))))
;;;
(define (do-move-to-mem loc expr si live env)
(record-case expr
[(constant)
(values (make-move expr loc) 0 #f)]
[else
(let-values ([(x msi call?)
(Value expr si live env)])
(values (make-seq x (make-move acr loc)) msi call?))]))
;;;
(define (do-bind lhs* rhs* si live env0 env body k)
(cond
[(null? lhs*)
(k body si live env)]
[else
(let ([fv (make-fvar si)])
(let-values ([(e0 msi0 call0?)
(do-move-to-mem fv (car rhs*) si live env0)])
(let-values ([(e1 msi1 call1?)
(do-bind (cdr lhs*) (cdr rhs*)
(fxadd1 si)
(cons si live)
env0
(cons (cons (car lhs*) fv) env)
body
k)])
(values (make-seq e0 e1)
(fxmax msi0 msi1)
(or call0? call1?)))))]))
;;;
(define (align n)
(cond
[(fxeven? n) n]
[else (fxadd1 n)]))
;;;
(define (extend-env* lhs* si live env)
(let f ([lhs* lhs*] [si si] [live live] [env env] [nlhs* '()])
(cond
[(null? lhs*)
(values nlhs* si live env)]
[else
(let ([fv (make-fvar si)])
(f (cdr lhs*) (fxadd1 si) (cons si live)
(cons (cons (car lhs*) fv) env)
(cons fv nlhs*)))])))
;;;
(define (insert-const-alloc-check n si live rest)
(cond
[(fxzero? n) rest]
[else
(make-seq
(make-alloc-check n si live)
rest)]))
;;;
(define (construct-closures n* lhs* nlhs* rhs* body)
(cond
[(null? lhs*) body]
[else
(make-seq 'FIXME:construct-closures body)]))
;;;
(define (do-fix lhs* rhs* si live env body k)
(define (compute-closure-size x)
(record-case x
[(closure label free*)
(align (fxadd1 (length free*)))]))
(let ([n* (map compute-closure-size rhs*)])
(let ([n (sum n*)])
(let-values ([(nlhs* si live env)
(extend-env* lhs* si live env)])
(let-values ([(x msi call?)
(k body si live env)])
(values (insert-const-alloc-check n si live
(construct-closures n* lhs* nlhs* rhs* x))
msi call?))))))
;;;
(define (constant-rep x)
'FIXME:constant-rep)
;;;
(define (do-closure label free* si live env)
'FIXME:do-closure)
;;;
(define (do-forcall x si live env)
(values 'FIXME:do-forcall si #f))
;;;
(define (do-tail-funcall x si live env)
(values 'FIXME:do-tail-funcall si #f))
;;;
(define (do-tail-appcall x si live env)
(values 'FIXME:do-tail-appcall si #f))
;;;
(define (do-tail-jmpcall x si live env)
(values 'FIXME:do-tail-jmpcall si #f))
;;;
(define (do-effect-funcall x si live env)
(values 'FIXME:do-effect-funcall si #f))
;;;
(define (do-effect-appcall x si live env)
(values 'FIXME:do-effect-appcall si #f))
;;;
(define (do-effect-jmpcall x si live env)
(values 'FIXME:do-effect-jmpcall si #f))
;;;
(define (do-value-funcall x si live env)
(values 'FIXME:do-value-funcall si #f))
;;;
(define (do-value-appcall x si live env)
(values 'FIXME:do-value-appcall si #f))
;;;
(define (do-value-jmpcall x si live env)
(values 'FIXME:do-value-jmpcall si #f))
;;;
(define (do-mvcall x si live env k)
(values 'FIXME:do-mvcall si #t))
;;;
(define (Var x env)
(cond
[(assq x env) => cdr]
[else (error who "unbound var ~s" x)]))
;;;
(define (Primref x)
'FIXME:primref)
;;;
(define (Value x si live env)
(define (make-closure x)
(record-case x
[(constant t)
(values (make-move (constant-rep t) acr) 0 #f)]
[(var)
(values (make-move (Var x env) acr) 0 #f)]
[(primref)
(values (make-move (Primref x) acr) 0 #f)]
[(bind lhs* rhs* body)
(do-bind lhs* rhs* si live env env body Value)]
[(fix lhs* rhs* body)
(do-fix lhs* rhs* si live env body Value)]
[(conditional e0 e1 e2)
(do-cond e0 si live env e1 e2 Value)]
[(seq e0 e1) (do-seq e0 si live env e1 Value)]
[(closure label free*)
(values (do-closure label free* si live env) 0 #f)]
[(forcall) (do-forcall x si live env)]
[(funcall) (do-value-funcall x si live env)]
[(jmpcall) (do-value-jmpcall x si live env)]
[(appcall) (do-value-appcall x si live env)]
[(mvcall) (do-mvcall x si live env Value)]
[else (error who "invalid value expr ~s" x)]))
[(closure code free*)
(cond
[(null? free*) x]
[else
(make-prim 'make-closure
(list code (make-constant (length free*))))])]))
;;;
(define (Pred x si live env)
(record-case x
[(constant t)
(values (if t #t #f) 0 #f)]
[(var) (values (make-cmp 'neq (Var x env) false-object) 0 #f)]
[(primref) (values #t 0 #f)]
[(bind lhs* rhs* body)
(do-bind lhs* rhs* si live env env body Pred)]
[(fix lhs* rhs* body)
(do-fix lhs* rhs* si live env body Pred)]
[(conditional e0 e1 e2)
(do-cond e0 si live env e1 e2 Pred)]
[(seq e0 e1) (do-seq e0 si live env e1 Pred)]
[(closure label free*) (values #t 0 #f)]
[(forcall)
(let-values ([(x msi call?) (Value x si live env)])
(values (make-seq x (make-cmp 'neq acr false-object)) msi call?))]
[(funcall)
(let-values ([(x msi call?) (Value x si live env)])
(values (make-seq x (make-cmp 'neq acr false-object)) msi call?))]
[(jmpcall)
(let-values ([(x msi call?) (Value x si live env)])
(values (make-seq x (make-cmp 'neq acr false-object)) msi call?))]
[(appcall)
(let-values ([(x msi call?) (Value x si live env)])
(values (make-seq x (make-cmp 'neq acr false-object)) msi call?))]
[(mvcall) (do-mvcall x si live env Pred)]
[else (error who "invalid pred expr ~s" x)]))
(define (closure-sets var x)
(record-case x
[(closure code free*)
(let f ([i 0] [free* free*])
(cond
[(null? free*) (make-primcall 'void '())]
[else
(make-seq
(make-primcall 'closure-set!
(list var (make-constant i) (car free*)))
(f (fxadd1 i) (cdr free*)))]))]))
;;;
(define (Effect x si live env)
(record-case x
[(constant) (values 'nop 0 #f)]
[(var) (values 'nop 0 #f)]
[(primref) (values 'nop 0 #f)]
[(bind lhs* rhs* body)
(do-bind lhs* rhs* si live env env body Effect)]
[(fix lhs* rhs* body)
(do-fix lhs* rhs* si live env body Effect)]
[(conditional e0 e1 e2)
(do-cond e0 si live env e1 e2 Effect)]
[(seq e0 e1) (do-seq e0 si live env e1 Effect)]
[(closure label free*) (values 'nop 0 #f)]
[(forcall) (do-forcall x si live env)]
[(funcall) (do-effect-funcall x si live env)]
[(jmpcall) (do-effect-jmpcall x si live env)]
[(appcall) (do-effect-appcall x si live env)]
[(mvcall) (do-mvcall x si live env Tail)]
[else (error who "invalid effect expr ~s" x)]))
;;;
(define (Tail x si live env)
(record-case x
[(constant) (values x si #f)]
[(var) (values (Var x env) si #f)]
[(primref) (values x si #f)]
[(bind lhs* rhs* body)
(do-bind lhs* rhs* si live env env body Tail)]
[(fix lhs* rhs* body)
(do-fix lhs* rhs* si live env body Tail)]
[(conditional e0 e1 e2)
(do-cond e0 si live env e1 e2 Tail)]
[(seq e0 e1) (do-seq e0 si live env e1 Tail)]
[(closure label free*)
(values (do-closure label free* si live env) si #f)]
[(forcall)
(let-values ([(x msi call?) (do-forcall x si live env)])
(values x msi call?))]
[(funcall) (do-tail-funcall x si live env)]
[(jmpcall) (do-tail-jmpcall x si live env)]
[(appcall) (do-tail-appcall x si live env)]
[(mvcall) (do-mvcall x si live env Tail)]
[else (error who "invalid tail expr ~s" x)]))
;;;
(define (MainTail x si live env)
(let-values ([(x msi call?)
(Tail x si live env)])
(if call?
(make-seq 'FIXME:stack-overflow-check x)
x)))
(define (ClambdaCase free*)
(define (bind-free ls)
(let f ([ls ls] [i 0] [env '()])
(define (do-fix lhs* rhs* body)
(make-bind lhs*
(map make-closure rhs*)
(let f ([lhs* lhs*] [rhs* rhs*])
(cond
[(null? ls) env]
[(null? lhs*) body]
[else
(f (cdr ls) (fxadd1 i)
(cons (cons (car ls) (make-cpvar i)) env))])))
(define (do-info x env)
(record-case x
[(case-info label args proper)
(let f ([ls args] [env env] [si 0] [live '()])
(cond
[(null? ls) (values env si live)]
[else
(let ([fv (make-fvar si)])
(f (cdr ls)
(cons (cons (car ls) fv) env)
(fxadd1 si)
(cons si live)))]))]))
(let ([env (bind-free free*)])
(lambda (x)
(record-case x
[(clambda-case info body)
(let-values ([(env si live) (do-info info env)])
(make-clambda-case info (MainTail body si live env)))]
[else (error who "invalid clambda-case ~s" x)]))))
(make-seq
(closure-sets (car lhs*) (car rhs*))
(f (cdr lhs*) (cdr rhs*)))]))))
;;;
(define (Expr x)
(record-case x
[(constant) x]
[(var) x]
[(primref) x]
[(bind lhs* rhs* body)
(make-bind lhs* (map Expr rhs*) (Expr body))]
[(fix lhs* rhs* body)
(do-fix lhs* rhs* (Expr body))]
[(conditional e0 e1 e2)
(make-conditional (Expr e0) (Expr e1) (Expr e2))]
[(seq e0 e1)
(make-seq (Expr e0) (Expr e1))]
[(closure)
(let ([t (unique-var 'tmp)])
(Expr (make-fix (list t) (list x) t)))]
[(primcall op arg*)
(make-appcall (make-primref op) (map Expr arg*))]
[(forcall op arg*)
(make-forcall op (map Expr arg*))]
[(funcall rator arg*)
(make-funcall (Expr rator) (map Expr arg*))]
[(jmpcall label rator arg*)
(make-jmpcall label (Expr rator) (map Expr arg*))]
[(appcall rator arg*)
(error who "appcall not supported yet")
(make-appcall (Expr rator) (map Expr arg*))]
[(mvcall rator k)
(make-mvcall (Expr rator) (Clambda k))]
[else (error who "invalid expr ~s" x)]))
;;;
(define (ClambdaCase x)
(record-case x
[(clambda-case info body)
(make-clambda-case info (Expr body))]
[else (error who "invalid clambda-case ~s" x)]))
;;;
(define (Clambda x)
(record-case x
[(clambda label case* free*)
(make-clambda label (map (ClambdaCase free*) case*) free*)]
(make-clambda label (map ClambdaCase case*) free*)]
[else (error who "invalid clambda ~s" x)]))
;;;
(define (Program x)
(record-case x
[(codes code* body)
(make-codes (map Clambda code*) (MainTail body 0 '() '()))]
(make-codes (map Clambda code*) (Expr body))]
[else (error who "invalid program ~s" x)]))
;;;
(Program x))
(define (specify-representation x)
(define who 'specify-representation)
;;;
(define nop (make-primcall 'nop '()))
;;;
(define (constant-rep x)
(let ([c (constant-value x)])
(cond
[(fixnum? c) (* c fixnum-scale)]
[(boolean? c) (if c bool-t bool-f)]
[(void? c) void-object]
[(bwp? c) bwp-object]
[(char? c) (fxlogor (fxsll (char->integer c) char-shift)
char-tag)]
[(null? c) nil]
[else x])))
;;;
(define (Effect x)
(record-case x
[(constant c) nop]
[(var) nop]
[(primref) nop]
[(closure code free*) nop]
[(bind lhs* rhs* body)
(make-bind lhs* (map Value rhs*) (Effect body))]
[(conditional e0 e1 e2)
(make-conditional (Pred e0) (Effect e1) (Effect e2))]
[(seq e0 e1)
(make-seq (Effect e0) (Effect e1))]
[(primcall op arg*)
(error who "effect prim ~a not supported" op)]
[(forcall op arg*)
(error who "effect forcall not supported" op)]
[(funcall rator arg*)
(make-funcall (Value rator) (map Value arg*))]
[(jmpcall label rator arg*)
(make-jmpcall label (Value rator) (map Value arg*))]
[(appcall rator arg*)
(error who "appcall not supported yet")]
[(mvcall rator x)
(make-mvcall (Value rator) (Clambda x Effect))]
[else (error who "invalid pred expr ~s" x)]))
;;;
(define (Pred x)
(record-case x
[(constant c) (if c #t #f)]
[(var) (mkprm '!= (list x bool-f))]
[(primref) #t]
[(closure code free*) #t]
[(bind lhs* rhs* body)
(make-bind lhs* (map Value rhs*) (Pred body))]
[(conditional e0 e1 e2)
(make-conditional (Pred e0) (Pred e1) (Pred e2))]
[(seq e0 e1)
(make-seq (Effect e0) (Pred e1))]
[(primcall op arg*)
(error who "pred prim ~a not supported" op)]
[(forcall op arg*)
(error who "pred forcall not supported" op)]
[(funcall rator arg*)
(mkprm '!=
(list (make-funcall (Value rator) (map Value arg*))
bool-f))]
[(jmpcall label rator arg*)
(mkprm '!=
(list (make-jmpcall label (Value rator) (map Value arg*))
bool-f))]
[(appcall rator arg*)
(error who "appcall not supported yet")]
[(mvcall rator x)
(make-mvcall (Value rator) (Clambda x Pred))]
[else (error who "invalid pred expr ~s" x)]))
;;;
(define (Value x)
(record-case x
[(constant) (constant-rep x)]
[(var) x]
[(primref) x]
[(bind lhs* rhs* body)
(make-bind lhs* (map Value rhs*) (Value body))]
[(conditional e0 e1 e2)
(make-conditional (Pred e0) (Value e1) (Value e2))]
[(seq e0 e1)
(make-seq (Effect e0) (Value e1))]
[(primcall op arg*)
(error who "value prim ~a not supported" op)]
[(forcall op arg*)
(error who "value forcall not supported" op)]
[(funcall rator arg*)
(make-funcall (Value rator) (map Value arg*))]
[(jmpcall label rator arg*)
(make-jmpcall label (Value rator) (map Value arg*))]
[(appcall rator arg*)
(error who "appcall not supported yet")]
[(mvcall rator x)
(make-mvcall (Value rator) (Clambda x Value))]
[else (error who "invalid value expr ~s" x)]))
;;;
(define (ClambdaCase x k)
(record-case x
[(clambda-case info body)
(make-clambda-case info (k body))]
[else (error who "invalid clambda-case ~s" x)]))
;;;
(define (Clambda x k)
(record-case x
[(clambda label case* free*)
(make-clambda label
(map (lambda (x) (ClambdaCase x k)) case*)
free*)]
[else (error who "invalid clambda ~s" x)]))
;;;
(define (Program x)
(record-case x
[(codes code* body)
(make-codes
(map (lambda (x) (Clambda x Value)) code*)
(Value body))]
[else (error who "invalid program ~s" x)]))
;;;
(Program x))
@ -534,11 +413,12 @@
(define (new-cogen x)
(verify-new-cogen-input x)
(let ([x (remove-primcalls x)])
(new-cogen-pass1 x)))
(let* ([x (remove-primcalls x)]
[x (eliminate-fix x)]
[x (specify-representation x)])
x))

View File

@ -263,7 +263,7 @@
(define label-name
(lambda (x) (cadr x)))
(define int? fixnum?)
(define int? integer?)
(define obj?
(lambda (x)

153
src/racompiler.ss Executable file
View File

@ -0,0 +1,153 @@
#!/usr/bin/env ikarus --script
(define (racompile x)
;;;
(define-syntax record-case
(lambda (x)
(define (enumerate fld* i)
(syntax-case fld* ()
[() #'()]
[(x . x*)
(with-syntax ([i i] [i* (enumerate #'x* (fx+ i 1))])
#'(i . i*))]))
(define (generate-body ctxt cls*)
(syntax-case cls* (else)
[() (with-syntax ([x x]) #'(error #f "unmatched ~s in ~s" v #'x))]
[([else b b* ...]) #'(begin b b* ...)]
[([(rec-name rec-field* ...) b b* ...] . rest) (identifier? #'rec-name)
(with-syntax ([altern (generate-body ctxt #'rest)]
[(id* ...) (enumerate #'(rec-field* ...) 0)]
[rtd #'(type-descriptor rec-name)])
#'(if (#%$record/rtd? v rtd)
(let ([rec-field* (#%$record-ref v id*)] ...)
b b* ...)
altern))]))
(syntax-case x ()
[(_ expr cls* ...)
(with-syntax ([body (generate-body #'_ #'(cls* ...))])
#'(let ([v expr]) body))])))
;;;
(define-record constant (val))
(define (mkconst v) (make-constant v))
(define-record int (val))
(define (mkint v) (make-int v))
(define-record set (lhs rhs))
(define (mkset x v) (make-set x v))
(define-record reg (name))
(define (mkreg x) (make-reg x))
(define-record primcall (op rand*))
(define (mkprm op . rand*) (make-primcall op rand*))
(define-record seq (e0 e1))
(define (mkseq e0 e1) (make-seq e0 e1))
;;;
(define (recordize x)
(define who 'recordize)
;;;
(define (E x r)
(cond
[(pair? x)
(case (car x)
[(quote) (mkconst (cadr x))]
[else (error who "invalid expression ~s" x)])]
[else (error who "invalid expression ~s" x)]))
;;;
(E x '()))
;;;
(define (specify-representation x)
(define who 'specify-representation)
;;;
(define fixnum-scale 4)
;;;
(define (immediate? c)
(or (fixnum? c)))
;;;
(define (immediate-rep c)
(cond
[(fixnum? c) (mkint (* c fixnum-scale))]
[else (error 'immediate-rep "invalid ~s" c)]))
;;;
(define (Tail x)
(record-case x
[(constant c)
(if (immediate? c)
(immediate-rep c)
x)]
[else (error who "invalid tail ~s" x)]))
;;;
(Tail x))
;;;
(define (impose-calling-convention x)
(define who 'impose-calling-convention)
;;;
(define rv-register (mkreg '%eax))
;;;
(define (Tail x)
(record-case x
[(constant c)
(mkseq (mkset rv-register x)
(mkprm 'return rv-register))]
[else (error who "invalid tail ~s" x)]))
;;;
(Tail x))
;;;
(define (linearize x)
(define who 'linearize)
;;;
(define (op x)
(record-case x
[(register r) r]
[(constant c) `(obj ,c)]
[(int i) `(int ,i)]
;;;
(define (Effect x ac)
(record-case x
[(seq e0 e1)
(Effect e0 (Effect e1 ac))]
[(set targ v)
(cons `(movl ,(op v) ,(op targ)) ac)]
[else (error who "invalid effect ~s" x)]))
;;;
(define (Tail x ac)
(record-case x
[(seq e0 e1)
(Effect e0 (Tail e1 ac))]
[(primcall op rands)
(case op
[(return)
(cons '(ret) ac)]
[else (error who "invalid tail prim ~s" op)])]
[else (error who "invalid tail ~s" x)]))
;;;
(list (Tail x '())))
;;;
(define (compile x)
(let* ([x (expand x)]
[x (recordize x)]
[x (specify-representation x)]
[x (impose-calling-convention x)]
[x* (linearize x)]
[code (car (#%list*->code*
(lambda (x) #f)
x*))])
((#%$code->closure code))))
(compile x))
(define-syntax add-tests-with-string-output
(syntax-rules (=>)
[(_ name [expr* => str*] ...)
(begin
(printf "SECTION ~a ...\n" 'name)
(let ([str str*]
[expr 'expr*])
(printf "testing ~s\n" expr)
(let ([r (with-output-to-string
(lambda ()
(write (racompile expr))
(newline)))])
(unless (string=? r str)
(error #f "expected ~s, got ~s\n" str r))))
...)]))
(load "tests/tests-1.1-req.scm")