<prompt> body and handler are lambdas; add escape-only? field
[bpt/guile.git] / module / language / tree-il / compile-glil.scm
CommitLineData
811d10f5
AW
1;;; TREE-IL -> GLIL compiler
2
d0ecf8eb 3;; Copyright (C) 2001,2008,2009,2010,2011,2012,2013 Free Software Foundation, Inc.
811d10f5 4
53befeb7
NJ
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
811d10f5
AW
18
19;;; Code:
20
21(define-module (language tree-il compile-glil)
22 #:use-module (system base syntax)
66d3e9a3 23 #:use-module (system base pmatch)
4b856371 24 #:use-module (system base message)
cf10678f 25 #:use-module (ice-9 receive)
178a4092 26 #:use-module (ice-9 match)
811d10f5 27 #:use-module (language glil)
60ed31d2 28 #:use-module (system vm instruction)
811d10f5 29 #:use-module (language tree-il)
073bb617 30 #:use-module (language tree-il optimize)
b275fb26 31 #:use-module (language tree-il canonicalize)
cf10678f 32 #:use-module (language tree-il analyze)
48b1db75 33 #:use-module ((srfi srfi-1) #:select (filter-map))
811d10f5
AW
34 #:export (compile-glil))
35
073bb617 36;; allocation:
66d3e9a3 37;; sym -> {lambda -> address}
8a4ca0ea
AW
38;; lambda -> (labels . free-locs)
39;; lambda-case -> (gensym . nlocs)
66d3e9a3 40;;
8a4ca0ea
AW
41;; address ::= (local? boxed? . index)
42;; labels ::= ((sym . lambda) ...)
66d3e9a3
AW
43;; free-locs ::= ((sym0 . address0) (sym1 . address1) ...)
44;; free variable addresses are relative to parent proc.
073bb617 45
a1a482e0
AW
46(define *comp-module* (make-fluid))
47
4b856371 48(define %warning-passes
48b1db75 49 `((unused-variable . ,unused-variable-analysis)
bcae9a98 50 (unused-toplevel . ,unused-toplevel-analysis)
ae03cf1f 51 (unbound-variable . ,unbound-variable-analysis)
75365375
LC
52 (arity-mismatch . ,arity-analysis)
53 (format . ,format-analysis)))
4b856371 54
811d10f5 55(define (compile-glil x e opts)
4b856371
LC
56 (define warnings
57 (or (and=> (memq #:warnings opts) cadr)
58 '()))
59
43eb8aca 60 ;; Go through the warning passes.
48b1db75
LC
61 (let ((analyses (filter-map (lambda (kind)
62 (assoc-ref %warning-passes kind))
63 warnings)))
64 (analyze-tree analyses x e))
aaae0d5a 65
8a4ca0ea 66 (let* ((x (make-lambda (tree-il-src x) '()
1e2a8edb 67 (make-lambda-case #f '() #f #f #f '() '() x #f)))
25450a0d 68 (x (optimize x e opts))
403d78f9 69 (x (canonicalize x))
aaae0d5a 70 (allocation (analyze-lexicals x)))
4b856371 71
eddd16d7
AW
72 (with-fluids ((*comp-module* e))
73 (values (flatten-lambda x #f allocation)
74 e
75 e))))
811d10f5
AW
76
77\f
811d10f5 78
112edbae
AW
79(define *primcall-ops* (make-hash-table))
80(for-each
81 (lambda (x) (hash-set! *primcall-ops* (car x) (cdr x)))
82 '(((eq? . 2) . eq?)
83 ((eqv? . 2) . eqv?)
84 ((equal? . 2) . equal?)
85 ((= . 2) . ee?)
86 ((< . 2) . lt?)
87 ((> . 2) . gt?)
88 ((<= . 2) . le?)
89 ((>= . 2) . ge?)
90 ((+ . 2) . add)
91 ((- . 2) . sub)
7382f23e
AW
92 ((1+ . 1) . add1)
93 ((1- . 1) . sub1)
112edbae
AW
94 ((* . 2) . mul)
95 ((/ . 2) . div)
96 ((quotient . 2) . quo)
97 ((remainder . 2) . rem)
98 ((modulo . 2) . mod)
b10d9330
AW
99 ((ash . 2) . ash)
100 ((logand . 2) . logand)
101 ((logior . 2) . logior)
102 ((logxor . 2) . logxor)
112edbae
AW
103 ((not . 1) . not)
104 ((pair? . 1) . pair?)
105 ((cons . 2) . cons)
106 ((car . 1) . car)
107 ((cdr . 1) . cdr)
108 ((set-car! . 2) . set-car!)
109 ((set-cdr! . 2) . set-cdr!)
110 ((null? . 1) . null?)
c11f46af 111 ((list? . 1) . list?)
cf45ff03
AW
112 ((symbol? . 1) . symbol?)
113 ((vector? . 1) . vector?)
9348168e 114 ((nil? . 1) . nil?)
c11f46af 115 (list . list)
ad9b8c45 116 (vector . vector)
aec4a84a 117 ((class-of . 1) . class-of)
86d0eb31 118 ((fluid-ref . 1) . fluid-ref)
5e0253f1 119 ((fluid-set! . 2) . fluid-set)
ad9b8c45 120 ((@slot-ref . 2) . slot-ref)
d6f1ce3d 121 ((@slot-set! . 3) . slot-set)
d5a4f51f
AW
122 ((string-length . 1) . string-length)
123 ((string-ref . 2) . string-ref)
124 ((vector-length . 1) . vector-length)
d6f1ce3d
AW
125 ((vector-ref . 2) . vector-ref)
126 ((vector-set! . 3) . vector-set)
1d30393f
AW
127 ((variable-ref . 1) . variable-ref)
128 ;; nb, *not* variable-set! -- the args are switched
d27a7811 129 ((variable-bound? . 1) . variable-bound?)
bd91ecce
LC
130 ((struct? . 1) . struct?)
131 ((struct-vtable . 1) . struct-vtable)
a752c0dc
LC
132 ((struct-ref . 2) . struct-ref)
133 ((struct-set! . 3) . struct-set)
9a974fd3 134 (make-struct/no-tail . make-struct)
39141c87 135
d61e866c 136 ;; hack for javascript
52272fc7 137 ((return . 1) . return)
9582b26c
AW
138 ;; hack for lua
139 (return/values . return/values)
d61e866c 140
bb97e4ab
AW
141 ((wind . 2) . wind)
142 ((unwind . 0) . unwind)
c32b7c4c
AW
143 ((push-fluid . 2) . push-fluid)
144 ((pop-fluid . 0) . pop-fluid)
bb97e4ab 145
39141c87
AW
146 ((bytevector-u8-ref . 2) . bv-u8-ref)
147 ((bytevector-u8-set! . 3) . bv-u8-set)
148 ((bytevector-s8-ref . 2) . bv-s8-ref)
149 ((bytevector-s8-set! . 3) . bv-s8-set)
150
151 ((bytevector-u16-ref . 3) . bv-u16-ref)
152 ((bytevector-u16-set! . 4) . bv-u16-set)
153 ((bytevector-u16-native-ref . 2) . bv-u16-native-ref)
154 ((bytevector-u16-native-set! . 3) . bv-u16-native-set)
155 ((bytevector-s16-ref . 3) . bv-s16-ref)
156 ((bytevector-s16-set! . 4) . bv-s16-set)
157 ((bytevector-s16-native-ref . 2) . bv-s16-native-ref)
158 ((bytevector-s16-native-set! . 3) . bv-s16-native-set)
159
160 ((bytevector-u32-ref . 3) . bv-u32-ref)
161 ((bytevector-u32-set! . 4) . bv-u32-set)
162 ((bytevector-u32-native-ref . 2) . bv-u32-native-ref)
163 ((bytevector-u32-native-set! . 3) . bv-u32-native-set)
164 ((bytevector-s32-ref . 3) . bv-s32-ref)
165 ((bytevector-s32-set! . 4) . bv-s32-set)
166 ((bytevector-s32-native-ref . 2) . bv-s32-native-ref)
167 ((bytevector-s32-native-set! . 3) . bv-s32-native-set)
168
169 ((bytevector-u64-ref . 3) . bv-u64-ref)
170 ((bytevector-u64-set! . 4) . bv-u64-set)
171 ((bytevector-u64-native-ref . 2) . bv-u64-native-ref)
172 ((bytevector-u64-native-set! . 3) . bv-u64-native-set)
173 ((bytevector-s64-ref . 3) . bv-s64-ref)
174 ((bytevector-s64-set! . 4) . bv-s64-set)
175 ((bytevector-s64-native-ref . 2) . bv-s64-native-ref)
176 ((bytevector-s64-native-set! . 3) . bv-s64-native-set)
177
178 ((bytevector-ieee-single-ref . 3) . bv-f32-ref)
179 ((bytevector-ieee-single-set! . 4) . bv-f32-set)
180 ((bytevector-ieee-single-native-ref . 2) . bv-f32-native-ref)
181 ((bytevector-ieee-single-native-set! . 3) . bv-f32-native-set)
182 ((bytevector-ieee-double-ref . 3) . bv-f64-ref)
183 ((bytevector-ieee-double-set! . 4) . bv-f64-set)
184 ((bytevector-ieee-double-native-ref . 2) . bv-f64-native-ref)
185 ((bytevector-ieee-double-native-set! . 3) . bv-f64-native-set)))
186
187
188\f
112edbae 189
811d10f5
AW
190(define (make-label) (gensym ":L"))
191
66d3e9a3 192(define (vars->bind-list ids vars allocation proc)
2ce77f2d 193 (map (lambda (id v)
66d3e9a3
AW
194 (pmatch (hashq-ref (hashq-ref allocation v) proc)
195 ((#t ,boxed? . ,n)
196 (list id boxed? n))
3b24aee6 197 (,x (error "bad var list element" id v x))))
2ce77f2d 198 ids
cf10678f
AW
199 vars))
200
66d3e9a3 201(define (emit-bindings src ids vars allocation proc emit-code)
d97b69d9
AW
202 (emit-code src (make-glil-bind
203 (vars->bind-list ids vars allocation proc))))
cf10678f
AW
204
205(define (with-output-to-code proc)
206 (let ((out '()))
207 (define (emit-code src x)
208 (set! out (cons x out))
209 (if src
210 (set! out (cons (make-glil-source src) out))))
211 (proc emit-code)
212 (reverse out)))
213
9b29d607 214(define (flatten-lambda x self-label allocation)
8a4ca0ea
AW
215 (record-case x
216 ((<lambda> src meta body)
217 (make-glil-program
218 meta
219 (with-output-to-code
220 (lambda (emit-code)
221 ;; write source info for proc
222 (if src (emit-code #f (make-glil-source src)))
8a4ca0ea 223 ;; compile the body, yo
0083cb5e
AW
224 (flatten-lambda-case body allocation x self-label
225 (car (hashq-ref allocation x))
226 emit-code)))))))
cf10678f 227
0083cb5e
AW
228(define (flatten-lambda-case lcase allocation self self-label fix-labels
229 emit-code)
cf10678f
AW
230 (define (emit-label label)
231 (emit-code #f (make-glil-label label)))
232 (define (emit-branch src inst label)
233 (emit-code src (make-glil-branch inst label)))
234
230cfcfb
AW
235 ;; RA: "return address"; #f unless we're in a non-tail fix with labels
236 ;; MVRA: "multiple-values return address"; #f unless we're in a let-values
0083cb5e 237 (let comp ((x lcase) (context 'tail) (RA #f) (MVRA #f))
230cfcfb
AW
238 (define (comp-tail tree) (comp tree context RA MVRA))
239 (define (comp-push tree) (comp tree 'push #f #f))
240 (define (comp-drop tree) (comp tree 'drop #f #f))
241 (define (comp-vals tree MVRA) (comp tree 'vals #f MVRA))
242 (define (comp-fix tree RA) (comp tree context RA MVRA))
243
244 ;; A couple of helpers. Note that if we are in tail context, we
245 ;; won't have an RA.
246 (define (maybe-emit-return)
247 (if RA
248 (emit-branch #f 'br RA)
249 (if (eq? context 'tail)
250 (emit-code #f (make-glil-call 'return 1)))))
251
fb135e12
AW
252 ;; After lexical binding forms in non-tail context, call this
253 ;; function to clear stack slots, allowing their previous values to
254 ;; be collected.
255 (define (clear-stack-slots context syms)
256 (case context
257 ((push drop)
258 (for-each (lambda (v)
259 (and=>
260 ;; Can be #f if the var is labels-allocated.
261 (hashq-ref allocation v)
262 (lambda (h)
263 (pmatch (hashq-ref h self)
264 ((#t _ . ,n)
265 (emit-code #f (make-glil-void))
266 (emit-code #f (make-glil-lexical #t #f 'set n)))
267 (,loc (error "bad let var allocation" x loc))))))
268 syms))))
269
cf10678f
AW
270 (record-case x
271 ((<void>)
272 (case context
230cfcfb
AW
273 ((push vals tail)
274 (emit-code #f (make-glil-void))))
275 (maybe-emit-return))
cf10678f
AW
276
277 ((<const> src exp)
278 (case context
230cfcfb
AW
279 ((push vals tail)
280 (emit-code src (make-glil-const exp))))
281 (maybe-emit-return))
cf10678f 282
6fc3eae4
AW
283 ((<seq> head tail)
284 (comp-drop head)
285 (comp-tail tail))
286
7081d4f9 287 ((<call> src proc args)
112edbae 288 (cond
0083cb5e 289 ;; call to the same lambda-case in tail position
9b29d607
AW
290 ((and (lexical-ref? proc)
291 self-label (eq? (lexical-ref-gensym proc) self-label)
0083cb5e
AW
292 (eq? context 'tail)
293 (not (lambda-case-kw lcase))
294 (not (lambda-case-rest lcase))
295 (= (length args)
296 (+ (length (lambda-case-req lcase))
297 (or (and=> (lambda-case-opt lcase) length) 0))))
298 (for-each comp-push args)
299 (for-each (lambda (sym)
300 (pmatch (hashq-ref (hashq-ref allocation sym) self)
301 ((#t #f . ,index) ; unboxed
302 (emit-code #f (make-glil-lexical #t #f 'set index)))
303 ((#t #t . ,index) ; boxed
304 ;; new box
305 (emit-code #f (make-glil-lexical #t #t 'box index)))
306 (,x (error "bad lambda-case arg allocation" x))))
307 (reverse (lambda-case-gensyms lcase)))
308 (emit-branch src 'br (car (hashq-ref allocation lcase))))
9b29d607 309
230cfcfb
AW
310 ;; lambda, the ultimate goto
311 ((and (lexical-ref? proc)
312 (assq (lexical-ref-gensym proc) fix-labels))
8a4ca0ea
AW
313 ;; like the self-tail-call case, though we can handle "drop"
314 ;; contexts too. first, evaluate new values, pushing them on
315 ;; the stack
230cfcfb 316 (for-each comp-push args)
8a4ca0ea
AW
317 ;; find the specific case, rename args, and goto the case label
318 (let lp ((lcase (lambda-body
319 (assq-ref fix-labels (lexical-ref-gensym proc)))))
320 (cond
321 ((and (lambda-case? lcase)
322 (not (lambda-case-kw lcase))
323 (not (lambda-case-opt lcase))
324 (not (lambda-case-rest lcase))
325 (= (length args) (length (lambda-case-req lcase))))
326 ;; we have a case that matches the args; rename variables
327 ;; and goto the case label
328 (for-each (lambda (sym)
329 (pmatch (hashq-ref (hashq-ref allocation sym) self)
330 ((#t #f . ,index) ; unboxed
331 (emit-code #f (make-glil-lexical #t #f 'set index)))
332 ((#t #t . ,index) ; boxed
333 (emit-code #f (make-glil-lexical #t #t 'box index)))
3b24aee6 334 (,x (error "bad lambda-case arg allocation" x))))
93f63467 335 (reverse (lambda-case-gensyms lcase)))
8a4ca0ea
AW
336 (emit-branch src 'br (car (hashq-ref allocation lcase))))
337 ((lambda-case? lcase)
338 ;; no match, try next case
3a88cb3b 339 (lp (lambda-case-alternate lcase)))
8a4ca0ea
AW
340 (else
341 ;; no cases left. we can't really handle this currently.
342 ;; ideally we would push on a new frame, then do a "local
343 ;; call" -- which doesn't require consing up a program
344 ;; object. but for now error, as this sort of case should
345 ;; preclude label allocation.
346 (error "couldn't find matching case for label call" x)))))
230cfcfb 347
112edbae 348 (else
b7946e9e
AW
349 (if (not (eq? context 'tail))
350 (emit-code src (make-glil-call 'new-frame 0)))
112edbae
AW
351 (comp-push proc)
352 (for-each comp-push args)
dce042f1
AW
353 (let ((len (length args)))
354 (case context
d0ecf8eb
AW
355 ((tail) (if (<= len #xff)
356 (emit-code src (make-glil-call 'tail-call len))
357 (begin
358 (comp-push (make-const #f len))
359 (emit-code src (make-glil-call 'tail-call/nargs 0)))))
360 ((push) (if (<= len #xff)
361 (emit-code src (make-glil-call 'call len))
362 (begin
363 (comp-push (make-const #f len))
364 (emit-code src (make-glil-call 'call/nargs 0))))
230cfcfb 365 (maybe-emit-return))
d0ecf8eb
AW
366 ;; FIXME: mv-call doesn't have a /nargs variant, so it is
367 ;; limited to 255 args. Can work around it with a
368 ;; trampoline and tail-call/nargs, but it's not so nice.
230cfcfb
AW
369 ((vals) (emit-code src (make-glil-mv-call len MVRA))
370 (maybe-emit-return))
371 ((drop) (let ((MV (make-label)) (POST (make-label)))
372 (emit-code src (make-glil-mv-call len MV))
373 (emit-code #f (make-glil-call 'drop 1))
374 (emit-branch #f 'br (or RA POST))
375 (emit-label MV)
05c51bcf 376 (emit-code #f (make-glil-mv-bind 0 #f))
230cfcfb
AW
377 (if RA
378 (emit-branch #f 'br RA)
379 (emit-label POST)))))))))
073bb617 380
a881a4ae
AW
381 ((<primcall> src name args)
382 (pmatch (cons name args)
39caffe7 383 ((apply ,proc . ,args)
a881a4ae
AW
384 (cond
385 ((and (primitive-ref? proc) (eq? (primitive-ref-name proc) 'values)
386 (not (eq? context 'push)) (not (eq? context 'vals)))
387 ;; tail: (lambda () (apply values '(1 2)))
388 ;; drop: (lambda () (apply values '(1 2)) 3)
389 ;; push: (lambda () (list (apply values '(10 12)) 1))
390 (case context
391 ((drop) (for-each comp-drop args) (maybe-emit-return))
392 ((tail)
393 (for-each comp-push args)
394 (emit-code src (make-glil-call 'return/values* (length args))))))
395
396 (else
397 (case context
398 ((tail)
399 (comp-push proc)
400 (for-each comp-push args)
401 (emit-code src (make-glil-call 'tail-apply (1+ (length args)))))
402 ((push)
403 (emit-code src (make-glil-call 'new-frame 0))
404 (comp-push proc)
405 (for-each comp-push args)
406 (emit-code src (make-glil-call 'apply (1+ (length args))))
407 (maybe-emit-return))
408 (else
39caffe7
AW
409 (comp-tail (make-call src (make-primitive-ref #f 'apply)
410 (cons proc args))))))))
a881a4ae 411
78f0ef20 412 ((values . _)
a881a4ae
AW
413 ;; tail: (lambda () (values '(1 2)))
414 ;; drop: (lambda () (values '(1 2)) 3)
415 ;; push: (lambda () (list (values '(10 12)) 1))
416 ;; vals: (let-values (((a b ...) (values 1 2 ...))) ...)
417 (case context
418 ((drop) (for-each comp-drop args) (maybe-emit-return))
78f0ef20
AW
419 ((push)
420 (case (length args)
421 ((0)
422 ;; FIXME: This is surely an error. We need to add a
423 ;; values-mismatch warning pass.
424 (comp-push (make-call src (make-primitive-ref #f 'values)
425 '())))
78f0ef20
AW
426 (else
427 ;; Taking advantage of unspecified order of evaluation of
428 ;; arguments.
429 (for-each comp-drop (cdr args))
252acfe8
AW
430 (comp-push (car args))
431 (maybe-emit-return))))
a881a4ae
AW
432 ((vals)
433 (for-each comp-push args)
434 (emit-code #f (make-glil-const (length args)))
435 (emit-branch src 'br MVRA))
436 ((tail)
437 (for-each comp-push args)
78f0ef20
AW
438 (emit-code src (let ((len (length args)))
439 (if (= len 1)
440 (make-glil-call 'return 1)
441 (make-glil-call 'return/values len)))))))
a881a4ae 442
0fcc39a0 443 ((call-with-values ,producer ,consumer)
a881a4ae
AW
444 ;; CONSUMER
445 ;; PRODUCER
446 ;; (mv-call MV)
447 ;; ([tail]-call 1)
448 ;; goto POST
449 ;; MV: [tail-]call/nargs
450 ;; POST: (maybe-drop)
451 (case context
452 ((vals)
453 ;; Fall back.
0fcc39a0
AW
454 (comp-tail
455 (make-call src (make-toplevel-ref #f 'call-with-values) args)))
a881a4ae
AW
456 (else
457 (let ((MV (make-label)) (POST (make-label)))
458 (if (not (eq? context 'tail))
459 (emit-code src (make-glil-call 'new-frame 0)))
460 (comp-push consumer)
461 (emit-code src (make-glil-call 'new-frame 0))
462 (comp-push producer)
463 (emit-code src (make-glil-mv-call 0 MV))
464 (case context
465 ((tail) (emit-code src (make-glil-call 'tail-call 1)))
466 (else (emit-code src (make-glil-call 'call 1))
467 (emit-branch #f 'br POST)))
468 (emit-label MV)
469 (case context
470 ((tail) (emit-code src (make-glil-call 'tail-call/nargs 0)))
471 (else (emit-code src (make-glil-call 'call/nargs 0))
472 (emit-label POST)
473 (if (eq? context 'drop)
474 (emit-code #f (make-glil-call 'drop 1)))
475 (maybe-emit-return)))))))
476
bc056057 477 ((call-with-current-continuation ,proc)
a881a4ae
AW
478 (case context
479 ((tail)
480 (comp-push proc)
481 (emit-code src (make-glil-call 'tail-call/cc 1)))
482 ((vals)
483 (comp-vals
bc056057
AW
484 (make-call src
485 (make-primitive-ref #f 'call-with-current-continuation)
486 args)
a881a4ae
AW
487 MVRA)
488 (maybe-emit-return))
489 ((push)
490 (comp-push proc)
491 (emit-code src (make-glil-call 'call/cc 1))
492 (maybe-emit-return))
493 ((drop)
494 ;; Fall back.
495 (comp-tail
bc056057
AW
496 (make-call src
497 (make-primitive-ref #f 'call-with-current-continuation)
498 args)))))
a881a4ae
AW
499
500 ;; A hack for variable-set, the opcode for which takes its args
501 ;; reversed, relative to the variable-set! function
502 ((variable-set! ,var ,val)
503 (comp-push val)
504 (comp-push var)
505 (emit-code src (make-glil-call 'variable-set 2))
506 (case context
507 ((tail push vals) (emit-code #f (make-glil-void))))
508 (maybe-emit-return))
509
510 (else
511 (cond
512 ((or (hash-ref *primcall-ops* (cons name (length args)))
513 (hash-ref *primcall-ops* name))
514 => (lambda (op)
515 (for-each comp-push args)
516 (emit-code src (make-glil-call op (length args)))
517 (case (instruction-pushes op)
518 ((0)
519 (case context
520 ((tail push vals) (emit-code #f (make-glil-void))))
521 (maybe-emit-return))
522 ((1)
523 (case context
524 ((drop) (emit-code #f (make-glil-call 'drop 1))))
525 (maybe-emit-return))
526 ((-1)
527 ;; A control instruction, like return/values. Here we
528 ;; just have to hope that the author of the tree-il
529 ;; knew what they were doing.
530 *unspecified*)
531 (else
532 (error "bad primitive op: too many pushes"
533 op (instruction-pushes op))))))
534 (else
535 ;; Fall back to the normal compilation strategy.
536 (comp-tail (make-call src (make-primitive-ref #f name) args)))))))
537
b6d93b11 538 ((<conditional> src test consequent alternate)
073bb617
AW
539 ;; TEST
540 ;; (br-if-not L1)
b6d93b11 541 ;; consequent
073bb617 542 ;; (br L2)
b6d93b11 543 ;; L1: alternate
073bb617
AW
544 ;; L2:
545 (let ((L1 (make-label)) (L2 (make-label)))
b4a595a5 546 (record-case test
a881a4ae
AW
547 ((<primcall> name args)
548 (pmatch (cons name args)
549 ((eq? ,a ,b)
550 (comp-push a)
551 (comp-push b)
552 (emit-branch src 'br-if-not-eq L1))
553 ((null? ,x)
554 (comp-push x)
555 (emit-branch src 'br-if-not-null L1))
5ddd9645
BT
556 ((nil? ,x)
557 (comp-push x)
558 (emit-branch src 'br-if-not-nil L1))
a881a4ae
AW
559 ((not ,x)
560 (record-case x
561 ((<primcall> name args)
562 (pmatch (cons name args)
563 ((eq? ,a ,b)
564 (comp-push a)
565 (comp-push b)
566 (emit-branch src 'br-if-eq L1))
567 ((null? ,x)
568 (comp-push x)
569 (emit-branch src 'br-if-null L1))
5ddd9645
BT
570 ((nil? ,x)
571 (comp-push x)
572 (emit-branch src 'br-if-nil L1))
a881a4ae
AW
573 (else
574 (comp-push x)
575 (emit-branch src 'br-if L1))))
576 (else
577 (comp-push x)
578 (emit-branch src 'br-if L1))))
b4a595a5
AW
579 (else
580 (comp-push test)
581 (emit-branch src 'br-if-not L1))))
582 (else
583 (comp-push test)
584 (emit-branch src 'br-if-not L1)))
585
b6d93b11 586 (comp-tail consequent)
d97b69d9
AW
587 ;; if there is an RA, comp-tail will cause a jump to it -- just
588 ;; have to clean up here if there is no RA.
589 (if (and (not RA) (not (eq? context 'tail)))
590 (emit-branch #f 'br L2))
cf10678f 591 (emit-label L1)
b4a595a5 592 (comp-tail alternate)
d97b69d9
AW
593 (if (and (not RA) (not (eq? context 'tail)))
594 (emit-label L2))))
595
cf10678f 596 ((<primitive-ref> src name)
a1a482e0
AW
597 (cond
598 ((eq? (module-variable (fluid-ref *comp-module*) name)
599 (module-variable the-root-module name))
600 (case context
230cfcfb
AW
601 ((tail push vals)
602 (emit-code src (make-glil-toplevel 'ref name))))
603 (maybe-emit-return))
94ff26b9 604 ((module-variable the-root-module name)
a1a482e0 605 (case context
230cfcfb
AW
606 ((tail push vals)
607 (emit-code src (make-glil-module 'ref '(guile) name #f))))
94ff26b9
AW
608 (maybe-emit-return))
609 (else
610 (case context
611 ((tail push vals)
612 (emit-code src (make-glil-module
613 'ref (module-name (fluid-ref *comp-module*)) name #f))))
230cfcfb 614 (maybe-emit-return))))
cf10678f 615
e5f5113c 616 ((<lexical-ref> src gensym)
cf10678f 617 (case context
f4aa8d53 618 ((push vals tail)
9b29d607 619 (pmatch (hashq-ref (hashq-ref allocation gensym) self)
66d3e9a3
AW
620 ((,local? ,boxed? . ,index)
621 (emit-code src (make-glil-lexical local? boxed? 'ref index)))
622 (,loc
3b24aee6 623 (error "bad lexical allocation" x loc)))))
230cfcfb 624 (maybe-emit-return))
66d3e9a3 625
e5f5113c 626 ((<lexical-set> src gensym exp)
cf10678f 627 (comp-push exp)
9b29d607 628 (pmatch (hashq-ref (hashq-ref allocation gensym) self)
66d3e9a3
AW
629 ((,local? ,boxed? . ,index)
630 (emit-code src (make-glil-lexical local? boxed? 'set index)))
631 (,loc
3b24aee6 632 (error "bad lexical allocation" x loc)))
cf10678f 633 (case context
230cfcfb
AW
634 ((tail push vals)
635 (emit-code #f (make-glil-void))))
636 (maybe-emit-return))
cf10678f
AW
637
638 ((<module-ref> src mod name public?)
639 (emit-code src (make-glil-module 'ref mod name public?))
640 (case context
230cfcfb
AW
641 ((drop) (emit-code #f (make-glil-call 'drop 1))))
642 (maybe-emit-return))
cf10678f
AW
643
644 ((<module-set> src mod name public? exp)
645 (comp-push exp)
646 (emit-code src (make-glil-module 'set mod name public?))
647 (case context
230cfcfb
AW
648 ((tail push vals)
649 (emit-code #f (make-glil-void))))
650 (maybe-emit-return))
cf10678f
AW
651
652 ((<toplevel-ref> src name)
653 (emit-code src (make-glil-toplevel 'ref name))
654 (case context
230cfcfb
AW
655 ((drop) (emit-code #f (make-glil-call 'drop 1))))
656 (maybe-emit-return))
cf10678f
AW
657
658 ((<toplevel-set> src name exp)
659 (comp-push exp)
660 (emit-code src (make-glil-toplevel 'set name))
661 (case context
230cfcfb
AW
662 ((tail push vals)
663 (emit-code #f (make-glil-void))))
664 (maybe-emit-return))
cf10678f
AW
665
666 ((<toplevel-define> src name exp)
667 (comp-push exp)
668 (emit-code src (make-glil-toplevel 'define name))
669 (case context
230cfcfb
AW
670 ((tail push vals)
671 (emit-code #f (make-glil-void))))
672 (maybe-emit-return))
cf10678f
AW
673
674 ((<lambda>)
8a4ca0ea 675 (let ((free-locs (cdr (hashq-ref allocation x))))
66d3e9a3
AW
676 (case context
677 ((push vals tail)
9b29d607 678 (emit-code #f (flatten-lambda x #f allocation))
66d3e9a3
AW
679 (if (not (null? free-locs))
680 (begin
681 (for-each
682 (lambda (loc)
683 (pmatch loc
d773ba23 684 ((,local? ,boxed? . ,n)
66d3e9a3 685 (emit-code #f (make-glil-lexical local? #f 'ref n)))
3b24aee6 686 (else (error "bad lambda free var allocation" x loc))))
66d3e9a3 687 free-locs)
6f16379e
AW
688 (emit-code #f (make-glil-call 'make-closure
689 (length free-locs))))))))
230cfcfb 690 (maybe-emit-return))
66d3e9a3 691
93f63467 692 ((<lambda-case> src req opt rest kw inits gensyms alternate body)
899d37a6
AW
693 ;; o/~ feature on top of feature o/~
694 ;; req := (name ...)
b0c8c187 695 ;; opt := (name ...) | #f
899d37a6 696 ;; rest := name | #f
b0c8c187 697 ;; kw: (allow-other-keys? (keyword name var) ...) | #f
93f63467
AW
698 ;; gensyms: (sym ...)
699 ;; init: tree-il in context of gensyms
700 ;; gensyms map to named arguments in the following order:
899d37a6
AW
701 ;; required, optional (positional), rest, keyword.
702 (let* ((nreq (length req))
703 (nopt (if opt (length opt) 0))
704 (rest-idx (and rest (+ nreq nopt)))
b0c8c187 705 (opt-names (or opt '()))
899d37a6
AW
706 (allow-other-keys? (if kw (car kw) #f))
707 (kw-indices (map (lambda (x)
708 (pmatch x
b0c8c187 709 ((,key ,name ,var)
93f63467 710 (cons key (list-index gensyms var)))
899d37a6
AW
711 (else (error "bad kwarg" x))))
712 (if kw (cdr kw) '())))
b0c8c187
AW
713 (nargs (apply max (+ nreq nopt (if rest 1 0))
714 (map 1+ (map cdr kw-indices))))
899d37a6 715 (nlocs (cdr (hashq-ref allocation x)))
3a88cb3b 716 (alternate-label (and alternate (make-label))))
899d37a6 717 (or (= nargs
93f63467 718 (length gensyms)
b0c8c187 719 (+ nreq (length inits) (if rest 1 0)))
3b24aee6 720 (error "lambda-case gensyms don't correspond to args"
93f63467 721 req opt rest kw inits gensyms nreq nopt kw-indices nargs))
7e01997e
AW
722 ;; the prelude, to check args & reset the stack pointer,
723 ;; allowing room for locals
724 (emit-code
725 src
726 (cond
7e01997e 727 (kw
899d37a6 728 (make-glil-kw-prelude nreq nopt rest-idx kw-indices
3a88cb3b 729 allow-other-keys? nlocs alternate-label))
7e01997e 730 ((or rest opt)
3a88cb3b 731 (make-glil-opt-prelude nreq nopt rest-idx nlocs alternate-label))
7e01997e 732 (#t
3a88cb3b 733 (make-glil-std-prelude nreq nlocs alternate-label))))
7e01997e
AW
734 ;; box args if necessary
735 (for-each
736 (lambda (v)
737 (pmatch (hashq-ref (hashq-ref allocation v) self)
738 ((#t #t . ,n)
739 (emit-code #f (make-glil-lexical #t #f 'ref n))
740 (emit-code #f (make-glil-lexical #t #t 'box n)))))
93f63467 741 gensyms)
7e01997e 742 ;; write bindings info
93f63467 743 (if (not (null? gensyms))
7e01997e
AW
744 (emit-bindings
745 #f
746 (let lp ((kw (if kw (cdr kw) '()))
b0c8c187 747 (names (append (reverse opt-names) (reverse req)))
93f63467 748 (gensyms (list-tail gensyms (+ nreq nopt
7e01997e
AW
749 (if rest 1 0)))))
750 (pmatch kw
899d37a6 751 (()
93f63467 752 ;; fixme: check that gensyms is empty
899d37a6 753 (reverse (if rest (cons rest names) names)))
7e01997e 754 (((,key ,name ,var) . ,kw)
93f63467
AW
755 (if (memq var gensyms)
756 (lp kw (cons name names) (delq var gensyms))
757 (lp kw names gensyms)))
7e01997e 758 (,kw (error "bad keywords, yo" kw))))
93f63467 759 gensyms allocation self emit-code))
b0c8c187 760 ;; init optional/kw args
93f63467 761 (let lp ((inits inits) (n nreq) (gensyms (list-tail gensyms nreq)))
b0c8c187
AW
762 (cond
763 ((null? inits)) ; done
764 ((and rest-idx (= n rest-idx))
93f63467 765 (lp inits (1+ n) (cdr gensyms)))
b0c8c187 766 (#t
93f63467 767 (pmatch (hashq-ref (hashq-ref allocation (car gensyms)) self)
b0c8c187
AW
768 ((#t ,boxed? . ,n*) (guard (= n* n))
769 (let ((L (make-label)))
770 (emit-code #f (make-glil-lexical #t boxed? 'bound? n))
771 (emit-code #f (make-glil-branch 'br-if L))
772 (comp-push (car inits))
773 (emit-code #f (make-glil-lexical #t boxed? 'set n))
774 (emit-label L)
93f63467 775 (lp (cdr inits) (1+ n) (cdr gensyms))))
3b24aee6 776 (#t (error "bad arg allocation" (car gensyms) inits))))))
7e01997e
AW
777 ;; post-prelude case label for label calls
778 (emit-label (car (hashq-ref allocation x)))
8a4ca0ea 779 (comp-tail body)
93f63467 780 (if (not (null? gensyms))
8a4ca0ea 781 (emit-code #f (make-glil-unbind)))
3a88cb3b 782 (if alternate-label
8a4ca0ea 783 (begin
3a88cb3b 784 (emit-label alternate-label)
0083cb5e
AW
785 (flatten-lambda-case alternate allocation self self-label
786 fix-labels emit-code)))))
8a4ca0ea 787
93f63467 788 ((<let> src names gensyms vals body)
073bb617 789 (for-each comp-push vals)
93f63467 790 (emit-bindings src names gensyms allocation self emit-code)
cf10678f 791 (for-each (lambda (v)
9b29d607 792 (pmatch (hashq-ref (hashq-ref allocation v) self)
66d3e9a3
AW
793 ((#t #f . ,n)
794 (emit-code src (make-glil-lexical #t #f 'set n)))
795 ((#t #t . ,n)
796 (emit-code src (make-glil-lexical #t #t 'box n)))
3b24aee6 797 (,loc (error "bad let var allocation" x loc))))
93f63467 798 (reverse gensyms))
f4aa8d53 799 (comp-tail body)
fb135e12 800 (clear-stack-slots context gensyms)
cf10678f
AW
801 (emit-code #f (make-glil-unbind)))
802
60d4b224
AW
803 ((<letrec> src in-order? names gensyms vals body)
804 ;; First prepare heap storage slots.
66d3e9a3 805 (for-each (lambda (v)
9b29d607 806 (pmatch (hashq-ref (hashq-ref allocation v) self)
66d3e9a3
AW
807 ((#t #t . ,n)
808 (emit-code src (make-glil-lexical #t #t 'empty-box n)))
3b24aee6 809 (,loc (error "bad letrec var allocation" x loc))))
93f63467 810 gensyms)
60d4b224 811 ;; Even though the slots are empty, the bindings are valid.
93f63467 812 (emit-bindings src names gensyms allocation self emit-code)
60d4b224
AW
813 (cond
814 (in-order?
815 ;; For letrec*, bind values in order.
816 (for-each (lambda (name v val)
817 (pmatch (hashq-ref (hashq-ref allocation v) self)
818 ((#t #t . ,n)
819 (comp-push val)
820 (emit-code src (make-glil-lexical #t #t 'set n)))
3b24aee6 821 (,loc (error "bad letrec var allocation" x loc))))
60d4b224
AW
822 names gensyms vals))
823 (else
824 ;; But for letrec, eval all values, then bind.
825 (for-each comp-push vals)
826 (for-each (lambda (v)
827 (pmatch (hashq-ref (hashq-ref allocation v) self)
828 ((#t #t . ,n)
829 (emit-code src (make-glil-lexical #t #t 'set n)))
3b24aee6 830 (,loc (error "bad letrec var allocation" x loc))))
60d4b224 831 (reverse gensyms))))
f4aa8d53 832 (comp-tail body)
fb135e12 833 (clear-stack-slots context gensyms)
f4aa8d53
AW
834 (emit-code #f (make-glil-unbind)))
835
93f63467 836 ((<fix> src names gensyms vals body)
230cfcfb
AW
837 ;; The ideal here is to just render the lambda bodies inline, and
838 ;; wire the code together with gotos. We can do that if
839 ;; analyze-lexicals has determined that a given var has "label"
840 ;; allocation -- which is the case if it is in `fix-labels'.
841 ;;
842 ;; But even for closures that we can't inline, we can do some
843 ;; tricks to avoid heap-allocation for the binding itself. Since
844 ;; we know the vals are lambdas, we can set them to their local
845 ;; var slots first, then capture their bindings, mutating them in
846 ;; place.
7f7b85cb 847 (let ((new-RA (if (or (eq? context 'tail) RA) #f (make-label))))
230cfcfb
AW
848 (for-each
849 (lambda (x v)
850 (cond
851 ((hashq-ref allocation x)
852 ;; allocating a closure
853 (emit-code #f (flatten-lambda x v allocation))
6f16379e
AW
854 (let ((free-locs (cdr (hashq-ref allocation x))))
855 (if (not (null? free-locs))
856 ;; Need to make-closure first, so we have a fresh closure on
857 ;; the heap, but with a temporary free values.
858 (begin
859 (for-each (lambda (loc)
860 (emit-code #f (make-glil-const #f)))
861 free-locs)
862 (emit-code #f (make-glil-call 'make-closure
863 (length free-locs))))))
230cfcfb
AW
864 (pmatch (hashq-ref (hashq-ref allocation v) self)
865 ((#t #f . ,n)
866 (emit-code src (make-glil-lexical #t #f 'set n)))
3b24aee6 867 (,loc (error "bad fix var allocation" x loc))))
230cfcfb
AW
868 (else
869 ;; labels allocation: emit label & body, but jump over it
870 (let ((POST (make-label)))
871 (emit-branch #f 'br POST)
8a4ca0ea
AW
872 (let lp ((lcase (lambda-body x)))
873 (if lcase
874 (record-case lcase
93f63467 875 ((<lambda-case> src req gensyms body alternate)
8a4ca0ea
AW
876 (emit-label (car (hashq-ref allocation lcase)))
877 ;; FIXME: opt & kw args in the bindings
93f63467 878 (emit-bindings #f req gensyms allocation self emit-code)
8a4ca0ea
AW
879 (if src
880 (emit-code #f (make-glil-source src)))
881 (comp-fix body (or RA new-RA))
882 (emit-code #f (make-glil-unbind))
3a88cb3b 883 (lp alternate)))
8a4ca0ea 884 (emit-label POST)))))))
230cfcfb 885 vals
93f63467 886 gensyms)
230cfcfb 887 ;; Emit bindings metadata for closures
93f63467
AW
888 (let ((binds (let lp ((out '()) (gensyms gensyms) (names names))
889 (cond ((null? gensyms) (reverse! out))
890 ((assq (car gensyms) fix-labels)
891 (lp out (cdr gensyms) (cdr names)))
230cfcfb 892 (else
93f63467
AW
893 (lp (acons (car gensyms) (car names) out)
894 (cdr gensyms) (cdr names)))))))
230cfcfb
AW
895 (emit-bindings src (map cdr binds) (map car binds)
896 allocation self emit-code))
897 ;; Now go back and fix up the bindings for closures.
898 (for-each
899 (lambda (x v)
900 (let ((free-locs (if (hashq-ref allocation x)
8a4ca0ea 901 (cdr (hashq-ref allocation x))
230cfcfb
AW
902 ;; can hit this latter case for labels allocation
903 '())))
904 (if (not (null? free-locs))
905 (begin
906 (for-each
907 (lambda (loc)
908 (pmatch loc
d773ba23 909 ((,local? ,boxed? . ,n)
230cfcfb 910 (emit-code #f (make-glil-lexical local? #f 'ref n)))
3b24aee6 911 (else (error "bad free var allocation" x loc))))
230cfcfb 912 free-locs)
230cfcfb
AW
913 (pmatch (hashq-ref (hashq-ref allocation v) self)
914 ((#t #f . ,n)
915 (emit-code #f (make-glil-lexical #t #f 'fix n)))
3b24aee6 916 (,loc (error "bad fix var allocation" x loc)))))))
230cfcfb 917 vals
93f63467 918 gensyms)
230cfcfb 919 (comp-tail body)
7f7b85cb
AW
920 (if new-RA
921 (emit-label new-RA))
fb135e12 922 (clear-stack-slots context gensyms)
230cfcfb 923 (emit-code #f (make-glil-unbind))))
c21c89b1 924
8a4ca0ea
AW
925 ((<let-values> src exp body)
926 (record-case body
93f63467 927 ((<lambda-case> req opt kw rest gensyms body alternate)
3a88cb3b 928 (if (or opt kw alternate)
8a4ca0ea
AW
929 (error "unexpected lambda-case in let-values" x))
930 (let ((MV (make-label)))
931 (comp-vals exp MV)
932 (emit-code #f (make-glil-const 1))
933 (emit-label MV)
934 (emit-code src (make-glil-mv-bind
935 (vars->bind-list
936 (append req (if rest (list rest) '()))
93f63467 937 gensyms allocation self)
8a4ca0ea
AW
938 (and rest #t)))
939 (for-each (lambda (v)
940 (pmatch (hashq-ref (hashq-ref allocation v) self)
941 ((#t #f . ,n)
942 (emit-code src (make-glil-lexical #t #f 'set n)))
943 ((#t #t . ,n)
944 (emit-code src (make-glil-lexical #t #t 'box n)))
3b24aee6 945 (,loc (error "bad let-values var allocation" x loc))))
93f63467 946 (reverse gensyms))
8a4ca0ea 947 (comp-tail body)
fb135e12 948 (clear-stack-slots context gensyms)
c6601f10
AW
949 (emit-code #f (make-glil-unbind))))))
950
c6601f10
AW
951 ;; What's the deal here? The deal is that we are compiling the start of a
952 ;; delimited continuation. We try to avoid heap allocation in the normal
953 ;; case; so the body is an expression, not a thunk, and we try to render
954 ;; the handler inline. Also we did some analysis, in analyze.scm, so that
955 ;; if the continuation isn't referenced, we don't reify it. This makes it
956 ;; possible to implement catch and throw with delimited continuations,
957 ;; without any overhead.
178a4092 958 ((<prompt> src escape-only? tag body handler)
c6601f10
AW
959 (let ((H (make-label))
960 (POST (make-label))
178a4092
AW
961 (body (if escape-only?
962 (match body
963 (($ <lambda> _ _
964 ($ <lambda-case> _ () #f #f #f () () body #f))
965 body))
966 (make-call #f body '()))))
967
c6601f10
AW
968 ;; First, set up the prompt.
969 (comp-push tag)
ea6b18e8 970 (emit-code src (make-glil-prompt H escape-only?))
c6601f10
AW
971
972 ;; Then we compile the body, with its normal return path, unwinding
973 ;; before proceeding.
974 (case context
975 ((tail)
976 (let ((MV (make-label)))
977 (comp-vals body MV)
978 ;; one value: unwind and return
979 (emit-code #f (make-glil-call 'unwind 0))
980 (emit-code #f (make-glil-call 'return 1))
981 ;; multiple values: unwind and return
982 (emit-label MV)
983 (emit-code #f (make-glil-call 'unwind 0))
984 (emit-code #f (make-glil-call 'return/nvalues 1))))
985
986 ((push)
987 ;; we only want one value. so ask for one value, unwind, and jump to
988 ;; post
989 (comp-push body)
990 (emit-code #f (make-glil-call 'unwind 0))
9dadfa47 991 (emit-branch #f 'br (or RA POST)))
c6601f10
AW
992
993 ((vals)
994 (let ((MV (make-label)))
995 (comp-vals body MV)
996 ;; one value: push 1 and fall through to MV case
997 (emit-code #f (make-glil-const 1))
998 ;; multiple values: unwind and goto MVRA
999 (emit-label MV)
1000 (emit-code #f (make-glil-call 'unwind 0))
1001 (emit-branch #f 'br MVRA)))
1002
1003 ((drop)
1004 ;; compile body, discarding values, then unwind & fall through.
1005 (comp-drop body)
1006 (emit-code #f (make-glil-call 'unwind 0))
1007 (emit-branch #f 'br (or RA POST))))
1008
c6601f10 1009 (emit-label H)
ea6b18e8
AW
1010 ;; Now the handler. The stack is now made up of the continuation, and
1011 ;; then the args to the continuation (pushed separately), and then the
1012 ;; number of args, including the continuation.
178a4092
AW
1013 (match handler
1014 (($ <lambda> src meta
1015 ($ <lambda-case> lsrc req #f rest #f () gensyms body #f))
1016 (emit-code (or lsrc src)
1017 (make-glil-mv-bind
1018 (vars->bind-list
1019 (append req (if rest (list rest) '()))
1020 gensyms allocation self)
1021 (and rest #t)))
ea6b18e8
AW
1022 (for-each (lambda (v)
1023 (pmatch (hashq-ref (hashq-ref allocation v) self)
1024 ((#t #f . ,n)
1025 (emit-code src (make-glil-lexical #t #f 'set n)))
1026 ((#t #t . ,n)
1027 (emit-code src (make-glil-lexical #t #t 'box n)))
3b24aee6
AW
1028 (,loc
1029 (error "bad prompt handler arg allocation" x loc))))
93f63467 1030 (reverse gensyms))
ea6b18e8
AW
1031 (comp-tail body)
1032 (emit-code #f (make-glil-unbind))))
c6601f10 1033
9dadfa47
AW
1034 (if (and (not RA)
1035 (or (eq? context 'push) (eq? context 'drop)))
c6601f10
AW
1036 (emit-label POST))))
1037
2d026f04 1038 ((<abort> src tag args tail)
c6601f10 1039 (comp-push tag)
6e84cb95 1040 (for-each comp-push args)
2d026f04 1041 (comp-push tail)
eaefabee
AW
1042 (emit-code src (make-glil-call 'abort (length args)))
1043 ;; so, the abort can actually return. if it does, the values will be on
1044 ;; the stack, then the MV marker, just as in an MV context.
1045 (case context
1046 ((tail)
1047 ;; Return values.
1048 (emit-code #f (make-glil-call 'return/nvalues 1)))
1049 ((drop)
1050 ;; Drop all values and goto RA, or otherwise fall through.
05c51bcf 1051 (emit-code #f (make-glil-mv-bind 0 #f))
eaefabee
AW
1052 (if RA (emit-branch #f 'br RA)))
1053 ((push)
1054 ;; Truncate to one value.
05c51bcf 1055 (emit-code #f (make-glil-mv-bind 1 #f)))
eaefabee
AW
1056 ((vals)
1057 ;; Go to MVRA.
1058 (emit-branch #f 'br MVRA)))))))