1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-18 10:10:23 +02:00

Source information goes on the $continue, not the $cont.

* module/language/cps.scm ($continue, $cont): Put source information on
  the $continue, not on the $cont.  Otherwise it is difficult for CPS
  conversion to preserve source information.
  ($fun): Add a src member to $fun.  Otherwise we might miss the source
  info for the start of the function.

* .dir-locals.el:
* module/language/cps/arities.scm:
* module/language/cps/closure-conversion.scm:
* module/language/cps/compile-rtl.scm:
* module/language/cps/constructors.scm:
* module/language/cps/contification.scm:
* module/language/cps/dfg.scm:
* module/language/cps/elide-values.scm:
* module/language/cps/reify-primitives.scm:
* module/language/cps/slot-allocation.scm:
* module/language/cps/verify.scm:
* module/language/tree-il/compile-cps.scm: Update the whole CPS world
  for this change.
This commit is contained in:
Andy Wingo 2013-11-07 10:32:21 +01:00
parent 963d95f1d9
commit 6e422a3599
13 changed files with 767 additions and 784 deletions

View file

@ -21,7 +21,7 @@
(eval . (put '$letk 'scheme-indent-function 1)) (eval . (put '$letk 'scheme-indent-function 1))
(eval . (put '$letk* 'scheme-indent-function 1)) (eval . (put '$letk* 'scheme-indent-function 1))
(eval . (put '$letconst 'scheme-indent-function 1)) (eval . (put '$letconst 'scheme-indent-function 1))
(eval . (put '$continue 'scheme-indent-function 1)) (eval . (put '$continue 'scheme-indent-function 2))
(eval . (put '$kargs 'scheme-indent-function 2)) (eval . (put '$kargs 'scheme-indent-function 2))
(eval . (put '$kentry 'scheme-indent-function 2)) (eval . (put '$kentry 'scheme-indent-function 2))
(eval . (put '$kclause 'scheme-indent-function 1)) (eval . (put '$kclause 'scheme-indent-function 1))

View file

@ -25,15 +25,15 @@
;;; and terms that call continuations. ;;; and terms that call continuations.
;;; ;;;
;;; $letk binds a set of mutually recursive continuations, each one an ;;; $letk binds a set of mutually recursive continuations, each one an
;;; instance of $cont. A $cont declares the name and source of a ;;; instance of $cont. A $cont declares the name of a continuation, and
;;; continuation, and then contains as a subterm the particular ;;; then contains as a subterm the particular continuation instance:
;;; continuation instance: $kif for test continuations, $kargs for ;;; $kif for test continuations, $kargs for continuations that bind
;;; continuations that bind values, etc. ;;; values, etc.
;;; ;;;
;;; $continue nodes call continuations. The expression contained in the ;;; $continue nodes call continuations. The expression contained in the
;;; $continue node determines the value or values that are passed to the ;;; $continue node determines the value or values that are passed to the
;;; target continuation: $const to pass a constant value, $values to ;;; target continuation: $const to pass a constant value, $values to
;;; pass multiple named values, etc. ;;; pass multiple named values, etc. $continue nodes also record the source at which
;;; ;;;
;;; Additionally there is $letrec, a term that binds mutually recursive ;;; Additionally there is $letrec, a term that binds mutually recursive
;;; functions. The contification pass will turn $letrec into $letk if ;;; functions. The contification pass will turn $letrec into $letk if
@ -71,8 +71,8 @@
;;; That's to say that a $fun can be matched like this: ;;; That's to say that a $fun can be matched like this:
;;; ;;;
;;; (match f ;;; (match f
;;; (($ $fun meta free ;;; (($ $fun src meta free
;;; ($ $cont kentry src ;;; ($ $cont kentry
;;; ($ $kentry self ($ $cont ktail _ ($ $ktail)) ;;; ($ $kentry self ($ $cont ktail _ ($ $ktail))
;;; (($ $kclause arity ;;; (($ $kclause arity
;;; ($ $cont kbody _ ($ $kargs names syms body))) ;;; ($ $cont kbody _ ($ $kargs names syms body)))
@ -165,11 +165,11 @@
;; Terms. ;; Terms.
(define-cps-type $letk conts body) (define-cps-type $letk conts body)
(define-cps-type $continue k exp) (define-cps-type $continue k src exp)
(define-cps-type $letrec names syms funs body) (define-cps-type $letrec names syms funs body)
;; Continuations ;; Continuations
(define-cps-type $cont k src cont) (define-cps-type $cont k cont)
(define-cps-type $kif kt kf) (define-cps-type $kif kt kf)
(define-cps-type $ktrunc arity k) (define-cps-type $ktrunc arity k)
(define-cps-type $kargs names syms body) (define-cps-type $kargs names syms body)
@ -182,7 +182,7 @@
(define-cps-type $void) (define-cps-type $void)
(define-cps-type $const val) (define-cps-type $const val)
(define-cps-type $prim name) (define-cps-type $prim name)
(define-cps-type $fun meta free body) (define-cps-type $fun src meta free body)
(define-cps-type $call proc args) (define-cps-type $call proc args)
(define-cps-type $primcall name args) (define-cps-type $primcall name args)
(define-cps-type $values args) (define-cps-type $values args)
@ -224,7 +224,7 @@
(define-syntax build-cps-cont (define-syntax build-cps-cont
(syntax-rules (unquote) (syntax-rules (unquote)
((_ (unquote exp)) exp) ((_ (unquote exp)) exp)
((_ (k src cont)) (make-$cont k src (build-cont-body cont))))) ((_ (k cont)) (make-$cont k (build-cont-body cont)))))
(define-syntax build-cps-exp (define-syntax build-cps-exp
(syntax-rules (unquote (syntax-rules (unquote
@ -234,7 +234,8 @@
((_ ($void)) (make-$void)) ((_ ($void)) (make-$void))
((_ ($const val)) (make-$const val)) ((_ ($const val)) (make-$const val))
((_ ($prim name)) (make-$prim name)) ((_ ($prim name)) (make-$prim name))
((_ ($fun meta free body)) (make-$fun meta free (build-cps-cont body))) ((_ ($fun src meta free body))
(make-$fun src meta free (build-cps-cont body)))
((_ ($call proc (arg ...))) (make-$call proc (list arg ...))) ((_ ($call proc (arg ...))) (make-$call proc (list arg ...)))
((_ ($call proc args)) (make-$call proc args)) ((_ ($call proc args)) (make-$call proc args))
((_ ($primcall name (arg ...))) (make-$primcall name (list arg ...))) ((_ ($primcall name (arg ...))) (make-$primcall name (list arg ...)))
@ -262,12 +263,14 @@
((_ ($letconst ((name sym val) tail ...) body)) ((_ ($letconst ((name sym val) tail ...) body))
(let-gensyms (kconst) (let-gensyms (kconst)
(build-cps-term (build-cps-term
($letk ((kconst #f ($kargs (name) (sym) ($letconst (tail ...) body)))) ($letk ((kconst ($kargs (name) (sym) ($letconst (tail ...) body))))
($continue kconst ($const val)))))) ($continue kconst (let ((props (source-properties val)))
(and (pair? props) props))
($const val))))))
((_ ($letrec names gensyms funs body)) ((_ ($letrec names gensyms funs body))
(make-$letrec names gensyms funs (build-cps-term body))) (make-$letrec names gensyms funs (build-cps-term body)))
((_ ($continue k exp)) ((_ ($continue k src exp))
(make-$continue k (build-cps-exp exp))))) (make-$continue k src (build-cps-exp exp)))))
(define-syntax-rule (rewrite-cps-term x (pat body) ...) (define-syntax-rule (rewrite-cps-term x (pat body) ...)
(match x (match x
@ -287,20 +290,20 @@
;; Continuations. ;; Continuations.
(('letconst k (name sym c) body) (('letconst k (name sym c) body)
(build-cps-term (build-cps-term
($letk ((k (src exp) ($kargs (name) (sym) ($letk ((k ($kargs (name) (sym)
,(parse-cps body)))) ,(parse-cps body))))
($continue k ($const c))))) ($continue k (src exp) ($const c)))))
(('let k (name sym val) body) (('let k (name sym val) body)
(build-cps-term (build-cps-term
($letk ((k (src exp) ($kargs (name) (sym) ($letk ((k ($kargs (name) (sym)
,(parse-cps body)))) ,(parse-cps body))))
,(parse-cps val)))) ,(parse-cps val))))
(('letk (cont ...) body) (('letk (cont ...) body)
(build-cps-term (build-cps-term
($letk ,(map parse-cps cont) ,(parse-cps body)))) ($letk ,(map parse-cps cont) ,(parse-cps body))))
(('k sym body) (('k sym body)
(build-cps-cont (build-cps-cont
(sym (src exp) ,(parse-cps body)))) (sym ,(parse-cps body))))
(('kif kt kf) (('kif kt kf)
(build-cont-body ($kif kt kf))) (build-cont-body ($kif kt kf)))
(('ktrunc req rest k) (('ktrunc req rest k)
@ -322,7 +325,7 @@
;; Calls. ;; Calls.
(('continue k exp) (('continue k exp)
(build-cps-term ($continue k ,(parse-cps exp)))) (build-cps-term ($continue k (src exp) ,(parse-cps exp))))
(('var sym) (('var sym)
(build-cps-exp ($var sym))) (build-cps-exp ($var sym)))
(('void) (('void)
@ -332,7 +335,7 @@
(('prim name) (('prim name)
(build-cps-exp ($prim name))) (build-cps-exp ($prim name)))
(('fun meta free body) (('fun meta free body)
(build-cps-exp ($fun meta free ,(parse-cps body)))) (build-cps-exp ($fun (src exp) meta free ,(parse-cps body))))
(('letrec ((name sym fun) ...) body) (('letrec ((name sym fun) ...) body)
(build-cps-term (build-cps-term
($letrec name sym (map parse-cps fun) ,(parse-cps body)))) ($letrec name sym (map parse-cps fun) ,(parse-cps body))))
@ -350,16 +353,16 @@
(define (unparse-cps exp) (define (unparse-cps exp)
(match exp (match exp
;; Continuations. ;; Continuations.
(($ $letk (($ $cont k src ($ $kargs (name) (sym) body))) (($ $letk (($ $cont k ($ $kargs (name) (sym) body)))
($ $continue k ($ $const c))) ($ $continue k src ($ $const c)))
`(letconst ,k (,name ,sym ,c) `(letconst ,k (,name ,sym ,c)
,(unparse-cps body))) ,(unparse-cps body)))
(($ $letk (($ $cont k src ($ $kargs (name) (sym) body))) val) (($ $letk (($ $cont k ($ $kargs (name) (sym) body))) val)
`(let ,k (,name ,sym ,(unparse-cps val)) `(let ,k (,name ,sym ,(unparse-cps val))
,(unparse-cps body))) ,(unparse-cps body)))
(($ $letk conts body) (($ $letk conts body)
`(letk ,(map unparse-cps conts) ,(unparse-cps body))) `(letk ,(map unparse-cps conts) ,(unparse-cps body)))
(($ $cont sym src body) (($ $cont sym body)
`(k ,sym ,(unparse-cps body))) `(k ,sym ,(unparse-cps body)))
(($ $kif kt kf) (($ $kif kt kf)
`(kif ,kt ,kf)) `(kif ,kt ,kf))
@ -377,7 +380,7 @@
`(kclause (,req ,opt ,rest ,kw ,allow-other-keys?) ,(unparse-cps body))) `(kclause (,req ,opt ,rest ,kw ,allow-other-keys?) ,(unparse-cps body)))
;; Calls. ;; Calls.
(($ $continue k exp) (($ $continue k src exp)
`(continue ,k ,(unparse-cps exp))) `(continue ,k ,(unparse-cps exp)))
(($ $var sym) (($ $var sym)
`(var ,sym)) `(var ,sym))
@ -387,7 +390,7 @@
`(const ,val)) `(const ,val))
(($ $prim name) (($ $prim name)
`(prim ,name)) `(prim ,name))
(($ $fun meta free body) (($ $fun src meta free body)
`(fun ,meta ,free ,(unparse-cps body))) `(fun ,meta ,free ,(unparse-cps body)))
(($ $letrec names syms funs body) (($ $letrec names syms funs body)
`(letrec ,(map (lambda (name sym fun) `(letrec ,(map (lambda (name sym fun)
@ -408,8 +411,8 @@
(define (fold-conts proc seed fun) (define (fold-conts proc seed fun)
(define (cont-folder cont seed) (define (cont-folder cont seed)
(match cont (match cont
(($ $cont k src cont) (($ $cont k cont)
(let ((seed (proc k src cont seed))) (let ((seed (proc k cont seed)))
(match cont (match cont
(($ $kargs names syms body) (($ $kargs names syms body)
(term-folder body seed)) (term-folder body seed))
@ -424,7 +427,7 @@
(define (fun-folder fun seed) (define (fun-folder fun seed)
(match fun (match fun
(($ $fun meta free body) (($ $fun src meta free body)
(cont-folder body seed)))) (cont-folder body seed))))
(define (term-folder term seed) (define (term-folder term seed)
@ -432,7 +435,7 @@
(($ $letk conts body) (($ $letk conts body)
(fold cont-folder (term-folder body seed) conts)) (fold cont-folder (term-folder body seed) conts))
(($ $continue k exp) (($ $continue k src exp)
(match exp (match exp
(($ $fun) (fun-folder exp seed)) (($ $fun) (fun-folder exp seed))
(_ seed))) (_ seed)))
@ -445,8 +448,8 @@
(define (fold-local-conts proc seed cont) (define (fold-local-conts proc seed cont)
(define (cont-folder cont seed) (define (cont-folder cont seed)
(match cont (match cont
(($ $cont k src cont) (($ $cont k cont)
(let ((seed (proc k src cont seed))) (let ((seed (proc k cont seed)))
(match cont (match cont
(($ $kargs names syms body) (($ $kargs names syms body)
(term-folder body seed)) (term-folder body seed))

View file

@ -35,105 +35,105 @@
(define (fix-clause-arities clause) (define (fix-clause-arities clause)
(let ((conts (build-local-cont-table clause)) (let ((conts (build-local-cont-table clause))
(ktail (match clause (ktail (match clause
(($ $cont _ _ ($ $kentry _ ($ $cont ktail) _)) ktail)))) (($ $cont _ ($ $kentry _ ($ $cont ktail) _)) ktail))))
(define (visit-term term) (define (visit-term term)
(rewrite-cps-term term (rewrite-cps-term term
(($ $letk conts body) (($ $letk conts body)
($letk ,(map visit-cont conts) ,(visit-term body))) ($letk ,(map visit-cont conts) ,(visit-term body)))
(($ $letrec names syms funs body) (($ $letrec names syms funs body)
($letrec names syms (map fix-arities funs) ,(visit-term body))) ($letrec names syms (map fix-arities funs) ,(visit-term body)))
(($ $continue k exp) (($ $continue k src exp)
,(visit-exp k exp)))) ,(visit-exp k src exp))))
(define (adapt-exp nvals k exp) (define (adapt-exp nvals k src exp)
(match nvals (match nvals
(0 (0
(rewrite-cps-term (lookup-cont k conts) (rewrite-cps-term (lookup-cont k conts)
(($ $ktail) (($ $ktail)
,(let-gensyms (kvoid kunspec unspec) ,(let-gensyms (kvoid kunspec unspec)
(build-cps-term (build-cps-term
($letk* ((kunspec #f ($kargs (unspec) (unspec) ($letk* ((kunspec ($kargs (unspec) (unspec)
($continue k ($continue k src
($primcall 'return (unspec))))) ($primcall 'return (unspec)))))
(kvoid #f ($kargs () () (kvoid ($kargs () ()
($continue kunspec ($void))))) ($continue kunspec src ($void)))))
($continue kvoid ,exp))))) ($continue kvoid src ,exp)))))
(($ $ktrunc arity kargs) (($ $ktrunc arity kargs)
,(rewrite-cps-term arity ,(rewrite-cps-term arity
(($ $arity () () #f () #f) (($ $arity () () #f () #f)
($continue kargs ,exp)) ($continue kargs src ,exp))
(_ (_
,(let-gensyms (kvoid kvalues void) ,(let-gensyms (kvoid kvalues void)
(build-cps-term (build-cps-term
($letk* ((kvalues #f ($kargs ('void) (void) ($letk* ((kvalues ($kargs ('void) (void)
($continue k ($continue k src
($primcall 'values (void))))) ($primcall 'values (void)))))
(kvoid #f ($kargs () () (kvoid ($kargs () ()
($continue kvalues ($continue kvalues src
($void))))) ($void)))))
($continue kvoid ,exp))))))) ($continue kvoid src ,exp)))))))
(($ $kargs () () _) (($ $kargs () () _)
($continue k ,exp)) ($continue k src ,exp))
(_ (_
,(let-gensyms (k*) ,(let-gensyms (k*)
(build-cps-term (build-cps-term
($letk ((k* #f ($kargs () () ($continue k ($void))))) ($letk ((k* ($kargs () () ($continue k src ($void)))))
($continue k* ,exp))))))) ($continue k* src ,exp)))))))
(1 (1
(rewrite-cps-term (lookup-cont k conts) (rewrite-cps-term (lookup-cont k conts)
(($ $ktail) (($ $ktail)
,(rewrite-cps-term exp ,(rewrite-cps-term exp
(($var sym) (($var sym)
($continue ktail ($primcall 'return (sym)))) ($continue ktail src ($primcall 'return (sym))))
(_ (_
,(let-gensyms (k* v) ,(let-gensyms (k* v)
(build-cps-term (build-cps-term
($letk ((k* #f ($kargs (v) (v) ($letk ((k* ($kargs (v) (v)
($continue k ($continue k src
($primcall 'return (v)))))) ($primcall 'return (v))))))
($continue k* ,exp))))))) ($continue k* src ,exp)))))))
(($ $ktrunc arity kargs) (($ $ktrunc arity kargs)
,(rewrite-cps-term arity ,(rewrite-cps-term arity
(($ $arity (_) () #f () #f) (($ $arity (_) () #f () #f)
($continue kargs ,exp)) ($continue kargs src ,exp))
(_ (_
,(let-gensyms (kvalues value) ,(let-gensyms (kvalues value)
(build-cps-term (build-cps-term
($letk ((kvalues #f ($kargs ('value) (value) ($letk ((kvalues ($kargs ('value) (value)
($continue k ($continue k src
($primcall 'values (value)))))) ($primcall 'values (value))))))
($continue kvalues ,exp))))))) ($continue kvalues src ,exp)))))))
(($ $kargs () () _) (($ $kargs () () _)
,(let-gensyms (k* drop) ,(let-gensyms (k* drop)
(build-cps-term (build-cps-term
($letk ((k* #f ($kargs ('drop) (drop) ($letk ((k* ($kargs ('drop) (drop)
($continue k ($values ()))))) ($continue k src ($values ())))))
($continue k* ,exp))))) ($continue k* src ,exp)))))
(_ (_
($continue k ,exp)))))) ($continue k src ,exp))))))
(define (visit-exp k exp) (define (visit-exp k src exp)
(rewrite-cps-term exp (rewrite-cps-term exp
((or ($ $void) ((or ($ $void)
($ $const) ($ $const)
($ $prim) ($ $prim)
($ $var)) ($ $var))
,(adapt-exp 1 k exp)) ,(adapt-exp 1 k src exp))
(($ $fun) (($ $fun)
,(adapt-exp 1 k (fix-arities exp))) ,(adapt-exp 1 k src (fix-arities exp)))
(($ $call) (($ $call)
;; In general, calls have unknown return arity. For that ;; In general, calls have unknown return arity. For that
;; reason every non-tail call has an implicit adaptor ;; reason every non-tail call has an implicit adaptor
;; continuation to adapt the return to the target ;; continuation to adapt the return to the target
;; continuation, and we don't need to do any adapting here. ;; continuation, and we don't need to do any adapting here.
($continue k ,exp)) ($continue k src ,exp))
(($ $primcall 'return (arg)) (($ $primcall 'return (arg))
;; Primcalls to return are in tail position. ;; Primcalls to return are in tail position.
($continue ktail ,exp)) ($continue ktail src ,exp))
(($ $primcall (? (lambda (name) (($ $primcall (? (lambda (name)
(and (not (prim-rtl-instruction name)) (and (not (prim-rtl-instruction name))
(not (branching-primitive? name)))))) (not (branching-primitive? name))))))
($continue k ,exp)) ($continue k src ,exp))
(($ $primcall 'struct-set! (obj pos val)) (($ $primcall 'struct-set! (obj pos val))
;; Unhappily, and undocumentedly, struct-set! returns the value ;; Unhappily, and undocumentedly, struct-set! returns the value
;; that was set. There is code that relies on this. Hackety ;; that was set. There is code that relies on this. Hackety
@ -142,63 +142,63 @@
(($ $ktail) (($ $ktail)
,(let-gensyms (kvoid) ,(let-gensyms (kvoid)
(build-cps-term (build-cps-term
($letk* ((kvoid #f ($kargs () () ($letk* ((kvoid ($kargs () ()
($continue ktail ($continue ktail src
($primcall 'return (val)))))) ($primcall 'return (val))))))
($continue kvoid ,exp))))) ($continue kvoid src ,exp)))))
(($ $ktrunc arity kargs) (($ $ktrunc arity kargs)
,(rewrite-cps-term arity ,(rewrite-cps-term arity
(($ $arity () () #f () #f) (($ $arity () () #f () #f)
($continue kargs ,exp)) ($continue kargs src ,exp))
(_ (_
,(let-gensyms (kvoid) ,(let-gensyms (kvoid)
(build-cps-term (build-cps-term
($letk* ((kvoid #f ($kargs () () ($letk* ((kvoid ($kargs () ()
($continue k ($continue k src
($primcall 'values (val)))))) ($primcall 'values (val))))))
($continue kvoid ,exp))))))) ($continue kvoid src ,exp)))))))
(($ $kargs () () _) (($ $kargs () () _)
($continue k ,exp)) ($continue k src ,exp))
(_ (_
,(let-gensyms (k*) ,(let-gensyms (k*)
(build-cps-term (build-cps-term
($letk ((k* #f ($kargs () () ($continue k ($var val))))) ($letk ((k* ($kargs () () ($continue k src ($var val)))))
($continue k* ,exp))))))) ($continue k* src ,exp)))))))
(($ $primcall name args) (($ $primcall name args)
,(match (prim-arity name) ,(match (prim-arity name)
((out . in) ((out . in)
(if (= in (length args)) (if (= in (length args))
(adapt-exp out k (adapt-exp out k src
(let ((inst (prim-rtl-instruction name))) (let ((inst (prim-rtl-instruction name)))
(if (and inst (not (eq? inst name))) (if (and inst (not (eq? inst name)))
(build-cps-exp ($primcall inst args)) (build-cps-exp ($primcall inst args))
exp))) exp)))
(let-gensyms (k* p*) (let-gensyms (k* p*)
(build-cps-term (build-cps-term
($letk ((k* #f ($kargs ('prim) (p*) ($letk ((k* ($kargs ('prim) (p*)
($continue k ($call p* args))))) ($continue k src ($call p* args)))))
($continue k* ($prim name))))))))) ($continue k* src ($prim name)))))))))
(($ $values) (($ $values)
;; Values nodes are inserted by CPS optimization passes, so ;; Values nodes are inserted by CPS optimization passes, so
;; we assume they are correct. ;; we assume they are correct.
($continue k ,exp)) ($continue k src ,exp))
(($ $prompt) (($ $prompt)
($continue k ,exp)))) ($continue k src ,exp))))
(define (visit-cont cont) (define (visit-cont cont)
(rewrite-cps-cont cont (rewrite-cps-cont cont
(($ $cont sym src ($ $kargs names syms body)) (($ $cont sym ($ $kargs names syms body))
(sym src ($kargs names syms ,(visit-term body)))) (sym ($kargs names syms ,(visit-term body))))
(($ $cont sym src ($ $kclause arity body)) (($ $cont sym ($ $kclause arity body))
(sym src ($kclause ,arity ,(visit-cont body)))) (sym ($kclause ,arity ,(visit-cont body))))
(($ $cont) (($ $cont)
,cont))) ,cont)))
(rewrite-cps-cont clause (rewrite-cps-cont clause
(($ $cont sym src ($ $kentry self tail clauses)) (($ $cont sym ($ $kentry self tail clauses))
(sym src ($kentry self ,tail ,(map visit-cont clauses))))))) (sym ($kentry self ,tail ,(map visit-cont clauses)))))))
(define (fix-arities fun) (define (fix-arities fun)
(rewrite-cps-exp fun (rewrite-cps-exp fun
(($ $fun meta free body) (($ $fun src meta free body)
($fun meta free ,(fix-clause-arities body))))) ($fun src meta free ,(fix-clause-arities body)))))

View file

@ -63,8 +63,8 @@ values in the term."
(let-gensyms (k* sym*) (let-gensyms (k* sym*)
(receive (exp free) (k sym*) (receive (exp free) (k sym*)
(values (build-cps-term (values (build-cps-term
($letk ((k* #f ($kargs (sym*) (sym*) ,exp))) ($letk ((k* ($kargs (sym*) (sym*) ,exp)))
($continue k* ($primcall 'free-ref (self sym))))) ($continue k* #f ($primcall 'free-ref (self sym)))))
(cons sym free)))))) (cons sym free))))))
(define (convert-free-vars syms self bound k) (define (convert-free-vars syms self bound k)
@ -88,13 +88,13 @@ performed, and @var{outer-bound} is the list of bound variables there."
(fold (lambda (free idx body) (fold (lambda (free idx body)
(let-gensyms (k idxsym) (let-gensyms (k idxsym)
(build-cps-term (build-cps-term
($letk ((k src ($kargs () () ,body))) ($letk ((k ($kargs () () ,body)))
,(convert-free-var ,(convert-free-var
free outer-self outer-bound free outer-self outer-bound
(lambda (free) (lambda (free)
(values (build-cps-term (values (build-cps-term
($letconst (('idx idxsym idx)) ($letconst (('idx idxsym idx))
($continue k ($continue k src
($primcall 'free-set! (v idxsym free))))) ($primcall 'free-set! (v idxsym free)))))
'()))))))) '())))))))
body body
@ -123,19 +123,19 @@ convert functions to flat closures."
(values (build-cps-term ($letk ,conts ,body)) (values (build-cps-term ($letk ,conts ,body))
(union free free*))))) (union free free*)))))
(($ $cont sym src ($ $kargs names syms body)) (($ $cont sym ($ $kargs names syms body))
(receive (body free) (cc body self (append syms bound)) (receive (body free) (cc body self (append syms bound))
(values (build-cps-cont (sym src ($kargs names syms ,body))) (values (build-cps-cont (sym ($kargs names syms ,body)))
free))) free)))
(($ $cont sym src ($ $kentry self tail clauses)) (($ $cont sym ($ $kentry self tail clauses))
(receive (clauses free) (cc* clauses self (list self)) (receive (clauses free) (cc* clauses self (list self))
(values (build-cps-cont (sym src ($kentry self ,tail ,clauses))) (values (build-cps-cont (sym ($kentry self ,tail ,clauses)))
free))) free)))
(($ $cont sym src ($ $kclause arity body)) (($ $cont sym ($ $kclause arity body))
(receive (body free) (cc body self bound) (receive (body free) (cc body self bound)
(values (build-cps-cont (sym src ($kclause ,arity ,body))) (values (build-cps-cont (sym ($kclause ,arity ,body)))
free))) free)))
(($ $cont) (($ $cont)
@ -153,76 +153,76 @@ convert functions to flat closures."
(free free)) (free free))
(match in (match in
(() (values (bindings body) free)) (() (values (bindings body) free))
(((name sym ($ $fun meta () fun-body)) . in) (((name sym ($ $fun src meta () fun-body)) . in)
(receive (fun-body fun-free) (cc fun-body #f '()) (receive (fun-body fun-free) (cc fun-body #f '())
(lp in (lp in
(lambda (body) (lambda (body)
(let-gensyms (k) (let-gensyms (k)
(build-cps-term (build-cps-term
($letk ((k #f ($kargs (name) (sym) ,(bindings body)))) ($letk ((k ($kargs (name) (sym) ,(bindings body))))
($continue k ($continue k src
($fun meta fun-free ,fun-body)))))) ($fun src meta fun-free ,fun-body))))))
(init-closure #f sym fun-free self bound body) (init-closure src sym fun-free self bound body)
(union free (difference fun-free bound)))))))))) (union free (difference fun-free bound))))))))))
(($ $continue k ($ $var sym)) (($ $continue k src ($ $var sym))
(convert-free-var sym self bound (convert-free-var sym self bound
(lambda (sym) (lambda (sym)
(values (build-cps-term ($continue k ($var sym))) (values (build-cps-term ($continue k src ($var sym)))
'())))) '()))))
(($ $continue k (($ $continue k src
(or ($ $void) (or ($ $void)
($ $const) ($ $const)
($ $prim))) ($ $prim)))
(values exp '())) (values exp '()))
(($ $continue k ($ $fun meta () body)) (($ $continue k src ($ $fun src* meta () body))
(receive (body free) (cc body #f '()) (receive (body free) (cc body #f '())
(match free (match free
(() (()
(values (build-cps-term (values (build-cps-term
($continue k ($fun meta free ,body))) ($continue k src ($fun src* meta free ,body)))
free)) free))
(_ (_
(values (values
(let-gensyms (kinit v) (let-gensyms (kinit v)
(build-cps-term (build-cps-term
($letk ((kinit #f ($kargs (v) (v) ($letk ((kinit ($kargs (v) (v)
,(init-closure #f v free self bound ,(init-closure src v free self bound
(build-cps-term (build-cps-term
($continue k ($var v))))))) ($continue k src ($var v)))))))
($continue kinit ($fun meta free ,body))))) ($continue kinit src ($fun src* meta free ,body)))))
(difference free bound)))))) (difference free bound))))))
(($ $continue k ($ $call proc args)) (($ $continue k src ($ $call proc args))
(convert-free-vars (cons proc args) self bound (convert-free-vars (cons proc args) self bound
(match-lambda (match-lambda
((proc . args) ((proc . args)
(values (build-cps-term (values (build-cps-term
($continue k ($call proc args))) ($continue k src ($call proc args)))
'()))))) '())))))
(($ $continue k ($ $primcall name args)) (($ $continue k src ($ $primcall name args))
(convert-free-vars args self bound (convert-free-vars args self bound
(lambda (args) (lambda (args)
(values (build-cps-term (values (build-cps-term
($continue k ($primcall name args))) ($continue k src ($primcall name args)))
'())))) '()))))
(($ $continue k ($ $values args)) (($ $continue k src ($ $values args))
(convert-free-vars args self bound (convert-free-vars args self bound
(lambda (args) (lambda (args)
(values (build-cps-term (values (build-cps-term
($continue k ($values args))) ($continue k src ($values args)))
'())))) '()))))
(($ $continue k ($ $prompt escape? tag handler pop)) (($ $continue k src ($ $prompt escape? tag handler pop))
(convert-free-var (convert-free-var
tag self bound tag self bound
(lambda (tag) (lambda (tag)
(values (build-cps-term (values (build-cps-term
($continue k ($prompt escape? tag handler pop))) ($continue k src ($prompt escape? tag handler pop)))
'())))) '()))))
(_ (error "what" exp)))) (_ (error "what" exp))))
@ -237,37 +237,38 @@ convert functions to flat closures."
(rewrite-cps-term term (rewrite-cps-term term
(($ $letk conts body) (($ $letk conts body)
($letk ,(map visit-cont conts) ,(visit-term body))) ($letk ,(map visit-cont conts) ,(visit-term body)))
(($ $continue k ($ $primcall 'free-ref (closure sym))) (($ $continue k src ($ $primcall 'free-ref (closure sym)))
,(let-gensyms (idx) ,(let-gensyms (idx)
(build-cps-term (build-cps-term
($letconst (('idx idx (free-index sym))) ($letconst (('idx idx (free-index sym)))
($continue k ($primcall 'free-ref (closure idx))))))) ($continue k src ($primcall 'free-ref (closure idx)))))))
(($ $continue k ($ $fun meta free body)) (($ $continue k src ($ $fun src* meta free body))
($continue k ($fun meta free ,(convert-to-indices body free)))) ($continue k src
($fun src* meta free ,(convert-to-indices body free))))
(($ $continue) (($ $continue)
,term))) ,term)))
(define (visit-cont cont) (define (visit-cont cont)
(rewrite-cps-cont cont (rewrite-cps-cont cont
(($ $cont sym src ($ $kargs names syms body)) (($ $cont sym ($ $kargs names syms body))
(sym src ($kargs names syms ,(visit-term body)))) (sym ($kargs names syms ,(visit-term body))))
(($ $cont sym src ($ $kclause arity body)) (($ $cont sym ($ $kclause arity body))
(sym src ($kclause ,arity ,(visit-cont body)))) (sym ($kclause ,arity ,(visit-cont body))))
;; Other kinds of continuations don't bind values and don't have ;; Other kinds of continuations don't bind values and don't have
;; bodies. ;; bodies.
(($ $cont) (($ $cont)
,cont))) ,cont)))
(rewrite-cps-cont body (rewrite-cps-cont body
(($ $cont sym src ($ $kentry self tail clauses)) (($ $cont sym ($ $kentry self tail clauses))
(sym src ($kentry self ,tail ,(map visit-cont clauses)))))) (sym ($kentry self ,tail ,(map visit-cont clauses))))))
(define (convert-closures exp) (define (convert-closures exp)
"Convert free reference in @var{exp} to primcalls to @code{free-ref}, "Convert free reference in @var{exp} to primcalls to @code{free-ref},
and allocate and initialize flat closures." and allocate and initialize flat closures."
(match exp (match exp
(($ $fun meta () body) (($ $fun src meta () body)
(receive (body free) (cc body #f '()) (receive (body free) (cc body #f '())
(unless (null? free) (unless (null? free)
(error "Expected no free vars in toplevel thunk" exp body free)) (error "Expected no free vars in toplevel thunk" exp body free))
(build-cps-exp (build-cps-exp
($fun meta free ,(convert-to-indices body free))))))) ($fun src meta free ,(convert-to-indices body free)))))))

View file

@ -76,413 +76,405 @@
exp)) exp))
(define (collect-conts f cfa) (define (collect-conts f cfa)
(let ((srcv (make-vector (cfa-k-count cfa) #f)) (let ((contv (make-vector (cfa-k-count cfa) #f)))
(contv (make-vector (cfa-k-count cfa) #f)))
(fold-local-conts (fold-local-conts
(lambda (k src cont tail) (lambda (k cont tail)
(let ((idx (cfa-k-idx cfa k #:default (lambda (k) #f)))) (let ((idx (cfa-k-idx cfa k #:default (lambda (k) #f))))
(when idx (when idx
(when src
(vector-set! srcv idx src))
(vector-set! contv idx cont)))) (vector-set! contv idx cont))))
'() '()
(match f (match f
(($ $fun meta free entry) (($ $fun src meta free entry)
entry))) entry)))
(values srcv contv))) contv))
(define (compile-fun f asm) (define (compile-fun f asm)
(let* ((dfg (compute-dfg f #:global? #f)) (let* ((dfg (compute-dfg f #:global? #f))
(cfa (analyze-control-flow f dfg)) (cfa (analyze-control-flow f dfg))
(allocation (allocate-slots f dfg))) (allocation (allocate-slots f dfg))
(call-with-values (lambda () (collect-conts f cfa)) (contv (collect-conts f cfa)))
(lambda (srcv contv) (define (lookup-cont k)
(define (lookup-cont k) (vector-ref contv (cfa-k-idx cfa k)))
(vector-ref contv (cfa-k-idx cfa k)))
(define (maybe-emit-source n) (define (immediate-u8? val)
(let ((src (vector-ref srcv n))) (and (integer? val) (exact? val) (<= 0 val 255)))
(when src
(emit-source asm src))))
(define (emit-label-and-maybe-source n) (define (maybe-immediate-u8 sym)
(emit-label asm (cfa-k-sym cfa n)) (call-with-values (lambda ()
(maybe-emit-source n)) (lookup-maybe-constant-value sym allocation))
(lambda (has-const? val)
(and has-const? (immediate-u8? val) val))))
(define (immediate-u8? val) (define (slot sym)
(and (integer? val) (exact? val) (<= 0 val 255))) (lookup-slot sym allocation))
(define (maybe-immediate-u8 sym) (define (constant sym)
(call-with-values (lambda () (lookup-constant-value sym allocation))
(lookup-maybe-constant-value sym allocation))
(lambda (has-const? val)
(and has-const? (immediate-u8? val) val))))
(define (slot sym) (define (maybe-mov dst src)
(lookup-slot sym allocation)) (unless (= dst src)
(emit-mov asm dst src)))
(define (constant sym) (define (maybe-load-constant slot src)
(lookup-constant-value sym allocation)) (call-with-values (lambda ()
(lookup-maybe-constant-value src allocation))
(lambda (has-const? val)
(and has-const?
(begin
(emit-load-constant asm slot val)
#t)))))
(define (maybe-mov dst src) (define (compile-entry meta)
(unless (= dst src) (match (vector-ref contv 0)
(emit-mov asm dst src))) (($ $kentry self tail clauses)
(emit-begin-program asm (cfa-k-sym cfa 0) meta)
(let lp ((n 1)
(ks (map (match-lambda (($ $cont k) k)) clauses)))
(match ks
(()
(unless (= n (vector-length contv))
(error "unexpected end of clauses"))
(emit-end-program asm))
((k . ks)
(unless (eq? (cfa-k-sym cfa n) k)
(error "unexpected k" k))
(lp (compile-clause n (and (pair? ks) (car ks)))
ks)))))))
(define (maybe-load-constant slot src) (define (compile-clause n alternate)
(call-with-values (lambda () (match (vector-ref contv n)
(lookup-maybe-constant-value src allocation)) (($ $kclause ($ $arity req opt rest kw allow-other-keys?))
(lambda (has-const? val) (let* ((kw-indices (map (match-lambda
(and has-const? ((key name sym)
(begin (cons key (lookup-slot sym allocation))))
(emit-load-constant asm slot val) kw))
#t))))) (k (cfa-k-sym cfa n))
(nlocals (lookup-nlocals k allocation)))
(emit-label asm k)
(emit-begin-kw-arity asm req opt rest kw-indices
allow-other-keys? nlocals alternate)
(let ((next (compile-body (1+ n) nlocals)))
(emit-end-arity asm)
next)))))
(define (compile-entry meta) (define (compile-body n nlocals)
(match (vector-ref contv 0) (let compile-cont ((n n))
(($ $kentry self tail clauses) (if (= n (vector-length contv))
(emit-begin-program asm (cfa-k-sym cfa 0) meta) n
(maybe-emit-source 0) (match (vector-ref contv n)
(let lp ((n 1) (($ $kclause) n)
(ks (map (match-lambda (($ $cont k) k)) clauses))) (($ $kargs _ _ term)
(match ks (emit-label asm (cfa-k-sym cfa n))
(() (let find-exp ((term term))
(unless (= n (vector-length contv)) (match term
(error "unexpected end of clauses")) (($ $letk conts term)
(emit-end-program asm)) (find-exp term))
((k . ks) (($ $continue k src exp)
(unless (eq? (cfa-k-sym cfa n) k) (when src
(error "unexpected k" k)) (emit-source asm src))
(lp (compile-clause n (and (pair? ks) (car ks))) (compile-expression n k exp nlocals)
ks))))))) (compile-cont (1+ n))))))
(_
(emit-label asm (cfa-k-sym cfa n))
(compile-cont (1+ n)))))))
(define (compile-clause n alternate) (define (compile-expression n k exp nlocals)
(match (vector-ref contv n) (let* ((label (cfa-k-sym cfa n))
(($ $kclause ($ $arity req opt rest kw allow-other-keys?)) (k-idx (cfa-k-idx cfa k))
(let ((kw-indices (map (match-lambda (fallthrough? (= k-idx (1+ n))))
((key name sym) (define (maybe-emit-jump)
(cons key (lookup-slot sym allocation)))) (unless (= k-idx (1+ n))
kw)) (emit-br asm k)))
(nlocals (lookup-nlocals (cfa-k-sym cfa n) allocation))) (match (vector-ref contv k-idx)
(emit-label-and-maybe-source n) (($ $ktail)
(emit-begin-kw-arity asm req opt rest kw-indices (compile-tail label exp))
allow-other-keys? nlocals alternate) (($ $kargs (name) (sym))
(let ((next (compile-body (1+ n) nlocals))) (let ((dst (slot sym)))
(emit-end-arity asm) (when dst
next))))) (compile-value label exp dst nlocals)))
(maybe-emit-jump))
(($ $kargs () ())
(compile-effect label exp k nlocals)
(maybe-emit-jump))
(($ $kargs names syms)
(compile-values label exp syms)
(maybe-emit-jump))
(($ $kif kt kf)
(compile-test label exp kt kf
(and (= k-idx (1+ n))
(< (+ n 2) (cfa-k-count cfa))
(cfa-k-sym cfa (+ n 2)))))
(($ $ktrunc ($ $arity req () rest () #f) k)
(compile-trunc label exp (length req) (and rest #t) nlocals)
(unless (and (= k-idx (1+ n))
(< (+ n 2) (cfa-k-count cfa))
(eq? (cfa-k-sym cfa (+ n 2)) k))
(emit-br asm k))))))
(define (compile-body n nlocals) (define (compile-tail label exp)
(let compile-cont ((n n)) ;; There are only three kinds of expressions in tail position:
(if (= n (vector-length contv)) ;; tail calls, multiple-value returns, and single-value returns.
n (match exp
(match (vector-ref contv n) (($ $call proc args)
(($ $kclause) n) (for-each (match-lambda
(($ $kargs _ _ term) ((src . dst) (emit-mov asm dst src)))
(emit-label-and-maybe-source n) (lookup-parallel-moves label allocation))
(let find-exp ((term term)) (let ((tail-slots (cdr (iota (1+ (length args))))))
(match term (for-each maybe-load-constant tail-slots args))
(($ $letk conts term) (emit-tail-call asm (1+ (length args))))
(find-exp term)) (($ $values args)
(($ $continue k exp) (let ((tail-slots (cdr (iota (1+ (length args))))))
(compile-expression n k exp nlocals) (for-each (match-lambda
(compile-cont (1+ n)))))) ((src . dst) (emit-mov asm dst src)))
(_ (lookup-parallel-moves label allocation))
(emit-label-and-maybe-source n) (for-each maybe-load-constant tail-slots args))
(compile-cont (1+ n))))))) (emit-reset-frame asm (1+ (length args)))
(emit-return-values asm))
(($ $primcall 'return (arg))
(emit-return asm (slot arg)))))
(define (compile-expression n k exp nlocals) (define (compile-value label exp dst nlocals)
(let* ((label (cfa-k-sym cfa n)) (match exp
(k-idx (cfa-k-idx cfa k)) (($ $var sym)
(fallthrough? (= k-idx (1+ n)))) (maybe-mov dst (slot sym)))
(define (maybe-emit-jump) ;; FIXME: Remove ($var sym), replace with ($values (sym))
(unless (= k-idx (1+ n)) (($ $values (arg))
(emit-br asm k))) (or (maybe-load-constant dst arg)
(match (vector-ref contv k-idx) (maybe-mov dst (slot arg))))
(($ $ktail) (($ $void)
(compile-tail label exp)) (emit-load-constant asm dst *unspecified*))
(($ $kargs (name) (sym)) (($ $const exp)
(let ((dst (slot sym))) (emit-load-constant asm dst exp))
(when dst (($ $fun src meta () ($ $cont k))
(compile-value label exp dst nlocals))) (emit-load-static-procedure asm dst k))
(maybe-emit-jump)) (($ $fun src meta free ($ $cont k))
(($ $kargs () ()) (emit-make-closure asm dst k (length free)))
(compile-effect label exp k nlocals) (($ $call proc args)
(maybe-emit-jump)) (let ((proc-slot (lookup-call-proc-slot label allocation))
(($ $kargs names syms) (nargs (length args)))
(compile-values label exp syms) (or (maybe-load-constant proc-slot proc)
(maybe-emit-jump)) (maybe-mov proc-slot (slot proc)))
(($ $kif kt kf) (let lp ((n (1+ proc-slot)) (args args))
(compile-test label exp kt kf (match args
(and (= k-idx (1+ n)) (()
(< (+ n 2) (cfa-k-count cfa)) (emit-call asm proc-slot (+ nargs 1))
(cfa-k-sym cfa (+ n 2))))) (emit-receive asm dst proc-slot nlocals))
(($ $ktrunc ($ $arity req () rest () #f) k) ((arg . args)
(compile-trunc label exp (length req) (and rest #t) nlocals) (or (maybe-load-constant n arg)
(unless (and (= k-idx (1+ n)) (maybe-mov n (slot arg)))
(< (+ n 2) (cfa-k-count cfa)) (lp (1+ n) args))))))
(eq? (cfa-k-sym cfa (+ n 2)) k)) (($ $primcall 'current-module)
(emit-br asm k)))))) (emit-current-module asm dst))
(($ $primcall 'cached-toplevel-box (scope name bound?))
(emit-cached-toplevel-box asm dst (constant scope) (constant name)
(constant bound?)))
(($ $primcall 'cached-module-box (mod name public? bound?))
(emit-cached-module-box asm dst (constant mod) (constant name)
(constant public?) (constant bound?)))
(($ $primcall 'resolve (name bound?))
(emit-resolve asm dst (constant bound?) (slot name)))
(($ $primcall 'free-ref (closure idx))
(emit-free-ref asm dst (slot closure) (constant idx)))
(($ $primcall 'make-vector (length init))
(cond
((maybe-immediate-u8 length)
=> (lambda (length)
(emit-constant-make-vector asm dst length (slot init))))
(else
(emit-make-vector asm dst (slot length) (slot init)))))
(($ $primcall 'vector-ref (vector index))
(cond
((maybe-immediate-u8 index)
=> (lambda (index)
(emit-constant-vector-ref asm dst (slot vector) index)))
(else
(emit-vector-ref asm dst (slot vector) (slot index)))))
(($ $primcall 'builtin-ref (name))
(emit-builtin-ref asm dst (constant name)))
(($ $primcall 'bv-u8-ref (bv idx))
(emit-bv-u8-ref asm dst (slot bv) (slot idx)))
(($ $primcall 'bv-u16-ref (bv idx))
(emit-bv-u16-ref asm dst (slot bv) (slot idx)))
(($ $primcall 'bv-s16-ref (bv idx))
(emit-bv-s16-ref asm dst (slot bv) (slot idx)))
(($ $primcall 'bv-u32-ref (bv idx val))
(emit-bv-u32-ref asm dst (slot bv) (slot idx)))
(($ $primcall 'bv-s32-ref (bv idx val))
(emit-bv-s32-ref asm dst (slot bv) (slot idx)))
(($ $primcall 'bv-u64-ref (bv idx val))
(emit-bv-u64-ref asm dst (slot bv) (slot idx)))
(($ $primcall 'bv-s64-ref (bv idx val))
(emit-bv-s64-ref asm dst (slot bv) (slot idx)))
(($ $primcall 'bv-f32-ref (bv idx val))
(emit-bv-f32-ref asm dst (slot bv) (slot idx)))
(($ $primcall 'bv-f64-ref (bv idx val))
(emit-bv-f64-ref asm dst (slot bv) (slot idx)))
(($ $primcall name args)
;; FIXME: Inline all the cases.
(let ((inst (prim-rtl-instruction name)))
(emit-text asm `((,inst ,dst ,@(map slot args))))))))
(define (compile-tail label exp) (define (compile-effect label exp k nlocals)
;; There are only three kinds of expressions in tail position: (match exp
;; tail calls, multiple-value returns, and single-value returns. (($ $values ()) #f)
(match exp (($ $prompt escape? tag handler pop)
(($ $call proc args) (match (lookup-cont handler)
(for-each (match-lambda (($ $ktrunc ($ $arity req () rest () #f) khandler-body)
((src . dst) (emit-mov asm dst src))) (let ((receive-args (gensym "handler"))
(lookup-parallel-moves label allocation)) (nreq (length req))
(let ((tail-slots (cdr (iota (1+ (length args)))))) (proc-slot (lookup-call-proc-slot label allocation)))
(for-each maybe-load-constant tail-slots args)) (emit-prompt asm (slot tag) escape? proc-slot receive-args)
(emit-tail-call asm (1+ (length args)))) (emit-br asm k)
(($ $values args) (emit-label asm receive-args)
(let ((tail-slots (cdr (iota (1+ (length args)))))) (emit-receive-values asm proc-slot (->bool rest) nreq)
(for-each (match-lambda (when rest
((src . dst) (emit-mov asm dst src))) (emit-bind-rest asm (+ proc-slot 1 nreq)))
(lookup-parallel-moves label allocation)) (for-each (match-lambda
(for-each maybe-load-constant tail-slots args)) ((src . dst) (emit-mov asm dst src)))
(emit-reset-frame asm (1+ (length args))) (lookup-parallel-moves handler allocation))
(emit-return-values asm)) (emit-reset-frame asm nlocals)
(($ $primcall 'return (arg)) (emit-br asm khandler-body)))))
(emit-return asm (slot arg))))) (($ $primcall 'cache-current-module! (sym scope))
(emit-cache-current-module! asm (slot sym) (constant scope)))
(($ $primcall 'free-set! (closure idx value))
(emit-free-set! asm (slot closure) (slot value) (constant idx)))
(($ $primcall 'box-set! (box value))
(emit-box-set! asm (slot box) (slot value)))
(($ $primcall 'struct-set! (struct index value))
(emit-struct-set! asm (slot struct) (slot index) (slot value)))
(($ $primcall 'vector-set! (vector index value))
(call-with-values (lambda ()
(lookup-maybe-constant-value index allocation))
(lambda (has-const? index-val)
(if (and has-const? (integer? index-val) (exact? index-val)
(<= 0 index-val 255))
(emit-constant-vector-set! asm (slot vector) index-val
(slot value))
(emit-vector-set! asm (slot vector) (slot index)
(slot value))))))
(($ $primcall 'variable-set! (var val))
(emit-box-set! asm (slot var) (slot val)))
(($ $primcall 'set-car! (pair value))
(emit-set-car! asm (slot pair) (slot value)))
(($ $primcall 'set-cdr! (pair value))
(emit-set-cdr! asm (slot pair) (slot value)))
(($ $primcall 'define! (sym value))
(emit-define! asm (slot sym) (slot value)))
(($ $primcall 'push-fluid (fluid val))
(emit-push-fluid asm (slot fluid) (slot val)))
(($ $primcall 'pop-fluid ())
(emit-pop-fluid asm))
(($ $primcall 'wind (winder unwinder))
(emit-wind asm (slot winder) (slot unwinder)))
(($ $primcall 'bv-u8-set! (bv idx val))
(emit-bv-u8-set! asm (slot bv) (slot idx) (slot val)))
(($ $primcall 'bv-u16-set! (bv idx val))
(emit-bv-u16-set! asm (slot bv) (slot idx) (slot val)))
(($ $primcall 'bv-s16-set! (bv idx val))
(emit-bv-s16-set! asm (slot bv) (slot idx) (slot val)))
(($ $primcall 'bv-u32-set! (bv idx val))
(emit-bv-u32-set! asm (slot bv) (slot idx) (slot val)))
(($ $primcall 'bv-s32-set! (bv idx val))
(emit-bv-s32-set! asm (slot bv) (slot idx) (slot val)))
(($ $primcall 'bv-u64-set! (bv idx val))
(emit-bv-u64-set! asm (slot bv) (slot idx) (slot val)))
(($ $primcall 'bv-s64-set! (bv idx val))
(emit-bv-s64-set! asm (slot bv) (slot idx) (slot val)))
(($ $primcall 'bv-f32-set! (bv idx val))
(emit-bv-f32-set! asm (slot bv) (slot idx) (slot val)))
(($ $primcall 'bv-f64-set! (bv idx val))
(emit-bv-f64-set! asm (slot bv) (slot idx) (slot val)))
(($ $primcall 'unwind ())
(emit-unwind asm))))
(define (compile-value label exp dst nlocals) (define (compile-values label exp syms)
(match exp (match exp
(($ $var sym) (($ $values args)
(maybe-mov dst (slot sym))) (for-each (match-lambda
;; FIXME: Remove ($var sym), replace with ($values (sym)) ((src . dst) (emit-mov asm dst src)))
(($ $values (arg)) (lookup-parallel-moves label allocation))
(or (maybe-load-constant dst arg) (for-each maybe-load-constant (map slot syms) args))))
(maybe-mov dst (slot arg))))
(($ $void)
(emit-load-constant asm dst *unspecified*))
(($ $const exp)
(emit-load-constant asm dst exp))
(($ $fun meta () ($ $cont k))
(emit-load-static-procedure asm dst k))
(($ $fun meta free ($ $cont k))
(emit-make-closure asm dst k (length free)))
(($ $call proc args)
(let ((proc-slot (lookup-call-proc-slot label allocation))
(nargs (length args)))
(or (maybe-load-constant proc-slot proc)
(maybe-mov proc-slot (slot proc)))
(let lp ((n (1+ proc-slot)) (args args))
(match args
(()
(emit-call asm proc-slot (+ nargs 1))
(emit-receive asm dst proc-slot nlocals))
((arg . args)
(or (maybe-load-constant n arg)
(maybe-mov n (slot arg)))
(lp (1+ n) args))))))
(($ $primcall 'current-module)
(emit-current-module asm dst))
(($ $primcall 'cached-toplevel-box (scope name bound?))
(emit-cached-toplevel-box asm dst (constant scope) (constant name)
(constant bound?)))
(($ $primcall 'cached-module-box (mod name public? bound?))
(emit-cached-module-box asm dst (constant mod) (constant name)
(constant public?) (constant bound?)))
(($ $primcall 'resolve (name bound?))
(emit-resolve asm dst (constant bound?) (slot name)))
(($ $primcall 'free-ref (closure idx))
(emit-free-ref asm dst (slot closure) (constant idx)))
(($ $primcall 'make-vector (length init))
(cond
((maybe-immediate-u8 length)
=> (lambda (length)
(emit-constant-make-vector asm dst length (slot init))))
(else
(emit-make-vector asm dst (slot length) (slot init)))))
(($ $primcall 'vector-ref (vector index))
(cond
((maybe-immediate-u8 index)
=> (lambda (index)
(emit-constant-vector-ref asm dst (slot vector) index)))
(else
(emit-vector-ref asm dst (slot vector) (slot index)))))
(($ $primcall 'builtin-ref (name))
(emit-builtin-ref asm dst (constant name)))
(($ $primcall 'bv-u8-ref (bv idx))
(emit-bv-u8-ref asm dst (slot bv) (slot idx)))
(($ $primcall 'bv-u16-ref (bv idx))
(emit-bv-u16-ref asm dst (slot bv) (slot idx)))
(($ $primcall 'bv-s16-ref (bv idx))
(emit-bv-s16-ref asm dst (slot bv) (slot idx)))
(($ $primcall 'bv-u32-ref (bv idx val))
(emit-bv-u32-ref asm dst (slot bv) (slot idx)))
(($ $primcall 'bv-s32-ref (bv idx val))
(emit-bv-s32-ref asm dst (slot bv) (slot idx)))
(($ $primcall 'bv-u64-ref (bv idx val))
(emit-bv-u64-ref asm dst (slot bv) (slot idx)))
(($ $primcall 'bv-s64-ref (bv idx val))
(emit-bv-s64-ref asm dst (slot bv) (slot idx)))
(($ $primcall 'bv-f32-ref (bv idx val))
(emit-bv-f32-ref asm dst (slot bv) (slot idx)))
(($ $primcall 'bv-f64-ref (bv idx val))
(emit-bv-f64-ref asm dst (slot bv) (slot idx)))
(($ $primcall name args)
;; FIXME: Inline all the cases.
(let ((inst (prim-rtl-instruction name)))
(emit-text asm `((,inst ,dst ,@(map slot args))))))))
(define (compile-effect label exp k nlocals) (define (compile-test label exp kt kf next-label)
(match exp (define (unary op sym)
(($ $values ()) #f) (cond
(($ $prompt escape? tag handler pop) ((eq? kt next-label)
(match (lookup-cont handler) (op asm (slot sym) #t kf))
(($ $ktrunc ($ $arity req () rest () #f) khandler-body) (else
(let ((receive-args (gensym "handler")) (op asm (slot sym) #f kt)
(nreq (length req)) (unless (eq? kf next-label)
(proc-slot (lookup-call-proc-slot label allocation))) (emit-br asm kf)))))
(emit-prompt asm (slot tag) escape? proc-slot receive-args) (define (binary op a b)
(emit-br asm k) (cond
(emit-label asm receive-args) ((eq? kt next-label)
(emit-receive-values asm proc-slot (->bool rest) nreq) (op asm (slot a) (slot b) #t kf))
(when rest (else
(emit-bind-rest asm (+ proc-slot 1 nreq))) (op asm (slot a) (slot b) #f kt)
(for-each (match-lambda (unless (eq? kf next-label)
((src . dst) (emit-mov asm dst src))) (emit-br asm kf)))))
(lookup-parallel-moves handler allocation)) (match exp
(emit-reset-frame asm nlocals) (($ $var sym) (unary emit-br-if-true sym))
(emit-br asm khandler-body))))) (($ $primcall 'null? (a)) (unary emit-br-if-null a))
(($ $primcall 'cache-current-module! (sym scope)) (($ $primcall 'nil? (a)) (unary emit-br-if-nil a))
(emit-cache-current-module! asm (slot sym) (constant scope))) (($ $primcall 'pair? (a)) (unary emit-br-if-pair a))
(($ $primcall 'free-set! (closure idx value)) (($ $primcall 'struct? (a)) (unary emit-br-if-struct a))
(emit-free-set! asm (slot closure) (slot value) (constant idx))) (($ $primcall 'char? (a)) (unary emit-br-if-char a))
(($ $primcall 'box-set! (box value)) (($ $primcall 'symbol? (a)) (unary emit-br-if-symbol a))
(emit-box-set! asm (slot box) (slot value))) (($ $primcall 'variable? (a)) (unary emit-br-if-variable a))
(($ $primcall 'struct-set! (struct index value)) (($ $primcall 'vector? (a)) (unary emit-br-if-vector a))
(emit-struct-set! asm (slot struct) (slot index) (slot value))) (($ $primcall 'string? (a)) (unary emit-br-if-string a))
(($ $primcall 'vector-set! (vector index value)) (($ $primcall 'bytevector? (a)) (unary emit-br-if-bytevector a))
(call-with-values (lambda () ;; Add more TC7 tests here. Keep in sync with
(lookup-maybe-constant-value index allocation)) ;; *branching-primcall-arities* in (language cps primitives) and
(lambda (has-const? index-val) ;; the set of macro-instructions in assembly.scm.
(if (and has-const? (integer? index-val) (exact? index-val) (($ $primcall 'eq? (a b)) (binary emit-br-if-eq a b))
(<= 0 index-val 255)) (($ $primcall 'eqv? (a b)) (binary emit-br-if-eqv a b))
(emit-constant-vector-set! asm (slot vector) index-val (($ $primcall 'equal? (a b)) (binary emit-br-if-equal a b))
(slot value)) (($ $primcall '< (a b)) (binary emit-br-if-< a b))
(emit-vector-set! asm (slot vector) (slot index) (($ $primcall '<= (a b)) (binary emit-br-if-<= a b))
(slot value)))))) (($ $primcall '= (a b)) (binary emit-br-if-= a b))
(($ $primcall 'variable-set! (var val)) (($ $primcall '>= (a b)) (binary emit-br-if-<= b a))
(emit-box-set! asm (slot var) (slot val))) (($ $primcall '> (a b)) (binary emit-br-if-< b a))))
(($ $primcall 'set-car! (pair value))
(emit-set-car! asm (slot pair) (slot value)))
(($ $primcall 'set-cdr! (pair value))
(emit-set-cdr! asm (slot pair) (slot value)))
(($ $primcall 'define! (sym value))
(emit-define! asm (slot sym) (slot value)))
(($ $primcall 'push-fluid (fluid val))
(emit-push-fluid asm (slot fluid) (slot val)))
(($ $primcall 'pop-fluid ())
(emit-pop-fluid asm))
(($ $primcall 'wind (winder unwinder))
(emit-wind asm (slot winder) (slot unwinder)))
(($ $primcall 'bv-u8-set! (bv idx val))
(emit-bv-u8-set! asm (slot bv) (slot idx) (slot val)))
(($ $primcall 'bv-u16-set! (bv idx val))
(emit-bv-u16-set! asm (slot bv) (slot idx) (slot val)))
(($ $primcall 'bv-s16-set! (bv idx val))
(emit-bv-s16-set! asm (slot bv) (slot idx) (slot val)))
(($ $primcall 'bv-u32-set! (bv idx val))
(emit-bv-u32-set! asm (slot bv) (slot idx) (slot val)))
(($ $primcall 'bv-s32-set! (bv idx val))
(emit-bv-s32-set! asm (slot bv) (slot idx) (slot val)))
(($ $primcall 'bv-u64-set! (bv idx val))
(emit-bv-u64-set! asm (slot bv) (slot idx) (slot val)))
(($ $primcall 'bv-s64-set! (bv idx val))
(emit-bv-s64-set! asm (slot bv) (slot idx) (slot val)))
(($ $primcall 'bv-f32-set! (bv idx val))
(emit-bv-f32-set! asm (slot bv) (slot idx) (slot val)))
(($ $primcall 'bv-f64-set! (bv idx val))
(emit-bv-f64-set! asm (slot bv) (slot idx) (slot val)))
(($ $primcall 'unwind ())
(emit-unwind asm))))
(define (compile-values label exp syms) (define (compile-trunc label exp nreq rest? nlocals)
(match exp (match exp
(($ $values args) (($ $call proc args)
(for-each (match-lambda (let ((proc-slot (lookup-call-proc-slot label allocation))
((src . dst) (emit-mov asm dst src))) (nargs (length args)))
(lookup-parallel-moves label allocation)) (or (maybe-load-constant proc-slot proc)
(for-each maybe-load-constant (map slot syms) args)))) (maybe-mov proc-slot (slot proc)))
(let lp ((n (1+ proc-slot)) (args args))
(match args
(()
(emit-call asm proc-slot (+ nargs 1))
;; FIXME: Only allow more values if there is a rest arg.
;; Express values truncation by the presence of an
;; unused rest arg instead of implicitly.
(emit-receive-values asm proc-slot #t nreq)
(when rest?
(emit-bind-rest asm (+ proc-slot 1 nreq)))
(for-each (match-lambda
((src . dst) (emit-mov asm dst src)))
(lookup-parallel-moves label allocation))
(emit-reset-frame asm nlocals))
((arg . args)
(or (maybe-load-constant n arg)
(maybe-mov n (slot arg)))
(lp (1+ n) args))))))))
(define (compile-test label exp kt kf next-label) (match f
(define (unary op sym) (($ $fun src meta free ($ $cont k ($ $kentry self tail clauses)))
(cond ;; FIXME: src on kentry instead?
((eq? kt next-label) (when src
(op asm (slot sym) #t kf)) (emit-source asm src))
(else (compile-entry (or meta '()))))))
(op asm (slot sym) #f kt)
(unless (eq? kf next-label)
(emit-br asm kf)))))
(define (binary op a b)
(cond
((eq? kt next-label)
(op asm (slot a) (slot b) #t kf))
(else
(op asm (slot a) (slot b) #f kt)
(unless (eq? kf next-label)
(emit-br asm kf)))))
(match exp
(($ $var sym) (unary emit-br-if-true sym))
(($ $primcall 'null? (a)) (unary emit-br-if-null a))
(($ $primcall 'nil? (a)) (unary emit-br-if-nil a))
(($ $primcall 'pair? (a)) (unary emit-br-if-pair a))
(($ $primcall 'struct? (a)) (unary emit-br-if-struct a))
(($ $primcall 'char? (a)) (unary emit-br-if-char a))
(($ $primcall 'symbol? (a)) (unary emit-br-if-symbol a))
(($ $primcall 'variable? (a)) (unary emit-br-if-variable a))
(($ $primcall 'vector? (a)) (unary emit-br-if-vector a))
(($ $primcall 'string? (a)) (unary emit-br-if-string a))
(($ $primcall 'bytevector? (a)) (unary emit-br-if-bytevector a))
;; Add more TC7 tests here. Keep in sync with
;; *branching-primcall-arities* in (language cps primitives) and
;; the set of macro-instructions in assembly.scm.
(($ $primcall 'eq? (a b)) (binary emit-br-if-eq a b))
(($ $primcall 'eqv? (a b)) (binary emit-br-if-eqv a b))
(($ $primcall 'equal? (a b)) (binary emit-br-if-equal a b))
(($ $primcall '< (a b)) (binary emit-br-if-< a b))
(($ $primcall '<= (a b)) (binary emit-br-if-<= a b))
(($ $primcall '= (a b)) (binary emit-br-if-= a b))
(($ $primcall '>= (a b)) (binary emit-br-if-<= b a))
(($ $primcall '> (a b)) (binary emit-br-if-< b a))))
(define (compile-trunc label exp nreq rest? nlocals)
(match exp
(($ $call proc args)
(let ((proc-slot (lookup-call-proc-slot label allocation))
(nargs (length args)))
(or (maybe-load-constant proc-slot proc)
(maybe-mov proc-slot (slot proc)))
(let lp ((n (1+ proc-slot)) (args args))
(match args
(()
(emit-call asm proc-slot (+ nargs 1))
;; FIXME: Only allow more values if there is a rest arg.
;; Express values truncation by the presence of an
;; unused rest arg instead of implicitly.
(emit-receive-values asm proc-slot #t nreq)
(when rest?
(emit-bind-rest asm (+ proc-slot 1 nreq)))
(for-each (match-lambda
((src . dst) (emit-mov asm dst src)))
(lookup-parallel-moves label allocation))
(emit-reset-frame asm nlocals))
((arg . args)
(or (maybe-load-constant n arg)
(maybe-mov n (slot arg)))
(lp (1+ n) args))))))))
(match f
(($ $fun meta free ($ $cont k src ($ $kentry self tail clauses)))
(compile-entry (or meta '()))))))))
(define (visit-funs proc exp) (define (visit-funs proc exp)
(match exp (match exp
(($ $continue _ exp) (($ $continue _ _ exp)
(visit-funs proc exp)) (visit-funs proc exp))
(($ $fun meta free body) (($ $fun src meta free body)
(proc exp) (proc exp)
(visit-funs proc body)) (visit-funs proc body))
@ -490,13 +482,13 @@
(visit-funs proc body) (visit-funs proc body)
(for-each (lambda (cont) (visit-funs proc cont)) conts)) (for-each (lambda (cont) (visit-funs proc cont)) conts))
(($ $cont sym src ($ $kargs names syms body)) (($ $cont sym ($ $kargs names syms body))
(visit-funs proc body)) (visit-funs proc body))
(($ $cont sym src ($ $kclause arity body)) (($ $cont sym ($ $kclause arity body))
(visit-funs proc body)) (visit-funs proc body))
(($ $cont sym src ($ $kentry self tail clauses)) (($ $cont sym ($ $kentry self tail clauses))
(for-each (lambda (clause) (visit-funs proc clause)) clauses)) (for-each (lambda (clause) (visit-funs proc clause)) clauses))
(_ (values)))) (_ (values))))

View file

@ -32,12 +32,12 @@
(define (inline-constructors fun) (define (inline-constructors fun)
(define (visit-cont cont) (define (visit-cont cont)
(rewrite-cps-cont cont (rewrite-cps-cont cont
(($ $cont sym src ($ $kargs names syms body)) (($ $cont sym ($ $kargs names syms body))
(sym src ($kargs names syms ,(visit-term body)))) (sym ($kargs names syms ,(visit-term body))))
(($ $cont sym src ($ $kentry self tail clauses)) (($ $cont sym ($ $kentry self tail clauses))
(sym src ($kentry self ,tail ,(map visit-cont clauses)))) (sym ($kentry self ,tail ,(map visit-cont clauses))))
(($ $cont sym src ($ $kclause arity body)) (($ $cont sym ($ $kclause arity body))
(sym src ($kclause ,arity ,(visit-cont body)))) (sym ($kclause ,arity ,(visit-cont body))))
(($ $cont) (($ $cont)
,cont))) ,cont)))
(define (visit-term term) (define (visit-term term)
@ -48,51 +48,51 @@
(($ $letrec names syms funs body) (($ $letrec names syms funs body)
($letrec names syms (map inline-constructors funs) ($letrec names syms (map inline-constructors funs)
,(visit-term body))) ,(visit-term body)))
(($ $continue k ($ $primcall 'list args)) (($ $continue k src ($ $primcall 'list args))
,(let-gensyms (kvalues val) ,(let-gensyms (kvalues val)
(build-cps-term (build-cps-term
($letk ((kvalues #f ($kargs ('val) (val) ($letk ((kvalues ($kargs ('val) (val)
($continue k ($continue k src
($primcall 'values (val)))))) ($primcall 'values (val))))))
,(let lp ((args args) (k kvalues)) ,(let lp ((args args) (k kvalues))
(match args (match args
(() (()
(build-cps-term (build-cps-term
($continue k ($const '())))) ($continue k src ($const '()))))
((arg . args) ((arg . args)
(let-gensyms (ktail tail) (let-gensyms (ktail tail)
(build-cps-term (build-cps-term
($letk ((ktail #f ($kargs ('tail) (tail) ($letk ((ktail ($kargs ('tail) (tail)
($continue k ($continue k src
($primcall 'cons (arg tail)))))) ($primcall 'cons (arg tail))))))
,(lp args ktail))))))))))) ,(lp args ktail)))))))))))
(($ $continue k ($ $primcall 'vector args)) (($ $continue k src ($ $primcall 'vector args))
,(let-gensyms (kalloc vec len init) ,(let-gensyms (kalloc vec len init)
(define (initialize args n) (define (initialize args n)
(match args (match args
(() (()
(build-cps-term (build-cps-term
($continue k ($primcall 'values (vec))))) ($continue k src ($primcall 'values (vec)))))
((arg . args) ((arg . args)
(let-gensyms (knext idx) (let-gensyms (knext idx)
(build-cps-term (build-cps-term
($letk ((knext #f ($kargs () () ($letk ((knext ($kargs () ()
,(initialize args (1+ n))))) ,(initialize args (1+ n)))))
($letconst (('idx idx n)) ($letconst (('idx idx n))
($continue knext ($continue knext src
($primcall 'vector-set! (vec idx arg)))))))))) ($primcall 'vector-set! (vec idx arg))))))))))
(build-cps-term (build-cps-term
($letk ((kalloc #f ($kargs ('vec) (vec) ($letk ((kalloc ($kargs ('vec) (vec)
,(initialize args 0)))) ,(initialize args 0))))
($letconst (('len len (length args)) ($letconst (('len len (length args))
('init init #f)) ('init init #f))
($continue kalloc ($continue kalloc src
($primcall 'make-vector (len init)))))))) ($primcall 'make-vector (len init))))))))
(($ $continue k (and fun ($ $fun))) (($ $continue k src (and fun ($ $fun)))
($continue k ,(inline-constructors fun))) ($continue k src ,(inline-constructors fun)))
(($ $continue) (($ $continue)
,term))) ,term)))
(rewrite-cps-exp fun (rewrite-cps-exp fun
(($ $fun meta free body) (($ $fun src meta free body)
($fun meta free ,(visit-cont body))))) ($fun src meta free ,(visit-cont body)))))

View file

@ -95,7 +95,7 @@
;; target continuation. Otherwise return #f. ;; target continuation. Otherwise return #f.
(define (call-target use proc) (define (call-target use proc)
(match (find-call (lookup-cont use cont-table)) (match (find-call (lookup-cont use cont-table))
(($ $continue k ($ $call proc* args)) (($ $continue k src ($ $call proc* args))
(and (eq? proc proc*) (not (memq proc args)) (applicable? proc args) (and (eq? proc proc*) (not (memq proc args)) (applicable? proc args)
k)) k))
(_ #f))) (_ #f)))
@ -141,7 +141,7 @@
;; bail. ;; bail.
(($ $kentry self tail clauses) (($ $kentry self tail clauses)
(match clauses (match clauses
((($ $cont _ _ ($ $kclause arity ($ $cont kargs)))) ((($ $cont _ ($ $kclause arity ($ $cont kargs))))
kargs) kargs)
(_ #f))) (_ #f)))
(_ scope))))) (_ scope)))))
@ -168,15 +168,15 @@
(define (visit-fun term) (define (visit-fun term)
(match term (match term
(($ $fun meta free body) (($ $fun src meta free body)
(visit-cont body)))) (visit-cont body))))
(define (visit-cont cont) (define (visit-cont cont)
(match cont (match cont
(($ $cont sym src ($ $kargs _ _ body)) (($ $cont sym ($ $kargs _ _ body))
(visit-term body sym)) (visit-term body sym))
(($ $cont sym src ($ $kentry self tail clauses)) (($ $cont sym ($ $kentry self tail clauses))
(for-each visit-cont clauses)) (for-each visit-cont clauses))
(($ $cont sym src ($ $kclause arity body)) (($ $cont sym ($ $kclause arity body))
(visit-cont body)) (visit-cont body))
(($ $cont) (($ $cont)
#t))) #t)))
@ -199,7 +199,7 @@
(if (null? rec) (if (null? rec)
'() '()
(list rec))) (list rec)))
(((and elt (n s ($ $fun meta free ($ $cont kentry)))) (((and elt (n s ($ $fun src meta free ($ $cont kentry))))
. nsf) . nsf)
(if (recursive? kentry) (if (recursive? kentry)
(lp nsf (cons elt rec)) (lp nsf (cons elt rec))
@ -208,11 +208,11 @@
(match component (match component
(((name sym fun) ...) (((name sym fun) ...)
(match fun (match fun
((($ $fun meta free ((($ $fun src meta free
($ $cont fun-k _ ($ $cont fun-k
($ $kentry self ($ $kentry self
($ $cont tail-k _ ($ $ktail)) ($ $cont tail-k ($ $ktail))
(($ $cont _ _ ($ $kclause arity body)) (($ $cont _ ($ $kclause arity body))
...)))) ...))))
...) ...)
(unless (contify-funs term-k sym self tail-k arity body) (unless (contify-funs term-k sym self tail-k arity body)
@ -220,13 +220,13 @@
(visit-term body term-k) (visit-term body term-k)
(for-each visit-component (for-each visit-component
(split-components (map list names syms funs)))) (split-components (map list names syms funs))))
(($ $continue k exp) (($ $continue k src exp)
(match exp (match exp
(($ $fun meta free (($ $fun src meta free
($ $cont fun-k _ ($ $cont fun-k
($ $kentry self ($ $kentry self
($ $cont tail-k _ ($ $ktail)) ($ $cont tail-k ($ $ktail))
(($ $cont _ _ ($ $kclause arity body)) ...)))) (($ $cont _ ($ $kclause arity body)) ...))))
(if (and=> (bound-symbol k) (if (and=> (bound-symbol k)
(lambda (sym) (lambda (sym)
(contify-fun term-k sym self tail-k arity body))) (contify-fun term-k sym self tail-k arity body)))
@ -238,7 +238,7 @@
(values call-substs cont-substs fun-elisions cont-splices))) (values call-substs cont-substs fun-elisions cont-splices)))
(define (apply-contification fun call-substs cont-substs fun-elisions cont-splices) (define (apply-contification fun call-substs cont-substs fun-elisions cont-splices)
(define (contify-call proc args) (define (contify-call src proc args)
(and=> (assq-ref call-substs proc) (and=> (assq-ref call-substs proc)
(lambda (clauses) (lambda (clauses)
(let lp ((clauses clauses)) (let lp ((clauses clauses))
@ -247,11 +247,11 @@
(((($ $arity req () #f () #f) . k) . clauses) (((($ $arity req () #f () #f) . k) . clauses)
(if (= (length req) (length args)) (if (= (length req) (length args))
(build-cps-term (build-cps-term
($continue k ($continue k src
($values args))) ($values args)))
(lp clauses))) (lp clauses)))
((_ . clauses) (lp clauses))))))) ((_ . clauses) (lp clauses)))))))
(define (continue k exp) (define (continue k src exp)
(define (lookup-return-cont k) (define (lookup-return-cont k)
(match (assq-ref cont-substs k) (match (assq-ref cont-substs k)
(#f k) (#f k)
@ -260,13 +260,13 @@
;; We are contifying this return. It must be a call or a ;; We are contifying this return. It must be a call or a
;; primcall to values, return, or return-values. ;; primcall to values, return, or return-values.
(if (eq? k k*) (if (eq? k k*)
(build-cps-term ($continue k ,exp)) (build-cps-term ($continue k src ,exp))
(rewrite-cps-term exp (rewrite-cps-term exp
(($ $primcall 'return (val)) (($ $primcall 'return (val))
($continue k* ($primcall 'values (val)))) ($continue k* src ($primcall 'values (val))))
(($ $values vals) (($ $values vals)
($continue k* ($primcall 'values vals))) ($continue k* src ($primcall 'values vals)))
(_ ($continue k* ,exp)))))) (_ ($continue k* src ,exp))))))
(define (splice-continuations term-k term) (define (splice-continuations term-k term)
(match (hashq-ref cont-splices term-k) (match (hashq-ref cont-splices term-k)
(#f term) (#f term)
@ -283,19 +283,19 @@
,body))))))) ,body)))))))
(define (visit-fun term) (define (visit-fun term)
(rewrite-cps-exp term (rewrite-cps-exp term
(($ $fun meta free body) (($ $fun src meta free body)
($fun meta free ,(visit-cont body))))) ($fun src meta free ,(visit-cont body)))))
(define (visit-cont cont) (define (visit-cont cont)
(rewrite-cps-cont cont (rewrite-cps-cont cont
(($ $cont (? (cut assq <> fun-elisions))) (($ $cont (? (cut assq <> fun-elisions)))
;; This cont gets inlined in place of the $fun. ;; This cont gets inlined in place of the $fun.
,#f) ,#f)
(($ $cont sym src ($ $kargs names syms body)) (($ $cont sym ($ $kargs names syms body))
(sym src ($kargs names syms ,(visit-term body sym)))) (sym ($kargs names syms ,(visit-term body sym))))
(($ $cont sym src ($ $kentry self tail clauses)) (($ $cont sym ($ $kentry self tail clauses))
(sym src ($kentry self ,tail ,(map visit-cont clauses)))) (sym ($kentry self ,tail ,(map visit-cont clauses))))
(($ $cont sym src ($ $kclause arity body)) (($ $cont sym ($ $kclause arity body))
(sym src ($kclause ,arity ,(visit-cont body)))) (sym ($kclause ,arity ,(visit-cont body))))
(($ $cont) (($ $cont)
,cont))) ,cont)))
(define (visit-term term term-k) (define (visit-term term term-k)
@ -324,7 +324,7 @@
(((names syms funs) ...) (((names syms funs) ...)
($letrec names syms (map visit-fun funs) ($letrec names syms (map visit-fun funs)
,(visit-term body term-k))))) ,(visit-term body term-k)))))
(($ $continue k exp) (($ $continue k src exp)
(splice-continuations (splice-continuations
term-k term-k
(match exp (match exp
@ -335,11 +335,11 @@
(($ $kargs (_) (_) body) (($ $kargs (_) (_) body)
(visit-term body k)))) (visit-term body k))))
(else (else
(continue k (visit-fun exp))))) (continue k src (visit-fun exp)))))
(($ $call proc args) (($ $call proc args)
(or (contify-call proc args) (or (contify-call src proc args)
(continue k exp))) (continue k src exp)))
(_ (continue k exp))))))) (_ (continue k src exp)))))))
(visit-fun fun)) (visit-fun fun))
(define (contify fun) (define (contify fun)

View file

@ -73,14 +73,14 @@
print-dfa)) print-dfa))
(define (build-cont-table fun) (define (build-cont-table fun)
(fold-conts (lambda (k src cont table) (fold-conts (lambda (k cont table)
(hashq-set! table k cont) (hashq-set! table k cont)
table) table)
(make-hash-table) (make-hash-table)
fun)) fun))
(define (build-local-cont-table cont) (define (build-local-cont-table cont)
(fold-local-conts (lambda (k src cont table) (fold-local-conts (lambda (k cont table)
(hashq-set! table k cont) (hashq-set! table k cont)
table) table)
(make-hash-table) (make-hash-table)
@ -206,10 +206,10 @@
(reachable-preds k-map block-preds)))) (reachable-preds k-map block-preds))))
(make-cfa k-map order preds))) (make-cfa k-map order preds)))
(match fun (match fun
(($ $fun meta free (($ $fun src meta free
($ $cont kentry src ($ $cont kentry
(and entry (and entry
($ $kentry self ($ $cont ktail _ tail) clauses)))) ($ $kentry self ($ $cont ktail tail) clauses))))
(if reverse? (if reverse?
(build-cfa ktail block-preds block-succs) (build-cfa ktail block-preds block-succs)
(build-cfa kentry block-succs block-preds))))) (build-cfa kentry block-succs block-preds)))))
@ -549,13 +549,13 @@
(map (cut hashq-ref mapping <>) (map (cut hashq-ref mapping <>)
((block-accessor blocks accessor) k)))) ((block-accessor blocks accessor) k))))
(match fun (match fun
(($ $fun meta free (($ $fun src meta free
(and entry (and entry
($ $cont kentry src ($ $kentry self ($ $cont ktail _ tail))))) ($ $cont kentry ($ $kentry self ($ $cont ktail tail)))))
(call-with-values (lambda () (make-variable-mapping (dfg-use-maps dfg))) (call-with-values (lambda () (make-variable-mapping (dfg-use-maps dfg)))
(lambda (var-map nvars) (lambda (var-map nvars)
(define (fold-all-conts f seed) (define (fold-all-conts f seed)
(fold-local-conts (lambda (k src cont seed) (f k seed)) (fold-local-conts (lambda (k cont seed) (f k seed))
seed entry)) seed entry))
(let* ((blocks (dfg-blocks dfg)) (let* ((blocks (dfg-blocks dfg))
(order (reverse-post-order ktail (order (reverse-post-order ktail
@ -662,7 +662,7 @@
(define (recur exp) (define (recur exp)
(visit exp exp-k)) (visit exp exp-k))
(match exp (match exp
(($ $letk (($ $cont k src cont) ...) body) (($ $letk (($ $cont k cont) ...) body)
;; Set up recursive environment before visiting cont bodies. ;; Set up recursive environment before visiting cont bodies.
(for-each (lambda (cont k) (for-each (lambda (cont k)
(declare-block! k cont exp-k)) (declare-block! k cont exp-k))
@ -688,7 +688,7 @@
(for-each (cut visit-fun <> conts blocks use-maps global?) funs) (for-each (cut visit-fun <> conts blocks use-maps global?) funs)
(visit body exp-k)) (visit body exp-k))
(($ $continue k exp) (($ $continue k src exp)
(use-k! k) (use-k! k)
(match exp (match exp
(($ $var sym) (($ $var sym)
@ -726,10 +726,10 @@
(_ #f))))) (_ #f)))))
(match fun (match fun
(($ $fun meta free (($ $fun src meta free
($ $cont kentry src ($ $cont kentry
(and entry (and entry
($ $kentry self ($ $cont ktail _ tail) clauses)))) ($ $kentry self ($ $cont ktail tail) clauses))))
(declare-block! kentry entry #f 0) (declare-block! kentry entry #f 0)
(add-def! #f self kentry) (add-def! #f self kentry)
@ -737,8 +737,8 @@
(for-each (for-each
(match-lambda (match-lambda
(($ $cont kclause _ (($ $cont kclause
(and clause ($ $kclause arity ($ $cont kbody _ body)))) (and clause ($ $kclause arity ($ $cont kbody body))))
(declare-block! kclause clause kentry) (declare-block! kclause clause kentry)
(link-blocks! kentry kclause) (link-blocks! kentry kclause)
@ -811,7 +811,7 @@
(define (call-expression call) (define (call-expression call)
(match call (match call
(($ $continue k exp) exp))) (($ $continue k src exp) exp)))
(define (find-expression term) (define (find-expression term)
(call-expression (find-call term))) (call-expression (find-call term)))
@ -827,7 +827,7 @@
(match (find-defining-expression sym dfg) (match (find-defining-expression sym dfg)
(($ $const val) (($ $const val)
(values #t val)) (values #t val))
(($ $continue k ($ $void)) (($ $continue k src ($ $void))
(values #t *unspecified*)) (values #t *unspecified*))
(else (else
(values #f #f)))) (values #f #f))))

View file

@ -37,15 +37,15 @@
(define (elide-values fun) (define (elide-values fun)
(let ((conts (build-local-cont-table (let ((conts (build-local-cont-table
(match fun (($ $fun meta free body) body))))) (match fun (($ $fun src meta free body) body)))))
(define (visit-cont cont) (define (visit-cont cont)
(rewrite-cps-cont cont (rewrite-cps-cont cont
(($ $cont sym src ($ $kargs names syms body)) (($ $cont sym ($ $kargs names syms body))
(sym src ($kargs names syms ,(visit-term body)))) (sym ($kargs names syms ,(visit-term body))))
(($ $cont sym src ($ $kentry self tail clauses)) (($ $cont sym ($ $kentry self tail clauses))
(sym src ($kentry self ,tail ,(map visit-cont clauses)))) (sym ($kentry self ,tail ,(map visit-cont clauses))))
(($ $cont sym src ($ $kclause arity body)) (($ $cont sym ($ $kclause arity body))
(sym src ($kclause ,arity ,(visit-cont body)))) (sym ($kclause ,arity ,(visit-cont body))))
(($ $cont) (($ $cont)
,cont))) ,cont)))
(define (visit-term term) (define (visit-term term)
@ -56,27 +56,27 @@
(($ $letrec names syms funs body) (($ $letrec names syms funs body)
($letrec names syms (map elide-values funs) ($letrec names syms (map elide-values funs)
,(visit-term body))) ,(visit-term body)))
(($ $continue k ($ $primcall 'values vals)) (($ $continue k src ($ $primcall 'values vals))
,(rewrite-cps-term (lookup-cont k conts) ,(rewrite-cps-term (lookup-cont k conts)
(($ $ktail) (($ $ktail)
($continue k ($values vals))) ($continue k src ($values vals)))
(($ $ktrunc ($ $arity req () rest () #f) kargs) (($ $ktrunc ($ $arity req () rest () #f) kargs)
,(if (or rest (< (length vals) (length req))) ,(if (or rest (< (length vals) (length req)))
term term
(let ((vals (list-head vals (length req)))) (let ((vals (list-head vals (length req))))
(build-cps-term (build-cps-term
($continue kargs ($values vals)))))) ($continue kargs src ($values vals))))))
(($ $kargs args) (($ $kargs args)
,(if (< (length vals) (length args)) ,(if (< (length vals) (length args))
term term
(let ((vals (list-head vals (length args)))) (let ((vals (list-head vals (length args))))
(build-cps-term (build-cps-term
($continue k ($values vals)))))))) ($continue k src ($values vals))))))))
(($ $continue k (and fun ($ $fun))) (($ $continue k src (and fun ($ $fun)))
($continue k ,(elide-values fun))) ($continue k src ,(elide-values fun)))
(($ $continue) (($ $continue)
,term))) ,term)))
(rewrite-cps-exp fun (rewrite-cps-exp fun
(($ $fun meta free body) (($ $fun src meta free body)
($fun meta free ,(visit-cont body)))))) ($fun src meta free ,(visit-cont body))))))

View file

@ -39,8 +39,8 @@
('name name-sym name) ('name name-sym name)
('public? public?-sym public?) ('public? public?-sym public?)
('bound? bound?-sym bound?)) ('bound? bound?-sym bound?))
($letk ((kbox src ($kargs ('box) (box) ,(val-proc box)))) ($letk ((kbox ($kargs ('box) (box) ,(val-proc box))))
($continue kbox ($continue kbox src
($primcall 'cached-module-box ($primcall 'cached-module-box
(module-sym name-sym public?-sym bound?-sym)))))))) (module-sym name-sym public?-sym bound?-sym))))))))
@ -72,63 +72,61 @@
((class-of @slot-ref @slot-set!) '(oop goops)) ((class-of @slot-ref @slot-set!) '(oop goops))
(else '(guile)))) (else '(guile))))
(define (primitive-ref name k) (define (primitive-ref name k src)
(module-box #f (primitive-module name) name #f #t (module-box #f (primitive-module name) name #f #t
(lambda (box) (lambda (box)
(build-cps-term (build-cps-term
($continue k ($primcall 'box-ref (box))))))) ($continue k src ($primcall 'box-ref (box)))))))
(define (builtin-ref idx k) (define (builtin-ref idx k src)
(let-gensyms (idx-sym) (let-gensyms (idx-sym)
(build-cps-term (build-cps-term
($letconst (('idx idx-sym idx)) ($letconst (('idx idx-sym idx))
($continue k ($continue k src
($primcall 'builtin-ref (idx-sym))))))) ($primcall 'builtin-ref (idx-sym)))))))
(define (reify-clause ktail) (define (reify-clause ktail)
(let-gensyms (kclause kbody wna false str eol kthrow throw) (let-gensyms (kclause kbody wna false str eol kthrow throw)
(build-cps-cont (build-cps-cont
(kclause #f ($kclause ('() '() #f '() #f) (kclause ($kclause ('() '() #f '() #f)
(kbody (kbody
#f ($kargs () ()
($kargs () () ($letconst (('wna wna 'wrong-number-of-args)
($letconst (('wna wna 'wrong-number-of-args) ('false false #f)
('false false #f) ('str str "Wrong number of arguments")
('str str "Wrong number of arguments") ('eol eol '()))
('eol eol '())) ($letk ((kthrow
($letk ((kthrow ($kargs ('throw) (throw)
#f ($continue ktail #f
($kargs ('throw) (throw) ($call throw
($continue ktail (wna false str eol false))))))
($call throw ,(primitive-ref 'throw kthrow #f))))))))))
(wna false str eol false))))))
,(primitive-ref 'throw kthrow))))))))))
;; FIXME: Operate on one function at a time, for efficiency. ;; FIXME: Operate on one function at a time, for efficiency.
(define (reify-primitives fun) (define (reify-primitives fun)
(let ((conts (build-cont-table fun))) (let ((conts (build-cont-table fun)))
(define (visit-fun term) (define (visit-fun term)
(rewrite-cps-exp term (rewrite-cps-exp term
(($ $fun meta free body) (($ $fun src meta free body)
($fun meta free ,(visit-cont body))))) ($fun src meta free ,(visit-cont body)))))
(define (visit-cont cont) (define (visit-cont cont)
(rewrite-cps-cont cont (rewrite-cps-cont cont
(($ $cont sym src ($ $kargs names syms body)) (($ $cont sym ($ $kargs names syms body))
(sym src ($kargs names syms ,(visit-term body)))) (sym ($kargs names syms ,(visit-term body))))
(($ $cont sym src ($ $kentry self (and tail ($ $cont ktail)) ())) (($ $cont sym ($ $kentry self (and tail ($ $cont ktail)) ()))
;; A case-lambda with no clauses. Reify a clause. ;; A case-lambda with no clauses. Reify a clause.
(sym src ($kentry self ,tail (,(reify-clause ktail))))) (sym ($kentry self ,tail (,(reify-clause ktail)))))
(($ $cont sym src ($ $kentry self tail clauses)) (($ $cont sym ($ $kentry self tail clauses))
(sym src ($kentry self ,tail ,(map visit-cont clauses)))) (sym ($kentry self ,tail ,(map visit-cont clauses))))
(($ $cont sym src ($ $kclause arity body)) (($ $cont sym ($ $kclause arity body))
(sym src ($kclause ,arity ,(visit-cont body)))) (sym ($kclause ,arity ,(visit-cont body))))
(($ $cont) (($ $cont)
,cont))) ,cont)))
(define (visit-term term) (define (visit-term term)
(rewrite-cps-term term (rewrite-cps-term term
(($ $letk conts body) (($ $letk conts body)
($letk ,(map visit-cont conts) ,(visit-term body))) ($letk ,(map visit-cont conts) ,(visit-term body)))
(($ $continue k exp) (($ $continue k src exp)
,(match exp ,(match exp
(($ $prim name) (($ $prim name)
(match (lookup-cont k conts) (match (lookup-cont k conts)
@ -136,14 +134,14 @@
(cond (cond
((builtin-name->index name) ((builtin-name->index name)
=> (lambda (idx) => (lambda (idx)
(builtin-ref idx k))) (builtin-ref idx k src)))
(else (primitive-ref name k)))) (else (primitive-ref name k src))))
(_ (build-cps-term ($continue k ($void)))))) (_ (build-cps-term ($continue k src ($void))))))
(($ $fun) (($ $fun)
(build-cps-term ($continue k ,(visit-fun exp)))) (build-cps-term ($continue k src ,(visit-fun exp))))
(($ $primcall 'call-thunk/no-inline (proc)) (($ $primcall 'call-thunk/no-inline (proc))
(build-cps-term (build-cps-term
($continue k ($call proc ())))) ($continue k src ($call proc ()))))
(($ $primcall name args) (($ $primcall name args)
(cond (cond
((or (prim-rtl-instruction name) (branching-primitive? name)) ((or (prim-rtl-instruction name) (branching-primitive? name))
@ -152,13 +150,13 @@
(else (else
(let-gensyms (k* v) (let-gensyms (k* v)
(build-cps-term (build-cps-term
($letk ((k* #f ($kargs (v) (v) ($letk ((k* ($kargs (v) (v)
($continue k ($call v args))))) ($continue k src ($call v args)))))
,(cond ,(cond
((builtin-name->index name) ((builtin-name->index name)
=> (lambda (idx) => (lambda (idx)
(builtin-ref idx k*))) (builtin-ref idx k* src)))
(else (primitive-ref name k*))))))))) (else (primitive-ref name k* src)))))))))
(_ term))))) (_ term)))))
(visit-fun fun))) (visit-fun fun)))

View file

@ -235,7 +235,7 @@ are comparable with eqv?. A tmp slot may be used."
(define nlocals (compute-slot live-slots #f)) (define nlocals (compute-slot live-slots #f))
(define nargs (define nargs
(match clause (match clause
(($ $cont _ _ ($ $kclause _ ($ $cont _ _ ($ $kargs names syms)))) (($ $cont _ ($ $kclause _ ($ $cont _ ($ $kargs names syms))))
(length syms)))) (length syms))))
(define (allocate! sym k hint live-slots) (define (allocate! sym k hint live-slots)
@ -310,7 +310,7 @@ are comparable with eqv?. A tmp slot may be used."
live-slots)) live-slots))
(match cont (match cont
(($ $kclause arity ($ $cont k src body)) (($ $kclause arity ($ $cont k body))
(visit-cont body k live-slots)) (visit-cont body k live-slots))
(($ $kargs names syms body) (($ $kargs names syms body)
@ -328,12 +328,12 @@ are comparable with eqv?. A tmp slot may be used."
(($ $letk conts body) (($ $letk conts body)
(let ((live-slots (visit-term body label live-slots))) (let ((live-slots (visit-term body label live-slots)))
(for-each (match-lambda (for-each (match-lambda
(($ $cont k src cont) (($ $cont k cont)
(visit-cont cont k live-slots))) (visit-cont cont k live-slots)))
conts)) conts))
live-slots) live-slots)
(($ $continue k exp) (($ $continue k src exp)
(visit-exp exp label k live-slots)))) (visit-exp exp label k live-slots))))
(define (visit-exp exp label k live-slots) (define (visit-exp exp label k live-slots)
@ -420,12 +420,12 @@ are comparable with eqv?. A tmp slot may be used."
(_ live-slots))) (_ live-slots)))
(match clause (match clause
(($ $cont k _ body) (($ $cont k body)
(visit-cont body k live-slots) (visit-cont body k live-slots)
(hashq-set! allocation k nlocals)))) (hashq-set! allocation k nlocals))))
(match fun (match fun
(($ $fun meta free ($ $cont k _ ($ $kentry self tail clauses))) (($ $fun src meta free ($ $cont k ($ $kentry self tail clauses)))
(let* ((dfa (compute-live-variables fun dfg)) (let* ((dfa (compute-live-variables fun dfg))
(allocation (make-hash-table)) (allocation (make-hash-table))
(slots (make-vector (dfa-var-count dfa) #f)) (slots (make-vector (dfa-var-count dfa) #f))

View file

@ -71,7 +71,7 @@
(define (visit-clause clause k-env v-env) (define (visit-clause clause k-env v-env)
(match clause (match clause
(($ $cont kclause src* (($ $cont kclause
($ $kclause ($ $kclause
($ $arity ($ $arity
((? symbol? req) ...) ((? symbol? req) ...)
@ -79,9 +79,7 @@
(and rest (or #f (? symbol?))) (and rest (or #f (? symbol?)))
(((? keyword? kw) (? symbol? kwname) (? symbol? kwsym)) ...) (((? keyword? kw) (? symbol? kwname) (? symbol? kwsym)) ...)
(or #f #t)) (or #f #t))
($ $cont kbody src (and body ($ $kargs names syms _))))) ($ $cont kbody (and body ($ $kargs names syms _)))))
(check-src src*)
(check-src src)
(for-each (lambda (sym) (for-each (lambda (sym)
(unless (memq sym syms) (unless (memq sym syms)
(error "bad keyword sym" sym))) (error "bad keyword sym" sym)))
@ -98,9 +96,9 @@
(define (visit-fun fun k-env v-env) (define (visit-fun fun k-env v-env)
(match fun (match fun
(($ $fun meta ((? symbol? free) ...) (($ $fun src meta ((? symbol? free) ...)
($ $cont kbody src ($ $cont kbody
($ $kentry (? symbol? self) ($ $cont ktail _ ($ $ktail)) clauses))) ($ $kentry (? symbol? self) ($ $cont ktail ($ $ktail)) clauses)))
(when (and meta (not (and (list? meta) (and-map pair? meta)))) (when (and meta (not (and (list? meta) (and-map pair? meta))))
(error "meta should be alist" meta)) (error "meta should be alist" meta))
(for-each (cut check-var <> v-env) free) (for-each (cut check-var <> v-env) free)
@ -142,9 +140,8 @@
(define (visit-term term k-env v-env) (define (visit-term term k-env v-env)
(match term (match term
(($ $letk (($ $cont (? symbol? k) src cont) ...) body) (($ $letk (($ $cont (? symbol? k) cont) ...) body)
(let ((k-env (add-env k k-env))) (let ((k-env (add-env k k-env)))
(for-each check-src src)
(for-each (cut visit-cont-body <> k-env v-env) cont) (for-each (cut visit-cont-body <> k-env v-env) cont)
(visit-term body k-env v-env))) (visit-term body k-env v-env)))
@ -155,8 +152,9 @@
(for-each (cut visit-fun <> k-env v-env) fun) (for-each (cut visit-fun <> k-env v-env) fun)
(visit-term body k-env v-env))) (visit-term body k-env v-env)))
(($ $continue k exp) (($ $continue k src exp)
(check-var k k-env) (check-var k k-env)
(check-src src)
(visit-expression exp k-env v-env)) (visit-expression exp k-env v-env))
(_ (_

View file

@ -81,18 +81,18 @@
(build-cps-term (build-cps-term
($letconst (('name name-sym name) ($letconst (('name name-sym name)
('bound? bound?-sym bound?)) ('bound? bound?-sym bound?))
($letk ((kbox src ($kargs ('box) (box) ,(val-proc box)))) ($letk ((kbox ($kargs ('box) (box) ,(val-proc box))))
,(match (current-topbox-scope) ,(match (current-topbox-scope)
(#f (#f
(build-cps-term (build-cps-term
($continue kbox ($continue kbox src
($primcall 'resolve ($primcall 'resolve
(name-sym bound?-sym))))) (name-sym bound?-sym)))))
(scope (scope
(let-gensyms (scope-sym) (let-gensyms (scope-sym)
(build-cps-term (build-cps-term
($letconst (('scope scope-sym scope)) ($letconst (('scope scope-sym scope))
($continue kbox ($continue kbox src
($primcall 'cached-toplevel-box ($primcall 'cached-toplevel-box
(scope-sym name-sym bound?-sym))))))))))))) (scope-sym name-sym bound?-sym)))))))))))))
@ -103,8 +103,8 @@
('name name-sym name) ('name name-sym name)
('public? public?-sym public?) ('public? public?-sym public?)
('bound? bound?-sym bound?)) ('bound? bound?-sym bound?))
($letk ((kbox src ($kargs ('box) (box) ,(val-proc box)))) ($letk ((kbox ($kargs ('box) (box) ,(val-proc box))))
($continue kbox ($continue kbox src
($primcall 'cached-module-box ($primcall 'cached-module-box
(module-sym name-sym public?-sym bound?-sym)))))))) (module-sym name-sym public?-sym bound?-sym))))))))
@ -112,11 +112,11 @@
(let-gensyms (module scope-sym kmodule) (let-gensyms (module scope-sym kmodule)
(build-cps-term (build-cps-term
($letconst (('scope scope-sym scope)) ($letconst (('scope scope-sym scope))
($letk ((kmodule src ($kargs ('module) (module) ($letk ((kmodule ($kargs ('module) (module)
($continue k ($continue k src
($primcall 'cache-current-module! ($primcall 'cache-current-module!
(module scope-sym)))))) (module scope-sym))))))
($continue kmodule ($continue kmodule src
($primcall 'current-module ()))))))) ($primcall 'current-module ())))))))
(define (fold-formals proc seed arity gensyms inits) (define (fold-formals proc seed arity gensyms inits)
@ -162,8 +162,8 @@
(let-gensyms (unbound ktest) (let-gensyms (unbound ktest)
(build-cps-term (build-cps-term
($letconst (('unbound unbound (pointer->scm (make-pointer unbound-bits)))) ($letconst (('unbound unbound (pointer->scm (make-pointer unbound-bits))))
($letk ((ktest src ($kif kt kf))) ($letk ((ktest ($kif kt kf)))
($continue ktest ($continue ktest src
($primcall 'eq? (sym unbound)))))))) ($primcall 'eq? (sym unbound))))))))
(define (init-default-value name sym subst init body) (define (init-default-value name sym subst init body)
@ -174,19 +174,19 @@
(if box? (if box?
(let-gensyms (kbox phi) (let-gensyms (kbox phi)
(build-cps-term (build-cps-term
($letk ((kbox src ($kargs (name) (phi) ($letk ((kbox ($kargs (name) (phi)
($continue k ($primcall 'box (phi)))))) ($continue k src ($primcall 'box (phi))))))
,(make-body kbox)))) ,(make-body kbox))))
(make-body k))) (make-body k)))
(let-gensyms (knext kbound kunbound) (let-gensyms (knext kbound kunbound)
(build-cps-term (build-cps-term
($letk ((knext src ($kargs (name) (subst-sym) ,body))) ($letk ((knext ($kargs (name) (subst-sym) ,body)))
,(maybe-box ,(maybe-box
knext knext
(lambda (k) (lambda (k)
(build-cps-term (build-cps-term
($letk ((kbound src ($kargs () () ($continue k ($var sym)))) ($letk ((kbound ($kargs () () ($continue k src ($var sym))))
(kunbound src ($kargs () () ,(convert init k subst)))) (kunbound ($kargs () () ,(convert init k subst))))
,(unbound? src sym kunbound kbound)))))))))))) ,(unbound? src sym kunbound kbound))))))))))))
;; exp k-name alist -> term ;; exp k-name alist -> term
@ -199,16 +199,15 @@
((box #t) ((box #t)
(let-gensyms (kunboxed unboxed) (let-gensyms (kunboxed unboxed)
(build-cps-term (build-cps-term
($letk ((kunboxed src ($kargs ('unboxed) (unboxed) ,(k unboxed)))) ($letk ((kunboxed ($kargs ('unboxed) (unboxed) ,(k unboxed))))
($continue kunboxed ($primcall 'box-ref (box))))))) ($continue kunboxed src ($primcall 'box-ref (box)))))))
((subst #f) (k subst)) ((subst #f) (k subst))
(#f (k sym)))) (#f (k sym))))
(else (else
(let ((src (tree-il-src exp))) (let-gensyms (karg arg)
(let-gensyms (karg arg) (build-cps-term
(build-cps-term ($letk ((karg ($kargs ('arg) (arg) ,(k arg))))
($letk ((karg src ($kargs ('arg) (arg) ,(k arg)))) ,(convert exp karg subst)))))))
,(convert exp karg subst))))))))
;; (exp ...) ((v-name ...) -> term) -> term ;; (exp ...) ((v-name ...) -> term) -> term
(define (convert-args exps k) (define (convert-args exps k)
(match exps (match exps
@ -224,25 +223,25 @@
((box #t) ((box #t)
(let-gensyms (k) (let-gensyms (k)
(build-cps-term (build-cps-term
($letk ((k #f ($kargs (name) (box) ,body))) ($letk ((k ($kargs (name) (box) ,body)))
($continue k ($primcall 'box (sym))))))) ($continue k #f ($primcall 'box (sym)))))))
(else body))) (else body)))
(match exp (match exp
(($ <lexical-ref> src name sym) (($ <lexical-ref> src name sym)
(match (assq-ref subst sym) (match (assq-ref subst sym)
((box #t) (build-cps-term ($continue k ($primcall 'box-ref (box))))) ((box #t) (build-cps-term ($continue k src ($primcall 'box-ref (box)))))
((subst #f) (build-cps-term ($continue k ($var subst)))) ((subst #f) (build-cps-term ($continue k src ($var subst))))
(#f (build-cps-term ($continue k ($var sym)))))) (#f (build-cps-term ($continue k src ($var sym))))))
(($ <void> src) (($ <void> src)
(build-cps-term ($continue k ($void)))) (build-cps-term ($continue k src ($void))))
(($ <const> src exp) (($ <const> src exp)
(build-cps-term ($continue k ($const exp)))) (build-cps-term ($continue k src ($const exp))))
(($ <primitive-ref> src name) (($ <primitive-ref> src name)
(build-cps-term ($continue k ($prim name)))) (build-cps-term ($continue k src ($prim name))))
(($ <lambda> fun-src meta body) (($ <lambda> fun-src meta body)
(let () (let ()
@ -260,10 +259,8 @@
(let-gensyms (kclause kargs) (let-gensyms (kclause kargs)
(build-cps-cont (build-cps-cont
(kclause (kclause
src
($kclause ,arity ($kclause ,arity
(kargs (kargs
src
($kargs names gensyms ($kargs names gensyms
,(fold-formals ,(fold-formals
(lambda (name sym init body) (lambda (name sym init body)
@ -276,15 +273,13 @@
(if (current-topbox-scope) (if (current-topbox-scope)
(let-gensyms (kentry self ktail) (let-gensyms (kentry self ktail)
(build-cps-term (build-cps-term
($continue k ($continue k fun-src
($fun meta '() ($fun fun-src meta '()
(kentry fun-src (kentry ($kentry self (ktail ($ktail))
($kentry self (ktail #f ($ktail)) ,(convert-clauses body ktail)))))))
,(convert-clauses body ktail)))))))
(let-gensyms (scope kscope) (let-gensyms (scope kscope)
(build-cps-term (build-cps-term
($letk ((kscope fun-src ($letk ((kscope ($kargs () ()
($kargs () ()
,(parameterize ((current-topbox-scope scope)) ,(parameterize ((current-topbox-scope scope))
(convert exp k subst))))) (convert exp k subst)))))
,(capture-toplevel-scope fun-src scope kscope))))))) ,(capture-toplevel-scope fun-src scope kscope)))))))
@ -293,7 +288,7 @@
(module-box (module-box
src mod name public? #t src mod name public? #t
(lambda (box) (lambda (box)
(build-cps-term ($continue k ($primcall 'box-ref (box))))))) (build-cps-term ($continue k src ($primcall 'box-ref (box)))))))
(($ <module-set> src mod name public? exp) (($ <module-set> src mod name public? exp)
(convert-arg exp (convert-arg exp
@ -301,13 +296,14 @@
(module-box (module-box
src mod name public? #f src mod name public? #f
(lambda (box) (lambda (box)
(build-cps-term ($continue k ($primcall 'box-set! (box val))))))))) (build-cps-term
($continue k src ($primcall 'box-set! (box val)))))))))
(($ <toplevel-ref> src name) (($ <toplevel-ref> src name)
(toplevel-box (toplevel-box
src name #t src name #t
(lambda (box) (lambda (box)
(build-cps-term ($continue k ($primcall 'box-ref (box))))))) (build-cps-term ($continue k src ($primcall 'box-ref (box)))))))
(($ <toplevel-set> src name exp) (($ <toplevel-set> src name exp)
(convert-arg exp (convert-arg exp
@ -315,7 +311,8 @@
(toplevel-box (toplevel-box
src name #f src name #f
(lambda (box) (lambda (box)
(build-cps-term ($continue k ($primcall 'box-set! (box val))))))))) (build-cps-term
($continue k src ($primcall 'box-set! (box val)))))))))
(($ <toplevel-define> src name exp) (($ <toplevel-define> src name exp)
(convert-arg exp (convert-arg exp
@ -323,13 +320,13 @@
(let-gensyms (kname name-sym) (let-gensyms (kname name-sym)
(build-cps-term (build-cps-term
($letconst (('name name-sym name)) ($letconst (('name name-sym name))
($continue k ($primcall 'define! (name-sym val))))))))) ($continue k src ($primcall 'define! (name-sym val)))))))))
(($ <call> src proc args) (($ <call> src proc args)
(convert-args (cons proc args) (convert-args (cons proc args)
(match-lambda (match-lambda
((proc . args) ((proc . args)
(build-cps-term ($continue k ($call proc args))))))) (build-cps-term ($continue k src ($call proc args)))))))
(($ <primcall> src name args) (($ <primcall> src name args)
(cond (cond
@ -389,22 +386,21 @@
(match args (match args
(() (()
(build-cps-term (build-cps-term
($continue k ($const '())))) ($continue k src ($const '()))))
((arg . args) ((arg . args)
(let-gensyms (ktail tail) (let-gensyms (ktail tail)
(build-cps-term (build-cps-term
($letk ((ktail src ($letk ((ktail ($kargs ('tail) (tail)
($kargs ('tail) (tail)
,(convert-arg arg ,(convert-arg arg
(lambda (head) (lambda (head)
(build-cps-term (build-cps-term
($continue k ($continue k src
($primcall 'cons (head tail))))))))) ($primcall 'cons (head tail)))))))))
,(lp args ktail)))))))) ,(lp args ktail))))))))
(else (else
(convert-args args (convert-args args
(lambda (args) (lambda (args)
(build-cps-term ($continue k ($primcall name args)))))))) (build-cps-term ($continue k src ($primcall name args))))))))
;; Prompts with inline handlers. ;; Prompts with inline handlers.
(($ <prompt> src escape-only? tag body (($ <prompt> src escape-only? tag body
@ -427,42 +423,38 @@
(let ((hnames (append hreq (if hrest (list hrest) '())))) (let ((hnames (append hreq (if hrest (list hrest) '()))))
(let-gensyms (khargs khbody kret kprim prim kpop krest vals kbody) (let-gensyms (khargs khbody kret kprim prim kpop krest vals kbody)
(build-cps-term (build-cps-term
($letk* ((khbody hsrc ($kargs hnames hsyms ;; FIXME: Attach hsrc to $ktrunc.
,(fold box-bound-var ($letk* ((khbody ($kargs hnames hsyms
(convert hbody k subst) ,(fold box-bound-var
hnames hsyms))) (convert hbody k subst)
(khargs hsrc ($ktrunc hreq hrest khbody)) hnames hsyms)))
(kpop src (khargs ($ktrunc hreq hrest khbody))
($kargs ('rest) (vals) (kpop ($kargs ('rest) (vals)
($letk ((kret ($letk ((kret
src
($kargs () () ($kargs () ()
($letk ((kprim ($letk ((kprim
src
($kargs ('prim) (prim) ($kargs ('prim) (prim)
($continue k ($continue k src
($primcall 'apply ($primcall 'apply
(prim vals)))))) (prim vals))))))
($continue kprim ($continue kprim src
($prim 'values)))))) ($prim 'values))))))
($continue kret ($continue kret src
($primcall 'unwind ()))))) ($primcall 'unwind ())))))
(krest src ($ktrunc '() 'rest kpop))) (krest ($ktrunc '() 'rest kpop)))
,(if escape-only? ,(if escape-only?
(build-cps-term (build-cps-term
($letk ((kbody (tree-il-src body) ($letk ((kbody ($kargs () ()
($kargs () ()
,(convert body krest subst)))) ,(convert body krest subst))))
($continue kbody ($prompt #t tag khargs kpop)))) ($continue kbody src ($prompt #t tag khargs kpop))))
(convert-arg body (convert-arg body
(lambda (thunk) (lambda (thunk)
(build-cps-term (build-cps-term
($letk ((kbody (tree-il-src body) ($letk ((kbody ($kargs () ()
($kargs () () ($continue krest (tree-il-src body)
($continue krest
($primcall 'call-thunk/no-inline ($primcall 'call-thunk/no-inline
(thunk)))))) (thunk))))))
($continue kbody ($continue kbody (tree-il-src body)
($prompt #f tag khargs kpop)))))))))))))) ($prompt #f tag khargs kpop))))))))))))))
;; Eta-convert prompts without inline handlers. ;; Eta-convert prompts without inline handlers.
@ -503,7 +495,8 @@
(convert-args (cons tag args) (convert-args (cons tag args)
(lambda (args*) (lambda (args*)
(build-cps-term (build-cps-term
($continue k ($primcall 'abort-to-prompt args*)))))) ($continue k src
($primcall 'abort-to-prompt args*))))))
(($ <abort> src tag args tail) (($ <abort> src tag args tail)
(convert-args (append (list (make-primitive-ref #f 'abort-to-prompt) (convert-args (append (list (make-primitive-ref #f 'abort-to-prompt)
@ -512,24 +505,24 @@
(list tail)) (list tail))
(lambda (args*) (lambda (args*)
(build-cps-term (build-cps-term
($continue k ($primcall 'apply args*)))))) ($continue k src ($primcall 'apply args*))))))
(($ <conditional> src test consequent alternate) (($ <conditional> src test consequent alternate)
(let-gensyms (kif kt kf) (let-gensyms (kif kt kf)
(build-cps-term (build-cps-term
($letk* ((kt (tree-il-src consequent) ($kargs () () ($letk* ((kt ($kargs () () ,(convert consequent k subst)))
,(convert consequent k subst))) (kf ($kargs () () ,(convert alternate k subst)))
(kf (tree-il-src alternate) ($kargs () () (kif ($kif kt kf)))
,(convert alternate k subst)))
(kif src ($kif kt kf)))
,(match test ,(match test
(($ <primcall> src (? branching-primitive? name) args) (($ <primcall> src (? branching-primitive? name) args)
(convert-args args (convert-args args
(lambda (args) (lambda (args)
(build-cps-term ($continue kif ($primcall name args)))))) (build-cps-term
($continue kif src ($primcall name args))))))
(_ (convert-arg test (_ (convert-arg test
(lambda (test) (lambda (test)
(build-cps-term ($continue kif ($var test))))))))))) (build-cps-term
($continue kif src ($var test)))))))))))
(($ <lexical-set> src name gensym exp) (($ <lexical-set> src name gensym exp)
(convert-arg exp (convert-arg exp
@ -537,14 +530,14 @@
(match (assq-ref subst gensym) (match (assq-ref subst gensym)
((box #t) ((box #t)
(build-cps-term (build-cps-term
($continue k ($primcall 'box-set! (box exp))))))))) ($continue k src ($primcall 'box-set! (box exp)))))))))
(($ <seq> src head tail) (($ <seq> src head tail)
(let-gensyms (ktrunc kseq) (let-gensyms (ktrunc kseq)
(build-cps-term (build-cps-term
($letk* ((kseq (tree-il-src tail) ($kargs () () ($letk* ((kseq ($kargs () ()
,(convert tail k subst))) ,(convert tail k subst)))
(ktrunc src ($ktrunc '() #f kseq))) (ktrunc ($ktrunc '() #f kseq)))
,(convert head ktrunc subst))))) ,(convert head ktrunc subst)))))
(($ <let> src names syms vals body) (($ <let> src names syms vals body)
@ -554,9 +547,9 @@
(((name . names) (sym . syms) (val . vals)) (((name . names) (sym . syms) (val . vals))
(let-gensyms (klet) (let-gensyms (klet)
(build-cps-term (build-cps-term
($letk ((klet src ($kargs (name) (sym) ($letk ((klet ($kargs (name) (sym)
,(box-bound-var name sym ,(box-bound-var name sym
(lp names syms vals))))) (lp names syms vals)))))
,(convert val klet subst)))))))) ,(convert val klet subst))))))))
(($ <fix> src names gensyms funs body) (($ <fix> src names gensyms funs body)
@ -568,15 +561,15 @@
gensyms gensyms
(map (lambda (fun) (map (lambda (fun)
(match (convert fun k subst) (match (convert fun k subst)
(($ $continue _ (and fun ($ $fun))) (($ $continue _ _ (and fun ($ $fun)))
fun))) fun)))
funs) funs)
,(convert body k subst)))) ,(convert body k subst))))
(let-gensyms (scope kscope) (let-gensyms (scope kscope)
(build-cps-term (build-cps-term
($letk ((kscope src ($kargs () () ($letk ((kscope ($kargs () ()
,(parameterize ((current-topbox-scope scope)) ,(parameterize ((current-topbox-scope scope))
(convert exp k subst))))) (convert exp k subst)))))
,(capture-toplevel-scope src scope kscope)))))) ,(capture-toplevel-scope src scope kscope))))))
(($ <let-values> src exp (($ <let-values> src exp
@ -584,11 +577,11 @@
(let ((names (append req (if rest (list rest) '())))) (let ((names (append req (if rest (list rest) '()))))
(let-gensyms (ktrunc kargs) (let-gensyms (ktrunc kargs)
(build-cps-term (build-cps-term
($letk* ((kargs src ($kargs names syms ($letk* ((kargs ($kargs names syms
,(fold box-bound-var ,(fold box-bound-var
(convert body k subst) (convert body k subst)
names syms))) names syms)))
(ktrunc src ($ktrunc req rest kargs))) (ktrunc ($ktrunc req rest kargs)))
,(convert exp ktrunc subst)))))))) ,(convert exp ktrunc subst))))))))
(define (build-subst exp) (define (build-subst exp)
@ -628,16 +621,14 @@ indicates that the replacement variable is in a box."
(let ((src (tree-il-src exp))) (let ((src (tree-il-src exp)))
(let-gensyms (kinit init ktail kclause kbody) (let-gensyms (kinit init ktail kclause kbody)
(build-cps-exp (build-cps-exp
($fun '() '() ($fun src '() '()
(kinit src (kinit ($kentry init
($kentry init (ktail ($ktail))
(ktail #f ($ktail)) ((kclause
((kclause src ($kclause ('() '() #f '() #f)
($kclause ('() '() #f '() #f) (kbody ($kargs () ()
(kbody src ,(convert exp ktail
($kargs () () (build-subst exp))))))))))))))
,(convert exp ktail
(build-subst exp))))))))))))))
(define *comp-module* (make-fluid)) (define *comp-module* (make-fluid))