ikarus/scheme/ikarus.compiler.ss

3013 lines
106 KiB
Scheme
Raw Normal View History

;;; Ikarus Scheme -- A compiler for R6RS Scheme.
;;; Copyright (C) 2006,2007,2008 Abdulaziz Ghuloum
;;;
;;; This program is free software: you can redistribute it and/or modify
;;; it under the terms of the GNU General Public License version 3 as
;;; published by the Free Software Foundation.
;;;
;;; This program is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;;; General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with this program. If not, see <http://www.gnu.org/licenses/>.
2006-11-23 19:44:29 -05:00
2008-02-14 17:45:15 -05:00
(library (ikarus.compiler)
(export compile-core-expr-to-port optimize-level
assembler-output scc-letrec optimize-cp
current-primitive-locations eval-core
compile-core-expr)
(import
(rnrs hashtables)
(ikarus system $fx)
(ikarus system $pairs)
(only (ikarus system $codes) $code->closure)
(only (ikarus system $structs) $struct-ref $struct/rtd?)
(except (ikarus)
optimize-level
fasl-write scc-letrec optimize-cp
compile-core-expr-to-port assembler-output
current-primitive-locations eval-core)
2008-02-14 17:45:15 -05:00
(ikarus.fasl.write)
(ikarus.intel-assembler))
2007-05-01 04:37:35 -04:00
(define-syntax struct-case
2006-11-23 19:44:29 -05:00
(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 " 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 ($struct/rtd? v rtd)
(let ([rec-field* ($struct-ref v id*)] ...)
b b* ...)
altern))]))
2006-11-23 19:44:29 -05:00
(syntax-case x ()
[(_ expr cls* ...)
(with-syntax ([body (generate-body #'_ #'(cls* ...))])
#'(let ([v expr]) body))])))
2006-11-23 19:44:29 -05:00
(define (remq1 x ls)
(cond
[(null? ls) '()]
[(eq? x (car ls)) (cdr ls)]
[else
(let ([t (remq1 x (cdr ls))])
(cond
[(eq? t (cdr ls)) ls]
[else (cons (car ls) t)]))]))
(define (singleton x) (list x))
(define (union s1 s2)
(define (add* s1 s2)
(cond
[(null? s1) s2]
[else (add (car s1) (add* (cdr s1) s2))]))
(define (add x s)
(cond
[(memq x s) s]
[else (cons x s)]))
(cond
[(null? s1) s2]
[(null? s2) s1]
[else (add* s1 s2)]))
(define (difference s1 s2)
(define (rem* s1 s2)
(cond
[(null? s1) s2]
[else (remq1 (car s1) (rem* (cdr s1) s2))]))
(cond
[(null? s1) '()]
[(null? s2) s1]
[else (rem* s2 s1)]))
2006-11-23 19:44:29 -05:00
(define-struct constant (value))
(define-struct code-loc (label))
(define-struct foreign-label (label))
(define-struct var
(name assigned referenced
reg-conf frm-conf var-conf reg-move frm-move var-move
loc index global-loc))
(define-struct cp-var (idx))
(define-struct frame-var (idx))
(define-struct new-frame (base-idx size body))
(define-struct save-cp (loc))
(define-struct eval-cp (check body))
(define-struct return (value))
(define-struct call-cp
(call-convention label save-cp? rp-convention base-idx arg-count live-mask))
(define-struct tailcall-cp (convention label arg-count))
(define-struct primcall (op arg*))
(define-struct primref (name))
(define-struct conditional (test conseq altern))
(define-struct interrupt-call (test handler))
(define-struct bind (lhs* rhs* body))
(define-struct recbind (lhs* rhs* body))
(define-struct rec*bind (lhs* rhs* body))
(define-struct fix (lhs* rhs* body))
(define-struct seq (e0 e1))
(define-struct case-info (label args proper))
(define-struct clambda-case (info body))
(define-struct clambda (label cases cp free name))
(define-struct closure (code free* well-known?))
(define-struct funcall (op rand*))
(define-struct jmpcall (label op rand*))
(define-struct forcall (op rand*))
(define-struct codes (list body))
(define-struct assign (lhs rhs))
(define-struct mvcall (producer consumer))
(define-struct known (expr type value))
(define-struct shortcut (body handler))
(define-struct fvar (idx))
(define-struct object (val))
(define-struct locals (vars body))
(define-struct nframe (vars live body))
(define-struct nfv (conf loc var-conf frm-conf nfv-conf))
(define-struct ntcall (target value args mask size))
(define-struct asm-instr (op dst src))
(define-struct disp (s0 s1))
2007-02-11 04:12:09 -05:00
(define mkfvar
(let ([cache '()])
(lambda (i)
(cond
[(fixnum? i)
(cond
[(assv i cache) => cdr]
[else
(let ([fv (make-fvar i)])
(set! cache (cons (cons i fv) cache))
fv)])]
[else (error 'mkfvar "not a fixnum" i)]))))
2006-11-23 19:44:29 -05:00
(define (unique-var x)
(make-var (gensym x) #f #f #f #f #f #f #f #f #f #f #f))
2006-11-23 19:44:29 -05:00
(define (recordize x)
(define *cookie* (gensym))
2006-11-23 19:44:29 -05:00
(define (gen-fml* fml*)
(cond
[(pair? fml*)
(let ([v (unique-var (car fml*))])
(putprop (car fml*) *cookie* v)
(cons v (gen-fml* (cdr fml*))))]
2006-11-23 19:44:29 -05:00
[(symbol? fml*)
(let ([v (unique-var fml*)])
(putprop fml* *cookie* v)
v)]
2006-11-23 19:44:29 -05:00
[else '()]))
(define (ungen-fml* fml*)
(cond
[(pair? fml*)
(remprop (car fml*) *cookie*)
(ungen-fml* (cdr fml*))]
[(symbol? fml*)
(remprop fml* *cookie*)]))
2006-11-23 19:44:29 -05:00
(define (properize fml*)
(cond
[(pair? fml*)
(cons (car fml*) (properize (cdr fml*)))]
[(null? fml*) '()]
[else (list fml*)]))
(define (quoted-sym x)
(if (and (list? x)
(fx= (length x) 2)
(eq? 'quote (car x))
(symbol? (cadr x)))
(cadr x)
(error 'quoted-sym "not a quoted symbol" x)))
(define (quoted-string x)
2006-11-23 19:44:29 -05:00
(if (and (list? x)
(fx= (length x) 2)
(eq? 'quote (car x))
(string? (cadr x)))
(cadr x)
(error 'quoted-string "not a quoted string" x)))
(define (Var x)
(or (getprop x *cookie*)
(error 'recordize "unbound" x)))
(define (lexical x)
(getprop x *cookie*))
(define (get-fmls x args)
(define (matching? fmls args)
(cond
[(null? fmls) (null? args)]
[(pair? fmls) (and (pair? args) (matching? (cdr fmls) (cdr args)))]
[else #t]))
(cond
[(and (pair? x) (eq? (car x) 'case-lambda))
(let f ([cls* (cdr x)])
(cond
[(null? cls*) '()]
[(matching? (caar cls*) args)
(caar cls*)]
[else (f (cdr cls*))]))]
[else '()]))
(define (make-global-set! lhs rhs)
(make-funcall (make-primref '$init-symbol-value!)
(list (make-constant lhs) rhs)))
(define (E x ctxt)
2006-11-23 19:44:29 -05:00
(cond
[(pair? x)
(case (car x)
[(quote) (make-constant (cadr x))]
2006-11-23 19:44:29 -05:00
[(if)
(make-conditional
(E (cadr x) #f)
(E (caddr x) ctxt)
(E (cadddr x) ctxt))]
2006-11-23 19:44:29 -05:00
[(set!)
(let ([lhs (cadr x)] [rhs (caddr x)])
(cond
[(lexical lhs) =>
(lambda (var)
(make-assign var (E rhs lhs)))]
[else (make-global-set! lhs (E rhs lhs))]))]
2006-11-23 19:44:29 -05:00
[(begin)
(let f ([a (cadr x)] [d (cddr x)])
2006-11-23 19:44:29 -05:00
(cond
[(null? d) (E a ctxt)]
2006-12-06 21:39:13 -05:00
[else
(make-seq (E a #f) (f (car d) (cdr d)))]))]
2006-11-23 19:44:29 -05:00
[(letrec)
(let ([bind* (cadr x)] [body (caddr x)])
(let ([lhs* (map car bind*)]
2006-11-23 19:44:29 -05:00
[rhs* (map cadr bind*)])
(let ([nlhs* (gen-fml* lhs*)])
(let ([expr (make-recbind nlhs* (map E rhs* lhs*) (E body ctxt))])
(ungen-fml* lhs*)
expr))))]
[(letrec*)
(let ([bind* (cadr x)] [body (caddr x)])
(let ([lhs* (map car bind*)]
[rhs* (map cadr bind*)])
(let ([nlhs* (gen-fml* lhs*)])
(let ([expr (make-rec*bind nlhs* (map E rhs* lhs*) (E body ctxt))])
(ungen-fml* lhs*)
expr))))]
[(library-letrec*)
(let ([bind* (cadr x)] [body (caddr x)])
(let ([lhs* (map car bind*)]
[loc* (map cadr bind*)]
[rhs* (map caddr bind*)])
(let ([nlhs* (gen-fml* lhs*)])
(for-each
(lambda (lhs loc)
(set-var-global-loc! lhs loc))
nlhs* loc*)
(let ([expr (make-rec*bind nlhs* (map E rhs* lhs*)
(let f ([lhs* nlhs*] [loc* loc*])
(cond
[(null? lhs*) (E body ctxt)]
[(not (car loc*)) (f (cdr lhs*) (cdr loc*))]
[else
(make-seq
2008-02-10 05:24:16 -05:00
(make-constant #f)
;(make-global-set! (car loc*) (car lhs*))
(f (cdr lhs*) (cdr loc*)))])))])
(ungen-fml* lhs*)
expr))))]
2006-11-23 19:44:29 -05:00
[(case-lambda)
(let ([cls*
(map
(lambda (cls)
(let ([fml* (car cls)] [body (cadr cls)])
(let ([nfml* (gen-fml* fml*)])
(let ([body (E body #f)])
(ungen-fml* fml*)
2006-11-23 19:44:29 -05:00
(make-clambda-case
2006-12-04 19:58:24 -05:00
(make-case-info
2006-12-04 20:13:21 -05:00
(gensym)
2006-12-04 19:58:24 -05:00
(properize nfml*)
(list? fml*))
2006-11-23 19:44:29 -05:00
body)))))
(cdr x))])
(make-clambda (gensym) cls* #f #f ctxt))]
[(lambda)
(E `(case-lambda ,(cdr x)) ctxt)]
2006-11-23 19:44:29 -05:00
[(foreign-call)
(let ([name (quoted-string (cadr x))] [arg* (cddr x)])
(make-forcall name (map (lambda (x) (E x #f)) arg*)))]
[(primitive)
(let ([var (cadr x)])
(make-primref var))]
2006-11-23 19:44:29 -05:00
[else
(let ([names (get-fmls (car x) (cdr x))])
(make-funcall
(E (car x) #f)
(let f ([arg* (cdr x)] [names names])
(cond
[(pair? names)
(cons
(E (car arg*) (car names))
(f (cdr arg*) (cdr names)))]
[else
(map (lambda (x) (E x #f)) arg*)]))))])]
[(symbol? x)
(or (lexical x)
(make-funcall
(make-primref 'top-level-value)
(list (make-constant x))))]
[else (error 'recordize "invalid expression" x)]))
(E x #f))
2006-11-23 19:44:29 -05:00
(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)
(struct-case x
2006-11-23 19:44:29 -05:00
[(constant c) `(quote ,c)]
[(code-loc x) `(code-loc ,x)]
[(var x) (string->symbol (format "v:~a" x))]
[(primref x) x]
[(conditional test conseq altern)
`(if ,(E test) ,(E conseq) ,(E altern))]
2006-12-21 09:49:30 -05:00
[(interrupt-call e0 e1)
`(interrupt-call ,(E e0) ,(E e1))]
2006-11-23 19:44:29 -05:00
[(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))]
[(recbind lhs* rhs* body)
`(letrec ,(map (lambda (lhs rhs) (list (E lhs) (E rhs))) lhs* rhs*)
,(E body))]
[(rec*bind lhs* rhs* body)
`(letrec* ,(map (lambda (lhs rhs) (list (E lhs) (E rhs))) lhs* rhs*)
,(E body))]
;[(library-recbind lhs* loc* rhs* body)
; `(letrec ,(map (lambda (lhs loc rhs) (list (E lhs) loc (E rhs)))
; lhs* loc* rhs*)
; ,(E body))]
2006-11-23 19:44:29 -05:00
[(fix lhs* rhs* body)
`(fix ,(map (lambda (lhs rhs) (list (E lhs) (E rhs))) lhs* rhs*)
,(E body))]
[(seq e0 e1)
(let ()
(define (f x ac)
(struct-case x
[(seq e0 e1) (f e0 (f e1 ac))]
[else (cons (E x) ac)]))
(cons 'begin (f e0 (f e1 '()))))]
2006-12-04 19:58:24 -05:00
[(clambda-case info body)
`(label: ,(case-info-label info)
,(E-args (case-info-proper info) (case-info-args info))
,(E body))]
[(clambda g cls* cp free)
`(clambda (label: ,g cp: ,(E cp) ) ;free: ,(map E free))
,@(map E cls*))]
2006-12-04 19:05:02 -05:00
[(clambda label clauses free)
2006-11-23 19:44:29 -05:00
`(code ,label . ,(map E clauses))]
[(closure code free* wk?)
`(closure ,@(if wk? '(wk) '()) ,(E code) ,(map E free*))]
2006-11-23 19:44:29 -05:00
[(codes list body)
`(codes ,(map E list)
,(E body))]
[(funcall rator rand*) `(funcall ,(E rator) . ,(map E rand*))]
2006-12-04 22:05:44 -05:00
[(jmpcall label rator rand*)
`(jmpcall ,label ,(E rator) . ,(map E rand*))]
2006-11-23 19:44:29 -05:00
[(forcall rator rand*) `(foreign-call ,rator . ,(map E rand*))]
[(assign lhs rhs) `(set! ,(E lhs) ,(E rhs))]
[(return x) `(return ,(E x))]
[(new-frame base-idx size body)
`(new-frame [base: ,base-idx]
[size: ,size]
,(E body))]
[(frame-var idx)
(string->symbol (format "fv.~a" idx))]
[(cp-var idx)
(string->symbol (format "cp.~a" idx))]
[(save-cp expr)
`(save-cp ,(E expr))]
[(eval-cp check body)
`(eval-cp ,check ,(E body))]
[(call-cp call-convention label save-cp? rp-convention base-idx arg-count live-mask)
2006-11-23 19:44:29 -05:00
`(call-cp [conv: ,call-convention]
2006-12-04 22:05:44 -05:00
[label: ,label]
[rpconv: ,(if (symbol? rp-convention)
rp-convention
(E rp-convention))]
2006-11-23 19:44:29 -05:00
[base-idx: ,base-idx]
[arg-count: ,arg-count]
[live-mask: ,live-mask])]
[(tailcall-cp convention label arg-count)
`(tailcall-cp ,convention ,label ,arg-count)]
2006-11-23 19:44:29 -05:00
[(foreign-label x) `(foreign-label ,x)]
[(mvcall prod cons) `(mvcall ,(E prod) ,(E cons))]
[(fvar idx) (string->symbol (format "fv.~a" idx))]
[(nfv idx) 'nfv]
[(locals vars body) `(locals ,(map E vars) ,(E body))]
[(asm-instr op d s)
`(asm ,op ,(E d) ,(E s))]
2007-02-17 19:22:14 -05:00
[(disp s0 s1)
`(disp ,(E s0) ,(E s1))]
[(nframe vars live body) `(nframe ;[vars: ,(map E vars)]
;[live: ,(map E live)]
,(E body))]
[(shortcut body handler)
`(shortcut ,(E body) ,(E handler))]
[(ntcall target valuw args mask size)
`(ntcall ,target ,size)]
[else
(if (symbol? x)
x
"#<unknown>")]))
2006-11-23 19:44:29 -05:00
(E x))
(define open-mvcalls (make-parameter #t))
2006-11-23 19:44:29 -05:00
(define (optimize-direct-calls x)
(define who 'optimize-direct-calls)
(define (make-conses ls)
(cond
[(null? ls) (make-constant '())]
[else
2007-06-05 20:11:12 -04:00
(make-funcall (make-primref 'cons)
2006-11-23 19:44:29 -05:00
(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-case cls rand*)
(struct-case cls
2006-12-04 19:58:24 -05:00
[(clambda-case info body)
(struct-case info
2006-12-04 20:13:21 -05:00
[(case-info label fml* proper)
2006-12-04 19:58:24 -05:00
(if proper
(and (fx= (length fml*) (length rand*))
(make-bind fml* rand* body))
(and (fx<= (length fml*) (length rand*))
(make-bind fml* (properize fml* rand*) body)))])]))
2006-11-23 19:44:29 -05:00
(define (try-inline cls* rand* default)
(cond
[(null? cls*) default]
[(inline-case (car cls*) rand*)]
[else (try-inline (cdr cls*) rand* default)]))
(define (inline rator rand*)
(define (valid-mv-consumer? x)
(struct-case x
[(clambda L cases F)
(and (fx= (length cases) 1)
(struct-case (car cases)
[(clambda-case info body)
(struct-case info
[(case-info L args proper) proper])]))]
[else #f]))
(define (single-value-consumer? x)
(struct-case x
[(clambda L cases F)
(and (fx= (length cases) 1)
(struct-case (car cases)
[(clambda-case info body)
(struct-case info
[(case-info L args proper)
(and proper (fx= (length args) 1))])]))]
[else #f]))
(define (valid-mv-producer? x)
(struct-case x
[(funcall) #t]
[(conditional) #f]
[(bind lhs* rhs* body) (valid-mv-producer? body)]
[else #f] ;; FIXME BUG
))
(struct-case rator
[(clambda g cls*)
2006-11-23 19:44:29 -05:00
(try-inline cls* rand*
(make-funcall rator rand*))]
[(primref op)
(case op
;;; FIXME HERE
[(call-with-values)
(cond
[(and (open-mvcalls) (fx= (length rand*) 2))
(let ([producer (inline (car rand*) '())]
[consumer (cadr rand*)])
(cond
[(single-value-consumer? consumer)
(inline consumer (list producer))]
[(and (valid-mv-consumer? consumer)
(valid-mv-producer? producer))
(make-mvcall producer consumer)]
[else
(make-funcall rator rand*)]))]
[else
(make-funcall rator rand*)])]
[else
(make-funcall rator rand*)])]
[(bind lhs* rhs* body)
(if (null? lhs*)
(inline body rand*)
(make-bind lhs* rhs*
(call-expr body rand*)))]
[(recbind lhs* rhs* body)
(if (null? lhs*)
(inline body rand*)
(make-recbind lhs* rhs*
(call-expr body rand*)))]
[(rec*bind lhs* rhs* body)
(if (null? lhs*)
(inline body rand*)
(make-rec*bind lhs* rhs*
(call-expr body rand*)))]
2006-11-23 19:44:29 -05:00
[else (make-funcall rator rand*)]))
(define (call-expr x rand*)
(cond
[(clambda? x) (inline x rand*)]
[(and (var? x) (not (var-assigned x)))
;;; FIXME: did we do the analysis yet?
(make-funcall x rand*)]
[else
(let ([t (unique-var 'tmp)])
(make-bind (list t) (list x)
(make-funcall t rand*)))]))
2006-11-23 19:44:29 -05:00
(define (Expr x)
(struct-case x
2006-11-23 19:44:29 -05:00
[(constant) x]
[(var) x]
[(primref) x]
[(bind lhs* rhs* body)
(make-bind lhs* (map Expr rhs*) (Expr body))]
[(recbind lhs* rhs* body)
(make-recbind lhs* (map Expr rhs*) (Expr body))]
[(rec*bind lhs* rhs* body)
(make-rec*bind lhs* (map Expr rhs*) (Expr body))]
2006-11-23 19:44:29 -05:00
[(conditional test conseq altern)
(make-conditional
(Expr test)
(Expr conseq)
(Expr altern))]
[(seq e0 e1)
(make-seq (Expr e0) (Expr e1))]
[(clambda g cls* cp free name)
(make-clambda g
2006-11-23 19:44:29 -05:00
(map (lambda (x)
(struct-case x
2006-12-04 19:58:24 -05:00
[(clambda-case info body)
(make-clambda-case info (Expr body))]))
2006-12-04 19:05:02 -05:00
cls*)
cp free name)]
2006-11-23 19:44:29 -05:00
[(funcall rator rand*)
(inline (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" (unparse x))]))
2006-11-23 19:44:29 -05:00
(Expr x))
(define simple-primitives
;;; primitives that are side-effect-free
;;; FIXME: surely something must go here, no?
'())
(define complex-count 0)
2006-11-23 19:44:29 -05:00
(define (optimize-letrec x)
(define who 'optimize-letrec)
(define (extend-hash lhs* h ref)
(for-each (lambda (lhs) (hashtable-set! h lhs #t)) lhs*)
2006-11-23 19:44:29 -05:00
(lambda (x)
(unless (hashtable-ref h x #f)
(hashtable-set! h x #t)
2006-11-23 19:44:29 -05:00
(ref x))))
(define (E* x* ref comp)
(cond
[(null? x*) '()]
[else
(cons (E (car x*) ref comp)
(E* (cdr x*) ref comp))]))
(define (do-rhs* i lhs* rhs* ref comp vref vcomp)
(cond
[(null? rhs*) '()]
[else
(let ([h (make-eq-hashtable)]
[rest (do-rhs* (fxadd1 i) lhs* (cdr rhs*) ref comp vref vcomp)])
(let ([ref
(lambda (x)
(unless (hashtable-ref h x #f)
(hashtable-set! h x #t)
(ref x)
(when (memq x lhs*)
(vector-set! vref i #t))))]
[comp
(lambda ()
(vector-set! vcomp i #t)
(comp))])
(cons (E (car rhs*) ref comp) rest)))]))
2006-11-23 19:44:29 -05:00
(define (partition-rhs* i lhs* rhs* vref vcomp)
(cond
[(null? lhs*) (values '() '() '() '() '() '())]
[else
(let-values
([(slhs* srhs* llhs* lrhs* clhs* crhs*)
(partition-rhs* (fxadd1 i) (cdr lhs*) (cdr rhs*) vref vcomp)]
[(lhs rhs) (values (car lhs*) (car rhs*))])
(cond
[(var-assigned lhs)
(values slhs* srhs* llhs* lrhs* (cons lhs clhs*) (cons rhs crhs*))]
[(clambda? rhs)
(values slhs* srhs* (cons lhs llhs*) (cons rhs lrhs*) clhs* crhs*)]
[(or (vector-ref vref i) (vector-ref vcomp i))
(values slhs* srhs* llhs* lrhs* (cons lhs clhs*) (cons rhs crhs*))]
[else
(values (cons lhs slhs*) (cons rhs srhs*) llhs* lrhs* clhs* crhs*)]
))]))
(define (do-recbind lhs* rhs* body ref comp letrec?)
(let ([h (make-eq-hashtable)]
2006-11-23 19:44:29 -05:00
[vref (make-vector (length lhs*) #f)]
[vcomp (make-vector (length lhs*) #f)])
(let* ([ref (extend-hash lhs* h ref)]
[body (E body ref comp)])
(let ([rhs* (do-rhs* 0 lhs* rhs* ref comp vref vcomp)])
(let-values ([(slhs* srhs* llhs* lrhs* clhs* crhs*)
(partition-rhs* 0 lhs* rhs* vref vcomp)])
;;; (let ([made-complex
;;; (filter (lambda (x) (not (var-assigned x)))
;;; clhs*)])
;;; (unless (null? made-complex)
;;; (set! complex-count
;;; (+ complex-count (length made-complex)))
;;; (printf "COMPLEX (~s) = ~s\n"
;;; complex-count
;;; (map unparse made-complex))))
(let ([void* (map (lambda (x) (make-constant (void))) clhs*)])
(make-bind slhs* srhs*
(make-bind clhs* void*
(make-fix llhs* lrhs*
(if letrec?
(let ([t* (map (lambda (x) (unique-var 'tmp)) clhs*)])
(make-bind t* crhs*
(build-assign* clhs* t* body)))
(build-assign* clhs* crhs* body)))))))))))
2006-11-23 19:44:29 -05:00
(define (build-assign* lhs* rhs* body)
(cond
[(null? lhs*) body]
2006-11-23 19:44:29 -05:00
[else
(make-seq
(make-assign (car lhs*) (car rhs*))
(build-assign* (cdr lhs*) (cdr rhs*) body))]))
(define (E x ref comp)
(struct-case x
2006-11-23 19:44:29 -05:00
[(constant) x]
[(var) (ref x) x]
[(assign lhs rhs)
(set-var-assigned! lhs #t)
(ref lhs)
(comp)
2006-11-23 19:44:29 -05:00
(make-assign lhs (E rhs ref comp))]
[(primref) x]
[(bind lhs* rhs* body)
(let ([rhs* (E* rhs* ref comp)])
(let ([h (make-eq-hashtable)])
2006-11-23 19:44:29 -05:00
(let ([body (E body (extend-hash lhs* h ref) comp)])
(make-bind lhs* rhs* body))))]
[(recbind lhs* rhs* body)
(if (null? lhs*)
(E body ref comp)
(do-recbind lhs* rhs* body ref comp #t))]
[(rec*bind lhs* rhs* body)
(if (null? lhs*)
(E body ref comp)
(do-recbind lhs* rhs* body ref comp #f))]
2006-11-23 19:44:29 -05:00
[(conditional e0 e1 e2)
(make-conditional (E e0 ref comp) (E e1 ref comp) (E e2 ref comp))]
[(seq e0 e1) (make-seq (E e0 ref comp) (E e1 ref comp))]
[(clambda g cls* cp free name)
(make-clambda g
2006-11-23 19:44:29 -05:00
(map (lambda (x)
(struct-case x
2006-12-04 19:58:24 -05:00
[(clambda-case info body)
(let ([h (make-eq-hashtable)])
2006-12-04 19:58:24 -05:00
(let ([body (E body (extend-hash (case-info-args info) h ref) void)])
(make-clambda-case info body)))]))
2006-12-04 19:05:02 -05:00
cls*)
cp free name)]
2006-11-23 19:44:29 -05:00
[(funcall rator rand*)
(let ([rator (E rator ref comp)] [rand* (E* rand* ref comp)])
(struct-case rator
2006-11-23 19:44:29 -05:00
[(primref op)
(unless (memq op simple-primitives)
2006-11-23 19:44:29 -05:00
(comp))]
[else
(comp)])
(make-funcall rator rand*))]
[(mvcall p c)
(let ([p (E p ref comp)] [c (E c ref comp)])
(comp)
(make-mvcall p c))]
2006-11-23 19:44:29 -05:00
[(forcall rator rand*)
(make-forcall rator (E* rand* ref comp))]
[else (error who "invalid expression" (unparse x))]))
(E x (lambda (x) (error who "free var found" x))
2006-11-23 19:44:29 -05:00
void))
#|
(letrec* (bi ...
[x (let ([lhs* rhs*] ...) body)]
bj ...)
body)
===?
(letrec* (bi ...
[tmp* rhs*] ...
[lhs* tmp*] ...
[x body]
bj ...)
body)
|#
2006-11-23 19:44:29 -05:00
2008-03-23 04:14:53 -04:00
2008-02-17 04:08:38 -05:00
(define scc-letrec (make-parameter #t))
(define (optimize-letrec/scc x)
(define who 'optimize-letrec/scc)
(module (get-sccs-in-order)
(define-struct node (data link* lowlink root done collection))
(define (create-graph v* e** data*)
(define h (make-eq-hashtable))
(let ([v*
(let f ([v* v*] [data* data*])
(cond
[(null? v*) '()]
[else
(let ([node (make-node (car data*) '() #f #f #f #f)])
(hashtable-set! h (car v*) node)