4 clean up
, reduce use of global
/special variables
5 clean up
, separate out initialisation code generation
6 implement large case with hashtable?
8 need to test %catch-tagbody with changes
10 think about implementation of mvcall -- alternative to %mv-collect
12 simplifyer rules
: drop unused variables from continuations?
13 be carefull about unused vs real multiple values
(for dropping no side eff.
)
14 constant folded version of nth-value?
15 push code generaotr test into simplifier?
17 need to recheck calling
, test calling speed
21 Value registers of zero are used to communicate that values should
22 (only) be stored in the multiple value array. This should work OK since
23 the zero register is reserved for the real final value continuation.
25 Continuations are represented in two parts. Part lives in the
26 continuation stack
, part on the value stack. The value stack part may
27 be shared -- this is true for the local calls generated by things like
28 unwind-protect. These local functions cannot overlay their call frame
29 on a tail call
, since that would clobber the part on the value stack.
30 The byte code interpreter checks for this possibility by checking
31 whether the current call stack part of the framt is identical to the
32 one for the next continuation on the stack.
35 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
39 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
47 (defvar *protected-continuations
*)
49 (defun generate-code (pieces)
54 (initialize-functions pieces
)
56 (let ((label (make-label (first p
)))
58 (push-label (first p
))
59 (generate-lambda-code label code
)))
60 (peephole-optimize (list (reverse *code
*)
62 (get-function-label (first (first pieces
)))
64 (nreverse (mapcar #'second
*functions
*)))
65 (get-function-labels))))
67 (defun generate-lambda-code (label n
)
68 (let ((*registers
* nil
)
70 (*protected-continuations
* nil
))
72 ;;**** clean this up!!
73 (let* ((consts (nreverse *constants
*))
74 (ainfo (lambda-node-lambda-list n
))
76 (nv (lambda-list-num-variables ainfo
))
77 (nr (count-registers))
80 (odef (coerce (third ainfo
) 'vector
))
81 (allow-keys (fourth ainfo
))
84 ((and (= nopt
0) (not allow-keys
) (not rest
))
85 (push-instruction `(%initialize-0
,nreq
,nc
,@consts
,(- nr nv nc
))))
86 ((and (not allow-keys
) (not rest
))
87 (let ((ol (add-literal (make-constant-node `(quote ,odef
)))))
89 `(%initialize
1 ,nreq
,nopt
,ol
,nc
,@consts
,(- nr nv nc
)))))
92 (let ((ol (add-literal (make-constant-node `(quote ,odef
)))))
94 `(%initialize
2 ,nreq
,nopt
,ol
,nc
,@consts
,(- nr nv nc
))))
96 `(%initialize
2 ,nreq
,nopt
,nc
,@consts
,(- nr nv nc
)))))
98 (let* ((kdefs (fifth ainfo
))
99 (allow-other-keys (seventh ainfo
))
100 (ksyms (eighth ainfo
))
101 (kdl (add-literal (make-constant-node `(quote ,kdefs
))))
102 (ksl (add-literal (make-constant-node `(quote ,ksyms
))))
103 (aok (if allow-other-keys
1 0))
106 (let ((ol (add-literal (make-constant-node `(quote ,odef
)))))
108 `(%initialize
3 ,nreq
,nopt
,ol
,r
,aok
,ksl
,kdl
109 ,nc
,@consts
,(- nr nv nc
))))
111 `(%initialize
3 ,nreq
,nopt
,r
,aok
,ksl
,kdl
112 ,nc
,@consts
,(- nr nv nc
))))))))
113 (set-function-data-registers (get-function-data label
) (register-map))
114 (generate-body-code (lambda-node-body n
))))
116 (defun generate-body-code (form)
117 (do ((trees (list form
)))
119 (let ((p (first trees
)))
122 ((leaf-node-p p
) (push-label p
) (rest trees
))
123 ((leaf-node-p (call-node-function p
))
124 (generate-symbol-call-code p
(rest trees
)))
125 (t (generate-lambda-call-code p
(rest trees
))))))))
127 (defun lifted-lfun-node-p (n) (and (leaf-node-p n
) (get-function-label n
)))
129 (defun generate-symbol-call-code (n rest
)
130 (let ((f (call-node-function n
)))
132 ((gfun-node-p f
) (generate-gfun-call-code n rest
))
133 ((lifted-lfun-node-p f
) (generate-lfun-call-code n rest
))
134 (t (generate-continuation-call-code n rest
)))))
136 (defun generate-lambda-call-code (n rest
)
137 (let* ((f (call-node-function n
))
138 (alist (lambda-node-arglist f
))
139 (body (lambda-node-body f
))
140 (args (call-node-args n
)))
141 (mapc #'(lambda (x y
)
142 (unless (leaf-node-p y
)
143 (push (lambda-node-body y
) rest
)
151 (defun generate-gfun-call-code (n rest
)
152 (let* ((f (call-node-function n
))
153 (cg (get-code-generator (gfun-symbol f
) n
)))
156 (let* ((c (get-continuation (call-node-arg n
0)))
157 (aregs (mapcar #'find-register
(rest (call-node-args n
))))
160 (if (final-value-continuation-p c
)
161 (let ((cr (continuation-register c
)))
162 (push-instruction `(%call
,s
,cr
,na
,@aregs
)))
163 (let ((vr (continuation-value-register c
)))
164 (push-instruction `(%save-call
,s
,vr
,na
,@aregs
))))
165 (cleanup-continuation c rest nil
)))))
167 (defun generate-lfun-call-code (n rest
)
168 (let* ((f (call-node-function n
))
169 (c (get-continuation (call-node-arg n
0)))
170 (aregs (mapcar #'find-register
(rest (call-node-args n
))))
172 (s (get-function-label f
)))
173 (if (final-value-continuation-p c
)
174 (let ((cr (continuation-register c
)))
175 (push-instruction `(%lcall
,s
,cr
,na
,@aregs
)))
176 (let ((vr (continuation-value-register c
)))
177 (push-instruction `(%save-lcall
,s
,vr
,na
,@aregs
))))
178 (cleanup-continuation c rest nil
)))
180 ;;**** needs to be thought through relative to %y
181 (defun generate-continuation-call-code (n rest
)
182 (let ((c (get-continuation (call-node-function n
))))
183 (case (continuation-type c
)
185 (let ((cr (continuation-register c
))
186 (vr (find-register (call-node-arg n
0))))
187 (push-instruction `(%set-one-value
,vr
))
188 (push-instruction `(%return
,cr
))))
189 ((protected multiple-value
)
190 (let ((aregs (mapcar #'find-register
(call-node-args n
))))
192 ((= (length aregs
) 1)
193 (push-instruction `(%set-one-value
,@aregs
)))
194 (t (warn "multiple value continuation in callposition ~
195 with more than one argument")
196 (push-instruction `(%set-values
,(length aregs
) ,@aregs
))))))
198 (let* ((fsym (continuation-name c
))
199 (f (continuation-function c
))
200 (b (lambda-node-body f
))
201 (vars (lambda-node-arglist f
))
202 (vals (call-node-args n
)))
203 (mapc #'(lambda (x y
)
204 (when (any-references-p y b
)
205 (let ((xr (find-register x
))
206 (yr (find-register y
)))
207 (push-instruction `(%copy
,xr
,yr
)))))
210 (push-instruction `(%goto
,(make-label fsym
))))))
211 (cleanup-continuation c rest nil
)))
215 ;;;; Function Information Representation
218 (defun initialize-functions (pieces)
220 (let* ((label (make-label (first p
)))
221 (d (make-function-data label
(leaf-node-value (first p
)))))
222 (push (list label d
) *functions
*))))
224 (defun make-function-data (label name
) (list label name nil
))
226 (defun get-function-data (label) (second (assoc label
*functions
*)))
227 (defun get-function-label (f) (first (assoc (make-label f
) *functions
*)))
228 (defun get-function-labels () (mapcar #'first
*functions
*))
230 (defun set-function-data-registers (fd r
) (setf (third fd
) r
))
234 ;;;; Continuation Handling
237 (defun get-continuation (n)
238 (if (lambda-node-p n
)
240 (let ((cf (find-lambda-binding n
)))
243 (if (member n
*protected-continuations
*)
247 (defun register-protected-continuation (k)
248 (pushnew k
*protected-continuations
*))
250 (defun immediate-continuation-p (c)
251 (and (lambda-node-p (cdr c
)) (null (continuation-name c
))))
253 (defun continuation-value-ignored-p (c)
254 (and (not (multiple-value-continuation-p c
))
255 (or (null (lambda-node-arglist (cdr c
)))
256 (not (any-references-p (first (lambda-node-arglist (cdr c
)))
259 (defun final-value-continuation-p (c) (eq (cdr c
) 'final
))
261 (defun protected-continuation-p (c) (eq (cdr c
) 'protected
))
263 (defun continuation-register (c) (if (car c
) (find-register (car c
))))
265 (defun multiple-value-continuation-p (c)
266 (multiple-value-continuation-node-p (cdr c
)))
268 (defun continuation-value-register (c)
269 (if (and (lambda-node-p (cdr c
))
270 (not (continuation-value-ignored-p c
))
271 (not (multiple-value-continuation-p c
)))
272 (find-register (first (lambda-node-arglist (cdr c
))))
275 (defun continuation-name (c) (car c
))
276 (defun continuation-function (c) (if (lambda-node-p (cdr c
)) (cdr c
)))
278 (defun continuation-type (c)
280 ((final-value-continuation-p c
) 'final-value
)
281 ((protected-continuation-p c
) 'protected
)
282 ((multiple-value-continuation-p c
) 'multiple-value
)
283 ((continuation-value-ignored-p c
) 'value-ignored
)
286 (defun cleanup-continuation (c rest inline
)
287 (if (final-value-continuation-p c
)
289 (let ((cr (continuation-register c
)))
290 (push-instruction `(%return
,cr
))))
291 (if (immediate-continuation-p c
)
292 (push (lambda-node-body (cdr c
)) rest
)
293 (push-instruction `(%goto
,(make-label (continuation-name c
))))))
298 ;;;; Register Handling
301 (defun find-register (v)
302 (let ((e (assoc v
*registers
*)))
303 (if e
(cdr e
) (error "register not found"))))
305 (defun assign-registers (n)
306 (assign-registers-1 (lambda-node-body n
)
307 (add-lambda-frame (lambda-node-arglist n
) nil
)))
309 (defun pop-unused-frames (env n
)
310 (let ((frame (first env
)))
312 (eq (cdr frame
) 'continuation
)
313 (every #'(lambda (x) (not (any-references-p x n
))) (car frame
)))
314 (pop-unused-frames (cdr env
) n
)
317 (defun setq-continuation-p (n)
318 (if (continuation-node-p n
)
319 (let* ((b (lambda-node-body n
))
320 (f (call-node-function b
)))
321 (if (and (gfun-eq f
'%setq
) (= (length (lambda-node-arglist n
)) 1))
322 (let ((v (first (lambda-node-arglist n
)))
323 (c (call-node-arg b
0)))
324 (and (eq v
(call-node-arg b
2))
325 (assoc (call-node-arg b
1) *registers
*)
326 (not (any-references-p v c
))))))))
328 (defun add-register-frame (vars type env
)
330 (dolist (e env
) (incf maxreg
(length (car e
))))
332 (push (cons v maxreg
) *registers
*)
334 (cons (cons vars type
) env
)))
336 (defun add-lambda-frame (vars env
) (add-register-frame vars
'lambda env
))
338 (defun add-continuation-frame (n env
)
339 (if (setq-continuation-p n
)
340 (let ((v (first (lambda-node-arglist n
)))
341 (vv (call-node-arg (lambda-node-body n
) 1)))
342 (push (cons v
(cdr (assoc vv
*registers
*))) *registers
*)
343 (pop-unused-frames env n
))
344 (let ((alist (lambda-node-arglist n
))
345 (b (lambda-node-body n
)))
346 (if (and (not (multiple-value-continuation-node-p n
))
347 (some #'(lambda (x) (any-references-p x b
)) alist
))
348 (add-register-frame alist
350 (pop-unused-frames env n
))
351 (pop-unused-frames env n
)))))
353 (defun assign-registers-1 (n env
)
354 (let ((f (call-node-function n
))
355 (args (call-node-args n
)))
356 (setf env
(pop-unused-frames env n
)) ;;**** is this OK?
357 (when (lambda-node-p f
)
359 (mapc #'(lambda (x y
)
360 (unless (lambda-node-p y
)
362 (push (add-literal y
) *constants
*)))
363 (lambda-node-arglist f
)
365 ;;**** think about this -- should only have non-nil nfvars once
366 (assign-registers-1 (lambda-node-body f
)
367 (add-lambda-frame (nreverse nfvars
) env
))))
369 (assign-registers-1 (lambda-node-body (call-node-arg n
0)) env
)
370 (let ((is-y-list (gfun-eq f
'%y-list
)))
372 (when (lambda-node-p a
)
373 (let ((new-env (if (and (continuation-node-p a
) (not is-y-list
))
374 (add-continuation-frame a env
)
375 (add-lambda-frame (lambda-node-arglist a
)
377 (assign-registers-1 (lambda-node-body a
) new-env
))))))))
379 (defun count-registers ()
381 (dolist (r *registers
* n
)
382 (setf n
(max n
(+ (cdr r
) 1))))))
384 (defun register-map ()
385 (flet ((rsym (x) (if (symbolp x
) x
(leaf-node-value x
))))
387 (dolist (r *registers
*)
388 (let* ((v (rsym (car r
)))
391 (if e
(pushnew v
(rest e
)) (push (list i v
) regs
))))
392 (sort regs
#'(lambda (x y
) (< (first x
) (first y
)))))))
396 ;;;; Instruction Representation
399 (defun make-label (v)
400 (let ((e (assoc v
*labels
*)))
403 (let ((s (gensym (string (leaf-node-value v
)))))
404 (push (cons v s
) *labels
*)
407 (defun make-label-node (&optional
(label "LABEL"))
408 (make-leaf-node (gensym (string label
))))
410 (defun push-label (v) (push (make-label v
) *code
*))
411 (defun push-instruction (i) (push i
*code
*))
415 ;;;; Literals Representation
418 (defun next-literal-index () (length *literals
*))
420 (defun literal-value (v)
421 (let ((c (leaf-node-value v
)))
422 (if (and (consp c
) (eq (first c
) 'quote
)) (second c
) c
)))
424 (defun push-literal (v)
425 (let ((n (next-literal-index)))
426 (push (literal-value v
) *literals
*)
429 (defun add-literal (c) (add-literal-value (literal-value c
)))
431 (defun add-literal-value (v)
432 (let ((p (position v
*literals
*)))
434 (- (length *literals
*) p
1)
435 (prog1 (length *literals
*) (push v
*literals
*)))))
439 ;;;; Code Generator Support for Special Instuctions
442 (defun get-code-generator (s n
)
443 (let* ((e (get s
'cmp-code-generator
))
446 (if test
(if (funcall test n
) f
) f
)))
448 (defun set-code-generator (s g
)
449 (let ((e (get s
'cmp-code-generator
)))
452 (setf (get s
'cmp-code-generator
) (list nil g
)))))
454 (defun set-code-generator-test (s g
)
455 (let ((e (get s
'cmp-code-generator
)))
458 (setf (get s
'cmp-code-generator
) (list g nil
)))))
460 (defmacro define-code-generator
(sym &rest body
)
461 `(set-code-generator ',sym
#'(lambda ,@body
)))
463 (defmacro define-code-generator-test
(sym &rest body
)
464 `(set-code-generator-test ',sym
#'(lambda ,@body
)))
466 (defun generate-inline-function-code (f n rest
)
467 (let* ((c (get-continuation (call-node-arg n
0)))
468 (vr (continuation-value-register c
))
469 (args (rest (call-node-args n
))))
471 (cleanup-continuation c rest t
)))
473 (defmacro define-inline-function-generator
(sym &rest body
)
474 `(define-code-generator ,sym
(n rest
)
475 (generate-inline-function-code #'(lambda ,@body
) n rest
)))
477 (defmacro define-standard-inline-generator
(sym &optional
479 (llist nil llist-supplied
))
481 ,@(if llist-supplied
`((define-lambda-list ,sym
,llist
)))
482 (define-inline-function-generator ,sym
(args r
)
484 (cons ',name
(append (mapcar #'find-register args
) (list r
)))))))
486 (defmacro define-standard-inline-generator-2
(sym &rest args
)
488 (define-standard-inline-generator ,sym
,@args
)
489 (define-code-generator-test ,sym
(n) (= (call-node-arg-count n
) 3))))
491 (defmacro define-test-code-generator-1
(name opcode
)
492 `(define-code-generator ,name
(n rest
)
493 (let* ((cons (call-node-arg n
0))
494 (alt (call-node-arg n
1))
495 (vr (find-register (call-node-arg n
2)))
496 (clab (if (lambda-node-p cons
) (make-label-node "THEN") cons
))
497 (alab (if (lambda-node-p alt
) (make-label-node "ELSE") alt
)))
499 (list '%test-1
,opcode
(make-label clab
) (make-label alab
) vr
))
500 (when (lambda-node-p alt
)
501 (push (lambda-node-body alt
) rest
)
503 (when (lambda-node-p cons
)
504 (push (lambda-node-body cons
) rest
)
508 (defmacro define-test-code-generator-2
(name opcode
)
509 `(define-code-generator ,name
(n rest
)
510 (let* ((cons (call-node-arg n
0))
511 (alt (call-node-arg n
1))
512 (vr1 (find-register (call-node-arg n
2)))
513 (vr2 (find-register (call-node-arg n
3)))
514 (clab (if (lambda-node-p cons
) (make-label-node "THEN") cons
))
515 (alab (if (lambda-node-p alt
) (make-label-node "ELSE") alt
)))
517 (list '%test-2
,opcode
(make-label clab
) (make-label alab
) vr1 vr2
))
518 (when (lambda-node-p alt
)
519 (push (lambda-node-body alt
) rest
)
521 (when (lambda-node-p cons
)
522 (push (lambda-node-body cons
) rest
)
527 (defmacro define-test-arith-code-generator-2
(name opcode
)
528 `(define-code-generator ,name
(n rest
)
529 (let* ((cons (call-node-arg n
0))
530 (alt (call-node-arg n
1))
531 (vr1 (find-register (call-node-arg n
2)))
532 (vr2 (find-register (call-node-arg n
3)))
533 (clab (if (lambda-node-p cons
) (make-label-node "THEN") cons
))
534 (alab (if (lambda-node-p alt
) (make-label-node "ELSE") alt
)))
542 (when (lambda-node-p alt
)
543 (push (lambda-node-body alt
) rest
)
545 (when (lambda-node-p cons
)
546 (push (lambda-node-body cons
) rest
)
550 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
552 ;;;;; Specific Code Generators
554 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
557 ;;;; Test/Case Code Generators
560 (define-test-code-generator-1 %test
0)
561 (define-test-code-generator-1 %test-consp
1)
562 (define-test-code-generator-1 %test-supplied-p
2)
563 (define-test-code-generator-1 %test-endp
3)
565 (define-test-code-generator-2 %test-eq
0)
566 (define-test-code-generator-2 %test-eql
1)
567 (define-test-code-generator-2 %test-equal
2)
569 (define-test-arith-code-generator-2 %test
= #\
=)
570 (define-test-arith-code-generator-2 %test
/= #\
#)
571 (define-test-arith-code-generator-2 %test
< #\
<)
572 (define-test-arith-code-generator-2 %test
> #\
>)
573 (define-test-arith-code-generator-2 %test
<= #\L
)
574 (define-test-arith-code-generator-2 %test
>= #\G
)
576 (define-code-generator %case
(n rest
)
577 (let* ((var (find-register (call-node-arg n
0)))
578 (choices (find-register (call-node-arg n
1)))
579 (actions (rest (rest (call-node-args n
))))
584 (let ((lab (make-label-node "CASE")))
585 (push (lambda-node-body a
) rest
)
587 (push (make-label lab
) labels
)))
588 (t (push (make-label a
) labels
))))
589 (push-instruction `(%case
,var
,choices
,@(reverse labels
)))
594 ;;;; Multiple Value Code Generators
597 (define-code-generator %mvc
(n rest
)
598 (let ((c (get-continuation (call-node-arg n
0)))
599 (f (call-node-arg n
1)))
600 (if (final-value-continuation-p c
)
601 (let ((cr (continuation-register c
)))
604 (push-instruction `(%mvcall
,(add-literal f
) ,cr
)))
605 ((lifted-lfun-node-p f
)
606 (push-instruction `(%mvlcall
,(get-function-label f
) ,cr
)))
608 (push-instruction `(%mvvcall
,(find-register f
) ,cr
)))))
609 (let ((vr (continuation-value-register c
)))
612 (push-instruction `(%save-mvcall
,(add-literal f
) ,vr
)))
613 ((lifted-lfun-node-p f
)
614 (push-instruction `(%save-mvlcall
,(get-function-label f
) ,vr
)))
616 (push-instruction `(%save-mvvcall
,(find-register f
) ,vr
))))))
617 (cleanup-continuation c rest nil
)))
619 ;;**** is the continuation necessarily both immediate and not multiple value?
620 (define-code-generator %mvcc
(n rest
)
621 (let* ((k (call-node-arg n
0))
622 (alist (lambda-node-arglist k
))
623 (b (lambda-node-body k
)))
624 (if (some #'(lambda (x) (any-references-p x b
)) alist
)
625 (let ((vregs (mapcar #'find-register alist
)))
626 (push-instruction `(%get-values
,(length vregs
) ,@vregs
))))
629 (define-code-generator values
(n rest
)
630 (let* ((c (get-continuation (call-node-arg n
0)))
631 (aregs (mapcar #'find-register
(rest (call-node-args n
))))
632 (r (continuation-value-register c
)))
633 ;;**** check number of values against limit
634 (push-instruction `(%set-values
,(length aregs
) ,@aregs
))
636 (warn "VALUES occurred in non-multiple value continuations")
637 (push-instruction `(%get-one-value
,r
)))
638 (cleanup-continuation c rest t
)))
640 (define-code-generator values-list
(n rest
)
641 (let* ((c (get-continuation (call-node-arg n
0)))
642 (ar (find-register (call-node-arg n
1)))
643 (r (continuation-value-register c
)))
644 (push-instruction `(%set-values-list
,ar
))
646 (warn "VALUES-LIST occurred in non-multiple value continuations")
647 (push-instruction `(%get-one-value
,r
)))
648 (cleanup-continuation c rest t
)))
652 ;;;; Catch/Throw/Unwind-Protect Code Generators
655 (defun cleanup-protected-continuation (label c rest
)
657 (let ((r (continuation-value-register c
)))
658 (unless (= r
0) (push-instruction `(%get-one-value
,r
))))
659 (cleanup-continuation c rest t
))
661 (define-code-generator %catch
(n rest
)
662 (let* ((c (get-continuation (call-node-arg n
0)))
663 (tr (find-register (call-node-arg n
1)))
664 (form-fun (call-node-arg n
2))
665 (fb (lambda-node-body form-fun
))
666 (fv (first (lambda-node-arglist form-fun
)))
667 (fr (find-register fv
))
668 (label (make-label-node "C")))
669 (push-instruction `(%catch
,tr
,(make-label label
) ,fr
))
671 (cleanup-protected-continuation label c rest
)))
673 (define-code-generator %throw
(n rest
)
674 (let ((tr (find-register (call-node-arg n
0))))
675 (push-instruction `(%throw
,tr
))
678 (define-code-generator %catch-block
(n rest
)
679 (let* ((c (get-continuation (call-node-arg n
0)))
680 (nr (find-register (call-node-arg n
1)))
681 (form-fun (call-node-arg n
2))
682 (fb (lambda-node-body form-fun
))
683 (fv (first (lambda-node-arglist form-fun
)))
684 (fr (find-register fv
))
685 (ftr (find-register (second (lambda-node-arglist form-fun
))))
686 (label (make-label-node "C")))
687 (push-instruction `(%catch-block
,nr
,(make-label label
) ,fr
,ftr
))
689 (cleanup-protected-continuation label c rest
)))
691 (define-code-generator %throw-return-from
(n rest
)
692 (let ((tr (find-register (call-node-arg n
0))))
693 (push-instruction `(%throw-return-from
,tr
))
696 (define-code-generator %catch-tagbody
(n rest
)
697 (cons (lambda-node-body (call-node-arg n
1)) rest
))
699 (define-code-generator %do-catch-tagbody
(n rest
)
700 (let* ((c (get-continuation (call-node-arg n
0)))
701 (vr (continuation-value-register c
))
702 (start (call-node-arg n
1))
703 (slab (if (lambda-node-p start
) (make-label-node "TAGBODY") start
))
704 (cr (find-register (call-node-arg n
2)))
705 (tr (find-register (call-node-arg n
3))))
706 (push-instruction `(%catch-tagbody
,(make-label slab
) ,cr
,tr
,vr
))
707 (when (lambda-node-p start
)
708 (push (lambda-node-body start
) rest
)
710 (cleanup-continuation c rest t
)))
712 (define-code-generator %throw-go
(n rest
)
713 (let* ((tr (find-register (call-node-arg n
0)))
714 (target (call-node-arg n
1))
715 (tlab (if (lambda-node-p target
) (make-label-node "TARGET") target
)))
716 (push-instruction `(%throw-go
,tr
,(make-label tlab
)))
717 (when (lambda-node-p target
)
718 (push (lambda-node-body target
) rest
)
722 (define-code-generator %errset
(n rest
)
723 (let* ((c (get-continuation (call-node-arg n
0)))
724 (form-fun (call-node-arg n
1))
725 (fi (find-register (call-node-arg n
2)))
726 (fb (lambda-node-body form-fun
))
727 (fv (first (lambda-node-arglist form-fun
)))
728 (fr (find-register fv
))
729 (label (make-label-node "C")))
730 (push-instruction `(%errset
,(make-label label
) ,fr
,fi
))
732 (cleanup-protected-continuation label c rest
)))
734 (define-code-generator %unwind-protect
(n rest
)
735 (let* ((c (get-continuation (call-node-arg n
0)))
736 (prot-form (call-node-arg n
1))
737 (pfb (lambda-node-body prot-form
))
738 (pfv (first (lambda-node-arglist prot-form
)))
739 (pfr (find-register pfv
))
740 (unwind-form (call-node-arg n
2))
741 (ufb (lambda-node-body unwind-form
))
742 (ufv (first (lambda-node-arglist unwind-form
)))
743 (ufr (find-register ufv
))
744 (label1 (make-label-node "U"))
745 (label2 (make-label-node "U")))
747 `(%unwind-protect
,(make-label label1
) ,(make-label label2
) ,pfr
,ufr
))
751 (cleanup-protected-continuation label2 c rest
)))
753 (define-code-generator %dynamic-bind
(n rest
)
754 (let* ((c (get-continuation (call-node-arg n
0)))
755 (svr (find-register (call-node-arg n
1)))
756 (vvr (find-register (call-node-arg n
2)))
757 (body-form (call-node-arg n
3))
758 (bfb (lambda-node-body body-form
))
759 (bfv (first (lambda-node-arglist body-form
)))
760 (ulabel (make-label bfv
))
761 (label (make-label-node "D")))
762 (register-protected-continuation bfv
)
763 (push-instruction `(%dynamic-bind
,svr
,vvr
))
764 (push-instruction `(%goto
,(make-label label
)))
765 (push-instruction (make-label bfv
))
766 (push-instruction '(%dynamic-unbind
))
768 (cleanup-protected-continuation label c rest
)))
772 ;;;; Y Combinator/Closure Code Generators
775 (define-code-generator %y
(n rest
)
776 (let* ((f (call-node-arg n
0))
777 (names (reverse (lambda-node-arglist f
)))
778 (b (lambda-node-body f
))
779 (bf (call-node-function b
)))
780 (when (gfun-eq bf
'%make-y-closures
)
781 (let* ((bc (call-node-arg b
0))
782 (cr (mapcar #'find-register
(lambda-node-arglist bc
)))
784 (bargs (rest (call-node-args b
)))
785 (fi (mapcar #'(lambda (x y
) (get-function-label x
)) bargs cr
))
786 (fvr (mapcar #'find-register
(nthcdr n bargs
)))
789 (mapc #'(lambda (x y
) (push x ficr
) (push y ficr
)) fi cr
)
790 (setf ficr
(nreverse ficr
))
791 (push-instruction `(%make-y-closures
,n
,nv
,@ficr
,@fvr
))
792 (setf b
(lambda-node-body bc
))))
793 (let* ((y-list-args (call-node-args b
))
794 (body (first y-list-args
))
795 (conts (reverse (rest y-list-args
))))
796 (mapc #'(lambda (x y
)
797 (push (lambda-node-body y
) rest
)
801 (push (lambda-node-body body
) rest
)
804 (define-inline-function-generator %make-closure
(args r
)
805 (let ((f (get-function-label (first args
)))
806 (n (length (rest args
)))
807 (aregs (mapcar #'find-register
(rest args
))))
808 (push-instruction `(%make-closure
,f
,r
,n
,@aregs
))))
812 ;;;; Funcall/Apply Code Generators
815 (define-code-generator funcall
(n rest
)
816 (let* ((c (get-continuation (call-node-arg n
0)))
817 (fr (find-register (call-node-arg n
1)))
818 (aregs (mapcar #'find-register
(rest (rest (call-node-args n
)))))
820 (if (final-value-continuation-p c
)
821 (let ((cr (continuation-register c
)))
822 (push-instruction `(%vcall
,fr
,cr
,na
,@aregs
)))
823 (let ((vr (continuation-value-register c
)))
824 (push-instruction `(%save-vcall
,fr
,vr
,na
,@aregs
))))
825 (cleanup-continuation c rest nil
)))
829 ;;;; Inlined Internal Codes
832 (define-inline-function-generator %symval
(args r
)
833 (push-instruction `(%symval
,(add-literal (first args
)) ,r
)))
835 (define-inline-function-generator %symfun
(args r
)
836 (push-instruction `(%symfun
,(add-literal (first args
)) ,r
)))
838 (define-inline-function-generator %set-symval
(args r
)
839 (push-instruction `(%set-symval
,(add-literal (first args
))
840 ,(find-register (second args
))
843 (define-standard-inline-generator %copy
)
845 (define-code-generator %setq
(n rest
)
846 (let* ((c (get-continuation (call-node-arg n
0)))
847 (p (find-register (call-node-arg n
1)))
848 (q (find-register (call-node-arg n
2)))
849 (r (continuation-value-register c
)))
850 (push-instruction `(%copy
,q
,p
))
852 ((/= r
0) (push-instruction `(%copy
,q
,r
)))
853 ((not (eq (continuation-type c
) 'value-ignored
))
854 (push-instruction `(%set-one-value
,q
))))
855 (cleanup-continuation c rest t
)))
857 (define-standard-inline-generator %supplied-p
)
858 (define-standard-inline-generator %make-cell
)
859 (define-standard-inline-generator %cell-value
)
860 (define-standard-inline-generator %set-cell-value
)
863 ;**** drop once implementation changes
864 (define-code-generator %mv-collect
(n rest
)
865 (cleanup-continuation (get-continuation (call-node-arg n
0)) rest nil
))
867 (define-standard-inline-generator %nth-value %nth-value
(x))
869 (define-code-generator %push-values
(n rest
)
870 (let* ((c (get-continuation (call-node-arg n
0)))
871 (r (continuation-value-register c
)))
872 (unless (= r
0) (push-instruction `(%push-values
,r
)))
873 (cleanup-continuation c rest nil
)))
875 (define-code-generator %pop-values
(n rest
)
876 (let* ((c (get-continuation (call-node-arg n
0)))
877 (nv (find-register (call-node-arg n
1)))
878 (r (continuation-value-register c
)))
879 (push-instruction `(%pop-values
,nv
))
880 (unless (= r
0) (push-instruction `(%get-one-value
,r
)))
881 (cleanup-continuation c rest t
)))
885 ;;;; Inlined Function Code Generators
888 ;;**** these could handle 3 args specially but funcall for 4 or more
889 (define-lambda-list + (&rest a
))
890 (define-inline-function-generator + (args r
)
891 (push-instruction `(%arith2
,(char-int #\
+)
892 ,(find-register (first args
))
893 ,(find-register (second args
))
895 (define-code-generator-test + (n) (= (call-node-arg-count n
) 3))
897 (define-lambda-list * (&rest a
))
898 (define-inline-function-generator * (args r
)
899 (push-instruction `(%arith2
,(char-int #\
*)
900 ,(find-register (first args
))
901 ,(find-register (second args
))
903 (define-code-generator-test * (n) (= (call-node-arg-count n
) 3))
905 (define-lambda-list -
(x &rest a
))
906 (define-inline-function-generator -
(args r
)
908 (1 (push-instruction `(%arith1
,(char-int #\-
)
909 ,(find-register (first args
)) ,r
)))
910 (2 (push-instruction `(%arith2
,(char-int #\-
)
911 ,(find-register (first args
))
912 ,(find-register (second args
))
914 (define-code-generator-test -
(n) (<= (call-node-arg-count n
) 3))
916 (define-lambda-list / (x &rest a
))
917 (define-inline-function-generator / (args r
)
919 (1 (push-instruction `(%arith1
,(char-int #\
/)
920 ,(find-register (first args
)) ,r
)))
921 (2 (push-instruction `(%arith2
,(char-int #\
/)
922 ,(find-register (first args
))
923 ,(find-register (second args
))
925 (define-code-generator-test / (n) (<= (call-node-arg-count n
) 3))
927 (define-lambda-list min
(x &rest a
))
928 (define-inline-function-generator min
(args r
)
929 (push-instruction `(%arith2
,(char-int #\m
)
930 ,(find-register (first args
))
931 ,(find-register (second args
))
933 (define-code-generator-test min
(n) (= (call-node-arg-count n
) 3))
935 (define-lambda-list max
(x &rest a
))
936 (define-inline-function-generator max
(args r
)
937 (push-instruction `(%arith2
,(char-int #\M
)
938 ,(find-register (first args
))
939 ,(find-register (second args
))
941 (define-code-generator-test max
(n) (= (call-node-arg-count n
) 3))
943 (defmacro define-arith-pred-generator-2
(sym char
)
945 (define-lambda-list ,sym
(x &rest a
))
946 (define-inline-function-generator ,sym
(args r
)
950 (find-register (first args
))
951 (find-register (second args
))
953 (define-code-generator-test ,sym
(n) (= (call-node-arg-count n
) 3))))
955 (define-arith-pred-generator-2 < #\
<)
956 (define-arith-pred-generator-2 <= #\L
)
957 (define-arith-pred-generator-2 = #\
=)
958 (define-arith-pred-generator-2 /= #\
#)
959 (define-arith-pred-generator-2 >= #\G
)
960 (define-arith-pred-generator-2 > #\
>)
962 (define-standard-inline-generator-2 get %get
)
963 (define-standard-inline-generator-2 %set-get
)
965 (define-standard-inline-generator consp %consp
(x))
966 (define-standard-inline-generator endp %endp
(x))
967 (define-standard-inline-generator eq %eq
(x y
))
968 (define-standard-inline-generator eql %eql
(x y
))
969 (define-standard-inline-generator equal %equal
(x y
))
971 (define-inline-function-generator aref
(args r
)
973 (2 (push-instruction `(%aref1
,(find-register (first args
))
974 ,(find-register (second args
))
976 (3 (push-instruction `(%aref2
,(find-register (first args
))
977 ,(find-register (second args
))
978 ,(find-register (third args
))
980 (define-code-generator-test aref
(n) (<= 3 (call-node-arg-count n
) 4))
981 (define-lambda-list aref
(x &rest args
))
983 (define-inline-function-generator %set-aref
(args r
)
985 (3 (push-instruction `(%set-aref1
,(find-register (first args
))
986 ,(find-register (second args
))
987 ,(find-register (third args
))
989 (4 (push-instruction `(%set-aref2
,(find-register (first args
))
990 ,(find-register (second args
))
991 ,(find-register (third args
))
992 ,(find-register (fourth args
))
994 (define-code-generator-test %set-aref
(n) (<= 4 (call-node-arg-count n
) 5))
995 (define-lambda-list %set-aref
(x v
&rest args
))
997 ;;**** check if others are needed
998 (define-standard-inline-generator %set-nth %set-nth
(i x v
))
999 (define-standard-inline-generator rplaca %rplaca
(x v
))
1000 (define-standard-inline-generator rplacd %rplacd
(x v
))
1001 (define-standard-inline-generator %set-svref %set-svref
(x i v
))
1002 (define-standard-inline-generator %set-elt %set-elt
(x i v
))
1004 (define-standard-inline-generator nth %nth
(i x
))
1005 (define-standard-inline-generator svref %svref
(x i
))
1006 (define-standard-inline-generator elt %elt
(x i
))
1008 (define-standard-inline-generator cons %cons
(x y
))
1010 (define-lambda-list 1+ (x))
1011 (define-inline-function-generator 1+ (args r
)
1012 (push-instruction `(%arith1
,(char-int #\p
)
1013 ,(find-register (first args
))
1016 (define-lambda-list 1-
(x))
1017 (define-inline-function-generator 1-
(args r
)
1018 (push-instruction `(%arith1
,(char-int #\m
)
1019 ,(find-register (first args
))
1027 (define-lambda-list slot-value
(x &optional y
))
1029 (define-inline-function-generator slot-value
(args r
)
1031 (1 (push-instruction `(%slot-value
,(find-register (first args
)) ,r
)))
1032 (2 (push-instruction `(%set-slot-value
,(find-register (first args
))
1033 ,(find-register (second args
))
1037 ;; C?R, C??R and C???R
1040 (define-lambda-list car
(x))
1041 (define-standard-inline-generator car %car
)
1043 (define-lambda-list cdr
(x))
1044 (define-standard-inline-generator cdr %cdr
)
1046 (defmacro define-cxr-generator
(name n x
)
1048 (define-lambda-list ,name
(x))
1049 (define-inline-function-generator ,name
(args r
)
1050 (push-instruction (list '%cxr
,n
,x
(find-register (first args
)) r
)))))
1052 (define-cxr-generator caar
2 #b11
)
1053 (define-cxr-generator cadr
2 #b10
)
1054 (define-cxr-generator cdar
2 #b01
)
1055 (define-cxr-generator cddr
2 #b00
)
1057 (define-cxr-generator caaar
3 #b111
)
1058 (define-cxr-generator caadr
3 #b110
)
1059 (define-cxr-generator cadar
3 #b101
)
1060 (define-cxr-generator caddr
3 #b100
)
1061 (define-cxr-generator cdaar
3 #b011
)
1062 (define-cxr-generator cdadr
3 #b010
)
1063 (define-cxr-generator cddar
3 #b001
)
1064 (define-cxr-generator cdddr
3 #b000
)
1067 ;; CAR and CDR setf methods
1070 (define-standard-inline-generator %set-car %set-car
(x v
))
1071 (define-standard-inline-generator %set-cdr %set-cdr
(x v
))