1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-17 21:22:25 +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

@ -76,413 +76,405 @@
exp))
(define (collect-conts f cfa)
(let ((srcv (make-vector (cfa-k-count cfa) #f))
(contv (make-vector (cfa-k-count cfa) #f)))
(let ((contv (make-vector (cfa-k-count cfa) #f)))
(fold-local-conts
(lambda (k src cont tail)
(lambda (k cont tail)
(let ((idx (cfa-k-idx cfa k #:default (lambda (k) #f))))
(when idx
(when src
(vector-set! srcv idx src))
(vector-set! contv idx cont))))
'()
(match f
(($ $fun meta free entry)
(($ $fun src meta free entry)
entry)))
(values srcv contv)))
contv))
(define (compile-fun f asm)
(let* ((dfg (compute-dfg f #:global? #f))
(cfa (analyze-control-flow f dfg))
(allocation (allocate-slots f dfg)))
(call-with-values (lambda () (collect-conts f cfa))
(lambda (srcv contv)
(define (lookup-cont k)
(vector-ref contv (cfa-k-idx cfa k)))
(allocation (allocate-slots f dfg))
(contv (collect-conts f cfa)))
(define (lookup-cont k)
(vector-ref contv (cfa-k-idx cfa k)))
(define (maybe-emit-source n)
(let ((src (vector-ref srcv n)))
(when src
(emit-source asm src))))
(define (immediate-u8? val)
(and (integer? val) (exact? val) (<= 0 val 255)))
(define (emit-label-and-maybe-source n)
(emit-label asm (cfa-k-sym cfa n))
(maybe-emit-source n))
(define (maybe-immediate-u8 sym)
(call-with-values (lambda ()
(lookup-maybe-constant-value sym allocation))
(lambda (has-const? val)
(and has-const? (immediate-u8? val) val))))
(define (immediate-u8? val)
(and (integer? val) (exact? val) (<= 0 val 255)))
(define (slot sym)
(lookup-slot sym allocation))
(define (maybe-immediate-u8 sym)
(call-with-values (lambda ()
(lookup-maybe-constant-value sym allocation))
(lambda (has-const? val)
(and has-const? (immediate-u8? val) val))))
(define (constant sym)
(lookup-constant-value sym allocation))
(define (slot sym)
(lookup-slot sym allocation))
(define (maybe-mov dst src)
(unless (= dst src)
(emit-mov asm dst src)))
(define (constant sym)
(lookup-constant-value sym allocation))
(define (maybe-load-constant slot src)
(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)
(unless (= dst src)
(emit-mov asm dst src)))
(define (compile-entry meta)
(match (vector-ref contv 0)
(($ $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)
(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 (compile-clause n alternate)
(match (vector-ref contv n)
(($ $kclause ($ $arity req opt rest kw allow-other-keys?))
(let* ((kw-indices (map (match-lambda
((key name sym)
(cons key (lookup-slot sym allocation))))
kw))
(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)
(match (vector-ref contv 0)
(($ $kentry self tail clauses)
(emit-begin-program asm (cfa-k-sym cfa 0) meta)
(maybe-emit-source 0)
(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 (compile-body n nlocals)
(let compile-cont ((n n))
(if (= n (vector-length contv))
n
(match (vector-ref contv n)
(($ $kclause) n)
(($ $kargs _ _ term)
(emit-label asm (cfa-k-sym cfa n))
(let find-exp ((term term))
(match term
(($ $letk conts term)
(find-exp term))
(($ $continue k src exp)
(when src
(emit-source asm src))
(compile-expression n k exp nlocals)
(compile-cont (1+ n))))))
(_
(emit-label asm (cfa-k-sym cfa n))
(compile-cont (1+ n)))))))
(define (compile-clause n alternate)
(match (vector-ref contv n)
(($ $kclause ($ $arity req opt rest kw allow-other-keys?))
(let ((kw-indices (map (match-lambda
((key name sym)
(cons key (lookup-slot sym allocation))))
kw))
(nlocals (lookup-nlocals (cfa-k-sym cfa n) allocation)))
(emit-label-and-maybe-source n)
(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-expression n k exp nlocals)
(let* ((label (cfa-k-sym cfa n))
(k-idx (cfa-k-idx cfa k))
(fallthrough? (= k-idx (1+ n))))
(define (maybe-emit-jump)
(unless (= k-idx (1+ n))
(emit-br asm k)))
(match (vector-ref contv k-idx)
(($ $ktail)
(compile-tail label exp))
(($ $kargs (name) (sym))
(let ((dst (slot sym)))
(when dst
(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)
(let compile-cont ((n n))
(if (= n (vector-length contv))
n
(match (vector-ref contv n)
(($ $kclause) n)
(($ $kargs _ _ term)
(emit-label-and-maybe-source n)
(let find-exp ((term term))
(match term
(($ $letk conts term)
(find-exp term))
(($ $continue k exp)
(compile-expression n k exp nlocals)
(compile-cont (1+ n))))))
(_
(emit-label-and-maybe-source n)
(compile-cont (1+ n)))))))
(define (compile-tail label exp)
;; There are only three kinds of expressions in tail position:
;; tail calls, multiple-value returns, and single-value returns.
(match exp
(($ $call proc args)
(for-each (match-lambda
((src . dst) (emit-mov asm dst src)))
(lookup-parallel-moves label allocation))
(let ((tail-slots (cdr (iota (1+ (length args))))))
(for-each maybe-load-constant tail-slots args))
(emit-tail-call asm (1+ (length args))))
(($ $values args)
(let ((tail-slots (cdr (iota (1+ (length args))))))
(for-each (match-lambda
((src . dst) (emit-mov asm dst src)))
(lookup-parallel-moves label allocation))
(for-each maybe-load-constant tail-slots args))
(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)
(let* ((label (cfa-k-sym cfa n))
(k-idx (cfa-k-idx cfa k))
(fallthrough? (= k-idx (1+ n))))
(define (maybe-emit-jump)
(unless (= k-idx (1+ n))
(emit-br asm k)))
(match (vector-ref contv k-idx)
(($ $ktail)
(compile-tail label exp))
(($ $kargs (name) (sym))
(let ((dst (slot sym)))
(when dst
(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-value label exp dst nlocals)
(match exp
(($ $var sym)
(maybe-mov dst (slot sym)))
;; FIXME: Remove ($var sym), replace with ($values (sym))
(($ $values (arg))
(or (maybe-load-constant dst arg)
(maybe-mov dst (slot arg))))
(($ $void)
(emit-load-constant asm dst *unspecified*))
(($ $const exp)
(emit-load-constant asm dst exp))
(($ $fun src meta () ($ $cont k))
(emit-load-static-procedure asm dst k))
(($ $fun src 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-tail label exp)
;; There are only three kinds of expressions in tail position:
;; tail calls, multiple-value returns, and single-value returns.
(match exp
(($ $call proc args)
(for-each (match-lambda
((src . dst) (emit-mov asm dst src)))
(lookup-parallel-moves label allocation))
(let ((tail-slots (cdr (iota (1+ (length args))))))
(for-each maybe-load-constant tail-slots args))
(emit-tail-call asm (1+ (length args))))
(($ $values args)
(let ((tail-slots (cdr (iota (1+ (length args))))))
(for-each (match-lambda
((src . dst) (emit-mov asm dst src)))
(lookup-parallel-moves label allocation))
(for-each maybe-load-constant tail-slots args))
(emit-reset-frame asm (1+ (length args)))
(emit-return-values asm))
(($ $primcall 'return (arg))
(emit-return asm (slot arg)))))
(define (compile-effect label exp k nlocals)
(match exp
(($ $values ()) #f)
(($ $prompt escape? tag handler pop)
(match (lookup-cont handler)
(($ $ktrunc ($ $arity req () rest () #f) khandler-body)
(let ((receive-args (gensym "handler"))
(nreq (length req))
(proc-slot (lookup-call-proc-slot label allocation)))
(emit-prompt asm (slot tag) escape? proc-slot receive-args)
(emit-br asm k)
(emit-label asm receive-args)
(emit-receive-values asm proc-slot (->bool rest) 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 handler allocation))
(emit-reset-frame asm nlocals)
(emit-br asm khandler-body)))))
(($ $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)
(match exp
(($ $var sym)
(maybe-mov dst (slot sym)))
;; FIXME: Remove ($var sym), replace with ($values (sym))
(($ $values (arg))
(or (maybe-load-constant dst arg)
(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-values label exp syms)
(match exp
(($ $values args)
(for-each (match-lambda
((src . dst) (emit-mov asm dst src)))
(lookup-parallel-moves label allocation))
(for-each maybe-load-constant (map slot syms) args))))
(define (compile-effect label exp k nlocals)
(match exp
(($ $values ()) #f)
(($ $prompt escape? tag handler pop)
(match (lookup-cont handler)
(($ $ktrunc ($ $arity req () rest () #f) khandler-body)
(let ((receive-args (gensym "handler"))
(nreq (length req))
(proc-slot (lookup-call-proc-slot label allocation)))
(emit-prompt asm (slot tag) escape? proc-slot receive-args)
(emit-br asm k)
(emit-label asm receive-args)
(emit-receive-values asm proc-slot (->bool rest) 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 handler allocation))
(emit-reset-frame asm nlocals)
(emit-br asm khandler-body)))))
(($ $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-test label exp kt kf next-label)
(define (unary op sym)
(cond
((eq? kt next-label)
(op asm (slot sym) #t kf))
(else
(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-values label exp syms)
(match exp
(($ $values args)
(for-each (match-lambda
((src . dst) (emit-mov asm dst src)))
(lookup-parallel-moves label allocation))
(for-each maybe-load-constant (map slot syms) args))))
(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))))))))
(define (compile-test label exp kt kf next-label)
(define (unary op sym)
(cond
((eq? kt next-label)
(op asm (slot sym) #t kf))
(else
(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 '()))))))))
(match f
(($ $fun src meta free ($ $cont k ($ $kentry self tail clauses)))
;; FIXME: src on kentry instead?
(when src
(emit-source asm src))
(compile-entry (or meta '()))))))
(define (visit-funs proc exp)
(match exp
(($ $continue _ exp)
(($ $continue _ _ exp)
(visit-funs proc exp))
(($ $fun meta free body)
(($ $fun src meta free body)
(proc exp)
(visit-funs proc body))
@ -490,13 +482,13 @@
(visit-funs proc body)
(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))
(($ $cont sym src ($ $kclause arity body))
(($ $cont sym ($ $kclause arity 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))
(_ (values))))