Closure conversion, reify-primitives use $kfun $cont
[bpt/guile.git] / module / language / cps / compile-bytecode.scm
CommitLineData
6e8ad823
AW
1;;; Continuation-passing style (CPS) intermediate language (IL)
2
7ab76a83 3;; Copyright (C) 2013, 2014 Free Software Foundation, Inc.
6e8ad823
AW
4
5;;;; This library is free software; you can redistribute it and/or
6;;;; modify it under the terms of the GNU Lesser General Public
7;;;; License as published by the Free Software Foundation; either
8;;;; version 3 of the License, or (at your option) any later version.
9;;;;
10;;;; This library is distributed in the hope that it will be useful,
11;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
12;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13;;;; Lesser General Public License for more details.
14;;;;
15;;;; You should have received a copy of the GNU Lesser General Public
16;;;; License along with this library; if not, write to the Free Software
17;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
19;;; Commentary:
20;;;
691697de
AW
21;;; Compiling CPS to bytecode. The result is in the bytecode language,
22;;; which happens to be an ELF image as a bytecode.
6e8ad823
AW
23;;;
24;;; Code:
25
691697de 26(define-module (language cps compile-bytecode)
6e8ad823
AW
27 #:use-module (ice-9 match)
28 #:use-module (srfi srfi-1)
29 #:use-module (language cps)
30 #:use-module (language cps arities)
31 #:use-module (language cps closure-conversion)
8ac8e2df 32 #:use-module (language cps contification)
fa3b6e57 33 #:use-module (language cps constructors)
7a08e479 34 #:use-module (language cps cse)
305cccb4 35 #:use-module (language cps dce)
6e8ad823 36 #:use-module (language cps dfg)
7e273b7a 37 #:use-module (language cps elide-values)
6e8ad823 38 #:use-module (language cps primitives)
63463880 39 #:use-module (language cps prune-bailouts)
dd692618 40 #:use-module (language cps prune-top-level-scopes)
6e8ad823 41 #:use-module (language cps reify-primitives)
62b7180b 42 #:use-module (language cps renumber)
c4a209b9 43 #:use-module (language cps self-references)
22a79b55 44 #:use-module (language cps simplify)
6e8ad823 45 #:use-module (language cps slot-allocation)
4c906ad5 46 #:use-module (language cps specialize-primcalls)
6e8ad823 47 #:use-module (system vm assembler)
691697de 48 #:export (compile-bytecode))
6e8ad823 49
d258fccc 50;; TODO: Local var names.
6e8ad823
AW
51
52(define (kw-arg-ref args kw default)
53 (match (memq kw args)
54 ((_ val . _) val)
55 (_ default)))
56
57(define (optimize exp opts)
58 (define (run-pass exp pass kw default)
59 (if (kw-arg-ref opts kw default)
1d15832f 60 (pass exp)
6e8ad823
AW
61 exp))
62
305cccb4
AW
63 ;; The first DCE pass is mainly to eliminate functions that aren't
64 ;; called. The last is mainly to eliminate rest parameters that
65 ;; aren't used, and thus shouldn't be consed.
66
9e94cd9b 67 (let* ((exp (run-pass exp eliminate-dead-code #:eliminate-dead-code? #t))
dd692618 68 (exp (run-pass exp prune-top-level-scopes #:prune-top-level-scopes? #t))
22a79b55 69 (exp (run-pass exp simplify #:simplify? #t))
305cccb4 70 (exp (run-pass exp contify #:contify? #t))
7e273b7a 71 (exp (run-pass exp inline-constructors #:inline-constructors? #t))
4c906ad5 72 (exp (run-pass exp specialize-primcalls #:specialize-primcalls? #t))
305cccb4 73 (exp (run-pass exp elide-values #:elide-values? #t))
9e94cd9b 74 (exp (run-pass exp prune-bailouts #:prune-bailouts? #t))
85270a8c 75 (exp (run-pass exp eliminate-common-subexpressions #:cse? #t))
c4a209b9 76 (exp (run-pass exp resolve-self-references #:resolve-self-references? #t))
22a79b55
AW
77 (exp (run-pass exp eliminate-dead-code #:eliminate-dead-code? #t))
78 (exp (run-pass exp simplify #:simplify? #t)))
6e8ad823
AW
79 ;; Passes that are needed:
80 ;;
6e8ad823
AW
81 ;; * Abort contification: turning abort primcalls into continuation
82 ;; calls, and eliding prompts if possible.
83 ;;
6e8ad823
AW
84 ;; * Loop peeling. Unrolls the first round through a loop if the
85 ;; loop has effects that CSE can work on. Requires effects
86 ;; analysis. When run before CSE, loop peeling is the equivalent
87 ;; of loop-invariant code motion (LICM).
6e8ad823
AW
88
89 exp))
90
d258fccc 91(define (compile-fun f asm)
6bc36ca5 92 (let* ((dfg (compute-dfg f #:global? #f))
a8430ab1 93 (allocation (allocate-slots f dfg)))
987c1f5f
AW
94 (define (maybe-slot sym)
95 (lookup-maybe-slot sym allocation))
96
6e422a35
AW
97 (define (slot sym)
98 (lookup-slot sym allocation))
99
100 (define (constant sym)
101 (lookup-constant-value sym allocation))
102
103 (define (maybe-mov dst src)
104 (unless (= dst src)
105 (emit-mov asm dst src)))
106
107 (define (maybe-load-constant slot src)
108 (call-with-values (lambda ()
109 (lookup-maybe-constant-value src allocation))
110 (lambda (has-const? val)
111 (and has-const?
112 (begin
113 (emit-load-constant asm slot val)
114 #t)))))
115
24b611e8 116 (define (compile-entry)
a8430ab1
AW
117 (let ((label (dfg-min-label dfg)))
118 (match (lookup-cont label dfg)
8320f504 119 (($ $kfun src meta self tail clause)
24b611e8
AW
120 (when src
121 (emit-source asm src))
a8430ab1
AW
122 (emit-begin-program asm label meta)
123 (compile-clause (1+ label))
124 (emit-end-program asm)))))
90dce16d 125
a8430ab1
AW
126 (define (compile-clause label)
127 (match (lookup-cont label dfg)
90dce16d
AW
128 (($ $kclause ($ $arity req opt rest kw allow-other-keys?)
129 body alternate)
6e422a35
AW
130 (let* ((kw-indices (map (match-lambda
131 ((key name sym)
132 (cons key (lookup-slot sym allocation))))
133 kw))
a8430ab1
AW
134 (nlocals (lookup-nlocals label allocation)))
135 (emit-label asm label)
90dce16d
AW
136 (emit-begin-kw-arity asm req opt rest kw-indices allow-other-keys?
137 nlocals
138 (match alternate (#f #f) (($ $cont alt) alt)))
a8430ab1 139 (let ((next (compile-body (1+ label) nlocals)))
6e422a35 140 (emit-end-arity asm)
90dce16d
AW
141 (match alternate
142 (($ $cont alt)
a8430ab1 143 (unless (eq? next alt)
90dce16d
AW
144 (error "unexpected k" alt))
145 (compile-clause next))
146 (#f
a8430ab1 147 (unless (= next (+ (dfg-min-label dfg) (dfg-label-count dfg)))
90dce16d 148 (error "unexpected end of clauses")))))))))
6e422a35 149
a8430ab1
AW
150 (define (compile-body label nlocals)
151 (let compile-cont ((label label))
152 (if (eq? label (+ (dfg-min-label dfg) (dfg-label-count dfg)))
153 label
154 (match (lookup-cont label dfg)
155 (($ $kclause) label)
6e422a35 156 (($ $kargs _ _ term)
a8430ab1 157 (emit-label asm label)
6e422a35
AW
158 (let find-exp ((term term))
159 (match term
160 (($ $letk conts term)
161 (find-exp term))
162 (($ $continue k src exp)
163 (when src
164 (emit-source asm src))
a8430ab1
AW
165 (compile-expression label k exp nlocals)
166 (compile-cont (1+ label))))))
6e422a35 167 (_
a8430ab1
AW
168 (emit-label asm label)
169 (compile-cont (1+ label)))))))
6e422a35 170
a8430ab1
AW
171 (define (compile-expression label k exp nlocals)
172 (let* ((fallthrough? (= k (1+ label))))
6e422a35 173 (define (maybe-emit-jump)
a8430ab1 174 (unless fallthrough?
6e422a35 175 (emit-br asm k)))
a8430ab1 176 (match (lookup-cont k dfg)
6e422a35
AW
177 (($ $ktail)
178 (compile-tail label exp))
179 (($ $kargs (name) (sym))
987c1f5f 180 (let ((dst (maybe-slot sym)))
6e422a35
AW
181 (when dst
182 (compile-value label exp dst nlocals)))
183 (maybe-emit-jump))
184 (($ $kargs () ())
185 (compile-effect label exp k nlocals)
186 (maybe-emit-jump))
187 (($ $kargs names syms)
188 (compile-values label exp syms)
189 (maybe-emit-jump))
190 (($ $kif kt kf)
a8430ab1 191 (compile-test label exp kt kf (and fallthrough? (1+ k))))
36527695 192 (($ $kreceive ($ $arity req () rest () #f) kargs)
fa48a2f7
AW
193 (compile-trunc label k exp (length req)
194 (and rest
a8430ab1 195 (match (lookup-cont kargs dfg)
fa48a2f7
AW
196 (($ $kargs names (_ ... rest)) rest)))
197 nlocals)
a8430ab1 198 (unless (and fallthrough? (= kargs (1+ k)))
987c1f5f 199 (emit-br asm kargs))))))
6e422a35
AW
200
201 (define (compile-tail label exp)
202 ;; There are only three kinds of expressions in tail position:
203 ;; tail calls, multiple-value returns, and single-value returns.
204 (match exp
205 (($ $call proc args)
206 (for-each (match-lambda
207 ((src . dst) (emit-mov asm dst src)))
208 (lookup-parallel-moves label allocation))
209 (let ((tail-slots (cdr (iota (1+ (length args))))))
210 (for-each maybe-load-constant tail-slots args))
211 (emit-tail-call asm (1+ (length args))))
b3ae2b50
AW
212 (($ $callk k proc args)
213 (for-each (match-lambda
214 ((src . dst) (emit-mov asm dst src)))
215 (lookup-parallel-moves label allocation))
216 (let ((tail-slots (cdr (iota (1+ (length args))))))
217 (for-each maybe-load-constant tail-slots args))
218 (emit-tail-call-label asm (1+ (length args)) k))
987c1f5f
AW
219 (($ $values ())
220 (emit-reset-frame asm 1)
221 (emit-return-values asm))
13085a82 222 (($ $values (arg))
987c1f5f 223 (if (maybe-slot arg)
13085a82
AW
224 (emit-return asm (slot arg))
225 (begin
226 (emit-load-constant asm 1 (constant arg))
227 (emit-return asm 1))))
6e422a35 228 (($ $values args)
13085a82
AW
229 (for-each (match-lambda
230 ((src . dst) (emit-mov asm dst src)))
231 (lookup-parallel-moves label allocation))
6e422a35 232 (let ((tail-slots (cdr (iota (1+ (length args))))))
6e422a35
AW
233 (for-each maybe-load-constant tail-slots args))
234 (emit-reset-frame asm (1+ (length args)))
235 (emit-return-values asm))
236 (($ $primcall 'return (arg))
237 (emit-return asm (slot arg)))))
238
239 (define (compile-value label exp dst nlocals)
240 (match exp
6e422a35
AW
241 (($ $values (arg))
242 (or (maybe-load-constant dst arg)
243 (maybe-mov dst (slot arg))))
244 (($ $void)
245 (emit-load-constant asm dst *unspecified*))
246 (($ $const exp)
247 (emit-load-constant asm dst exp))
24b611e8 248 (($ $fun () ($ $cont k))
6e422a35 249 (emit-load-static-procedure asm dst k))
24b611e8 250 (($ $fun free ($ $cont k))
6e422a35 251 (emit-make-closure asm dst k (length free)))
6e422a35
AW
252 (($ $primcall 'current-module)
253 (emit-current-module asm dst))
254 (($ $primcall 'cached-toplevel-box (scope name bound?))
255 (emit-cached-toplevel-box asm dst (constant scope) (constant name)
256 (constant bound?)))
257 (($ $primcall 'cached-module-box (mod name public? bound?))
258 (emit-cached-module-box asm dst (constant mod) (constant name)
259 (constant public?) (constant bound?)))
260 (($ $primcall 'resolve (name bound?))
261 (emit-resolve asm dst (constant bound?) (slot name)))
262 (($ $primcall 'free-ref (closure idx))
263 (emit-free-ref asm dst (slot closure) (constant idx)))
6e422a35 264 (($ $primcall 'vector-ref (vector index))
4c906ad5
AW
265 (emit-vector-ref asm dst (slot vector) (slot index)))
266 (($ $primcall 'make-vector/immediate (length init))
267 (emit-make-vector/immediate asm dst (constant length) (slot init)))
268 (($ $primcall 'vector-ref/immediate (vector index))
269 (emit-vector-ref/immediate asm dst (slot vector) (constant index)))
270 (($ $primcall 'allocate-struct/immediate (vtable nfields))
271 (emit-allocate-struct/immediate asm dst (slot vtable) (constant nfields)))
272 (($ $primcall 'struct-ref/immediate (struct n))
273 (emit-struct-ref/immediate asm dst (slot struct) (constant n)))
6e422a35
AW
274 (($ $primcall 'builtin-ref (name))
275 (emit-builtin-ref asm dst (constant name)))
276 (($ $primcall 'bv-u8-ref (bv idx))
277 (emit-bv-u8-ref asm dst (slot bv) (slot idx)))
d59060ce
AW
278 (($ $primcall 'bv-s8-ref (bv idx))
279 (emit-bv-s8-ref asm dst (slot bv) (slot idx)))
6e422a35
AW
280 (($ $primcall 'bv-u16-ref (bv idx))
281 (emit-bv-u16-ref asm dst (slot bv) (slot idx)))
282 (($ $primcall 'bv-s16-ref (bv idx))
283 (emit-bv-s16-ref asm dst (slot bv) (slot idx)))
284 (($ $primcall 'bv-u32-ref (bv idx val))
285 (emit-bv-u32-ref asm dst (slot bv) (slot idx)))
286 (($ $primcall 'bv-s32-ref (bv idx val))
287 (emit-bv-s32-ref asm dst (slot bv) (slot idx)))
288 (($ $primcall 'bv-u64-ref (bv idx val))
289 (emit-bv-u64-ref asm dst (slot bv) (slot idx)))
290 (($ $primcall 'bv-s64-ref (bv idx val))
291 (emit-bv-s64-ref asm dst (slot bv) (slot idx)))
292 (($ $primcall 'bv-f32-ref (bv idx val))
293 (emit-bv-f32-ref asm dst (slot bv) (slot idx)))
294 (($ $primcall 'bv-f64-ref (bv idx val))
295 (emit-bv-f64-ref asm dst (slot bv) (slot idx)))
296 (($ $primcall name args)
297 ;; FIXME: Inline all the cases.
691697de 298 (let ((inst (prim-instruction name)))
6e422a35
AW
299 (emit-text asm `((,inst ,dst ,@(map slot args))))))))
300
301 (define (compile-effect label exp k nlocals)
302 (match exp
303 (($ $values ()) #f)
7ab76a83 304 (($ $prompt escape? tag handler)
a8430ab1 305 (match (lookup-cont handler dfg)
36527695 306 (($ $kreceive ($ $arity req () rest () #f) khandler-body)
6e422a35
AW
307 (let ((receive-args (gensym "handler"))
308 (nreq (length req))
987c1f5f 309 (proc-slot (lookup-call-proc-slot handler allocation)))
6e422a35
AW
310 (emit-prompt asm (slot tag) escape? proc-slot receive-args)
311 (emit-br asm k)
312 (emit-label asm receive-args)
4dfcb360
AW
313 (unless (and rest (zero? nreq))
314 (emit-receive-values asm proc-slot (->bool rest) nreq))
fa48a2f7 315 (when (and rest
a8430ab1 316 (match (lookup-cont khandler-body dfg)
fa48a2f7
AW
317 (($ $kargs names (_ ... rest))
318 (maybe-slot rest))))
6e422a35
AW
319 (emit-bind-rest asm (+ proc-slot 1 nreq)))
320 (for-each (match-lambda
321 ((src . dst) (emit-mov asm dst src)))
322 (lookup-parallel-moves handler allocation))
323 (emit-reset-frame asm nlocals)
324 (emit-br asm khandler-body)))))
325 (($ $primcall 'cache-current-module! (sym scope))
326 (emit-cache-current-module! asm (slot sym) (constant scope)))
327 (($ $primcall 'free-set! (closure idx value))
328 (emit-free-set! asm (slot closure) (slot value) (constant idx)))
329 (($ $primcall 'box-set! (box value))
330 (emit-box-set! asm (slot box) (slot value)))
4c906ad5
AW
331 (($ $primcall 'struct-set!/immediate (struct index value))
332 (emit-struct-set!/immediate asm (slot struct) (constant index) (slot value)))
6e422a35 333 (($ $primcall 'vector-set! (vector index value))
4c906ad5
AW
334 (emit-vector-set! asm (slot vector) (slot index) (slot value)))
335 (($ $primcall 'vector-set!/immediate (vector index value))
336 (emit-vector-set!/immediate asm (slot vector) (constant index)
337 (slot value)))
6e422a35
AW
338 (($ $primcall 'set-car! (pair value))
339 (emit-set-car! asm (slot pair) (slot value)))
340 (($ $primcall 'set-cdr! (pair value))
341 (emit-set-cdr! asm (slot pair) (slot value)))
342 (($ $primcall 'define! (sym value))
343 (emit-define! asm (slot sym) (slot value)))
344 (($ $primcall 'push-fluid (fluid val))
345 (emit-push-fluid asm (slot fluid) (slot val)))
346 (($ $primcall 'pop-fluid ())
347 (emit-pop-fluid asm))
348 (($ $primcall 'wind (winder unwinder))
349 (emit-wind asm (slot winder) (slot unwinder)))
350 (($ $primcall 'bv-u8-set! (bv idx val))
351 (emit-bv-u8-set! asm (slot bv) (slot idx) (slot val)))
d59060ce
AW
352 (($ $primcall 'bv-s8-set! (bv idx val))
353 (emit-bv-s8-set! asm (slot bv) (slot idx) (slot val)))
6e422a35
AW
354 (($ $primcall 'bv-u16-set! (bv idx val))
355 (emit-bv-u16-set! asm (slot bv) (slot idx) (slot val)))
356 (($ $primcall 'bv-s16-set! (bv idx val))
357 (emit-bv-s16-set! asm (slot bv) (slot idx) (slot val)))
358 (($ $primcall 'bv-u32-set! (bv idx val))
359 (emit-bv-u32-set! asm (slot bv) (slot idx) (slot val)))
360 (($ $primcall 'bv-s32-set! (bv idx val))
361 (emit-bv-s32-set! asm (slot bv) (slot idx) (slot val)))
362 (($ $primcall 'bv-u64-set! (bv idx val))
363 (emit-bv-u64-set! asm (slot bv) (slot idx) (slot val)))
364 (($ $primcall 'bv-s64-set! (bv idx val))
365 (emit-bv-s64-set! asm (slot bv) (slot idx) (slot val)))
366 (($ $primcall 'bv-f32-set! (bv idx val))
367 (emit-bv-f32-set! asm (slot bv) (slot idx) (slot val)))
368 (($ $primcall 'bv-f64-set! (bv idx val))
369 (emit-bv-f64-set! asm (slot bv) (slot idx) (slot val)))
370 (($ $primcall 'unwind ())
371 (emit-unwind asm))))
372
373 (define (compile-values label exp syms)
374 (match exp
375 (($ $values args)
376 (for-each (match-lambda
377 ((src . dst) (emit-mov asm dst src)))
378 (lookup-parallel-moves label allocation))
379 (for-each maybe-load-constant (map slot syms) args))))
380
381 (define (compile-test label exp kt kf next-label)
382 (define (unary op sym)
383 (cond
384 ((eq? kt next-label)
385 (op asm (slot sym) #t kf))
386 (else
387 (op asm (slot sym) #f kt)
388 (unless (eq? kf next-label)
389 (emit-br asm kf)))))
390 (define (binary op a b)
391 (cond
392 ((eq? kt next-label)
393 (op asm (slot a) (slot b) #t kf))
394 (else
395 (op asm (slot a) (slot b) #f kt)
396 (unless (eq? kf next-label)
397 (emit-br asm kf)))))
398 (match exp
58ef5f07
AW
399 (($ $values (sym))
400 (call-with-values (lambda ()
401 (lookup-maybe-constant-value sym allocation))
402 (lambda (has-const? val)
403 (if has-const?
404 (if val
405 (unless (eq? kt next-label)
406 (emit-br asm kt))
407 (unless (eq? kf next-label)
408 (emit-br asm kf)))
409 (unary emit-br-if-true sym)))))
6e422a35
AW
410 (($ $primcall 'null? (a)) (unary emit-br-if-null a))
411 (($ $primcall 'nil? (a)) (unary emit-br-if-nil a))
412 (($ $primcall 'pair? (a)) (unary emit-br-if-pair a))
413 (($ $primcall 'struct? (a)) (unary emit-br-if-struct a))
414 (($ $primcall 'char? (a)) (unary emit-br-if-char a))
415 (($ $primcall 'symbol? (a)) (unary emit-br-if-symbol a))
416 (($ $primcall 'variable? (a)) (unary emit-br-if-variable a))
417 (($ $primcall 'vector? (a)) (unary emit-br-if-vector a))
418 (($ $primcall 'string? (a)) (unary emit-br-if-string a))
419 (($ $primcall 'bytevector? (a)) (unary emit-br-if-bytevector a))
420 ;; Add more TC7 tests here. Keep in sync with
421 ;; *branching-primcall-arities* in (language cps primitives) and
422 ;; the set of macro-instructions in assembly.scm.
423 (($ $primcall 'eq? (a b)) (binary emit-br-if-eq a b))
424 (($ $primcall 'eqv? (a b)) (binary emit-br-if-eqv a b))
425 (($ $primcall 'equal? (a b)) (binary emit-br-if-equal a b))
426 (($ $primcall '< (a b)) (binary emit-br-if-< a b))
427 (($ $primcall '<= (a b)) (binary emit-br-if-<= a b))
428 (($ $primcall '= (a b)) (binary emit-br-if-= a b))
429 (($ $primcall '>= (a b)) (binary emit-br-if-<= b a))
430 (($ $primcall '> (a b)) (binary emit-br-if-< b a))))
431
fa48a2f7 432 (define (compile-trunc label k exp nreq rest-var nlocals)
b3ae2b50
AW
433 (define (do-call proc args emit-call)
434 (let* ((proc-slot (lookup-call-proc-slot label allocation))
435 (nargs (1+ (length args)))
436 (arg-slots (map (lambda (x) (+ x proc-slot)) (iota nargs))))
437 (for-each (match-lambda
438 ((src . dst) (emit-mov asm dst src)))
439 (lookup-parallel-moves label allocation))
440 (for-each maybe-load-constant arg-slots (cons proc args))
441 (emit-call asm proc-slot nargs)
442 (emit-dead-slot-map asm proc-slot
443 (lookup-dead-slot-map label allocation))
444 (cond
445 ((and (= 1 nreq) (and rest-var) (not (maybe-slot rest-var))
446 (match (lookup-parallel-moves k allocation)
447 ((((? (lambda (src) (= src (1+ proc-slot))) src)
448 . dst)) dst)
449 (_ #f)))
450 ;; The usual case: one required live return value, ignoring
451 ;; any additional values.
452 => (lambda (dst)
453 (emit-receive asm dst proc-slot nlocals)))
454 (else
455 (unless (and (zero? nreq) rest-var)
456 (emit-receive-values asm proc-slot (->bool rest-var) nreq))
457 (when (and rest-var (maybe-slot rest-var))
458 (emit-bind-rest asm (+ proc-slot 1 nreq)))
459 (for-each (match-lambda
460 ((src . dst) (emit-mov asm dst src)))
461 (lookup-parallel-moves k allocation))
462 (emit-reset-frame asm nlocals)))))
6e422a35
AW
463 (match exp
464 (($ $call proc args)
b3ae2b50
AW
465 (do-call proc args
466 (lambda (asm proc-slot nargs)
467 (emit-call asm proc-slot nargs))))
468 (($ $callk k proc args)
469 (do-call proc args
470 (lambda (asm proc-slot nargs)
471 (emit-call-label asm proc-slot nargs k))))))
6e422a35
AW
472
473 (match f
6bc36ca5 474 (($ $cont k ($ $kfun src meta self tail clause))
24b611e8 475 (compile-entry)))))
d258fccc 476
6e8ad823
AW
477(define (visit-funs proc exp)
478 (match exp
6e422a35 479 (($ $continue _ _ exp)
6e8ad823
AW
480 (visit-funs proc exp))
481
24b611e8 482 (($ $fun free body)
6e8ad823
AW
483 (visit-funs proc body))
484
485 (($ $letk conts body)
486 (visit-funs proc body)
487 (for-each (lambda (cont) (visit-funs proc cont)) conts))
488
6e422a35 489 (($ $cont sym ($ $kargs names syms body))
6e8ad823
AW
490 (visit-funs proc body))
491
90dce16d
AW
492 (($ $cont sym ($ $kclause arity body alternate))
493 (visit-funs proc body)
494 (when alternate
495 (visit-funs proc alternate)))
6e8ad823 496
8320f504 497 (($ $cont sym ($ $kfun src meta self tail clause))
6bc36ca5 498 (proc exp)
90dce16d
AW
499 (when clause
500 (visit-funs proc clause)))
6e8ad823
AW
501
502 (_ (values))))
503
691697de 504(define (compile-bytecode exp env opts)
6e8ad823
AW
505 (let* ((exp (fix-arities exp))
506 (exp (optimize exp opts))
507 (exp (convert-closures exp))
508 (exp (reify-primitives exp))
b85f5f85
AW
509 (exp (match (renumber (build-cps-exp ($fun '() ,exp)))
510 (($ $fun free body) body)))
6e8ad823
AW
511 (asm (make-assembler)))
512 (visit-funs (lambda (fun)
513 (compile-fun fun asm))
b85f5f85 514 exp)
6e8ad823
AW
515 (values (link-assembly asm #:page-aligned? (kw-arg-ref opts #:to-file? #f))
516 env
517 env)))