1 ;;;; This file contains the implementation-independent facilities used
2 ;;;; for defining the compiler's interface to the VM in a given
3 ;;;; implementation that are needed at meta-compile time. They are
4 ;;;; separated out from vmdef.lisp so that they can be compiled and
5 ;;;; loaded without trashing the running compiler.
7 ;;;; FIXME: The "trashing the running [CMU CL] compiler" motivation no
8 ;;;; longer makes sense in SBCL, since we can cross-compile cleanly.
10 ;;;; This software is part of the SBCL system. See the README file for
11 ;;;; more information.
13 ;;;; This software is derived from the CMU CL system, which was
14 ;;;; written at Carnegie Mellon University and released into the
15 ;;;; public domain. The software is in the public domain and is
16 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
17 ;;;; files for more information.
21 ;;;; storage class and storage base definition
23 ;;; Define a storage base having the specified NAME. KIND may be :FINITE,
24 ;;; :UNBOUNDED or :NON-PACKED. The following keywords are legal:
25 ;;; :SIZE specifies the number of locations in a :FINITE SB or
26 ;;; the initial size of an :UNBOUNDED SB.
28 ;;; We enter the basic structure at meta-compile time, and then fill
29 ;;; in the missing slots at load time.
30 (defmacro define-storage-base (name kind &key size)
32 (declare (type symbol name))
33 (declare (type (member :finite :unbounded :non-packed) kind))
35 ;; SIZE is either mandatory or forbidden.
39 (error "A size specification is meaningless in a ~S SB." kind)))
41 (unless size (error "Size is not specified in a ~S SB." kind))
42 (aver (typep size 'unsigned-byte))))
44 (let ((res (if (eq kind :non-packed)
45 (make-sb :name name :kind kind)
46 (make-finite-sb :name name :kind kind :size size))))
48 (eval-when (:compile-toplevel :load-toplevel :execute)
49 (/show0 "about to SETF GETHASH META-SB-NAMES in DEFINE-STORAGE-BASE")
50 (setf (gethash ',name *backend-meta-sb-names*)
52 (/show0 "about to SETF GETHASH SB-NAMES in DEFINE-STORAGE-BASE")
53 ,(if (eq kind :non-packed)
54 `(setf (gethash ',name *backend-sb-names*)
56 `(let ((res (copy-finite-sb ',res)))
57 (/show0 "not :NON-PACKED, i.e. hairy case")
58 (setf (finite-sb-always-live res)
61 #-(or sb-xc sb-xc-host) #*
62 ;; The cross-compiler isn't very good
63 ;; at dumping specialized arrays; we
64 ;; work around that by postponing
65 ;; generation of the specialized
66 ;; array 'til runtime.
67 #+(or sb-xc sb-xc-host)
68 (make-array 0 :element-type 'bit)))
69 (/show0 "doing second SETF")
70 (setf (finite-sb-conflicts res)
71 (make-array ',size :initial-element '#()))
72 (/show0 "doing third SETF")
73 (setf (finite-sb-live-tns res)
74 (make-array ',size :initial-element nil))
75 (/show0 "doing fourth SETF")
76 (setf (finite-sb-always-live-count res)
77 (make-array ',size :initial-element 0))
78 (/show0 "doing fifth and final SETF")
79 (setf (gethash ',name *backend-sb-names*)
82 (/show0 "about to put SB onto/into SB-LIST")
83 (setf *backend-sb-list*
84 (cons (sb-or-lose ',name)
85 (remove ',name *backend-sb-list* :key #'sb-name)))
86 (/show0 "finished with DEFINE-STORAGE-BASE expansion")
89 ;;; Define a storage class NAME that uses the named Storage-Base.
90 ;;; NUMBER is a small, non-negative integer that is used as an alias.
91 ;;; The following keywords are defined:
93 ;;; :ELEMENT-SIZE Size
94 ;;; The size of objects in this SC in whatever units the SB uses.
95 ;;; This defaults to 1.
98 ;;; The alignment restrictions for this SC. TNs will only be
99 ;;; allocated at offsets that are an even multiple of this number.
100 ;;; This defaults to 1.
102 ;;; :LOCATIONS (Location*)
103 ;;; If the SB is :FINITE, then this is a list of the offsets within
104 ;;; the SB that are in this SC.
106 ;;; :RESERVE-LOCATIONS (Location*)
107 ;;; A subset of the Locations that the register allocator should try to
108 ;;; reserve for operand loading (instead of to hold variable values.)
110 ;;; :SAVE-P {T | NIL}
111 ;;; If T, then values stored in this SC must be saved in one of the
112 ;;; non-save-p :ALTERNATE-SCs across calls.
114 ;;; :ALTERNATE-SCS (SC*)
115 ;;; Indicates other SCs that can be used to hold values from this SC across
116 ;;; calls or when storage in this SC is exhausted. The SCs should be
117 ;;; specified in order of decreasing \"goodness\". There must be at least
118 ;;; one SC in an unbounded SB, unless this SC is only used for restricted or
121 ;;; :CONSTANT-SCS (SC*)
122 ;;; A list of the names of all the constant SCs that can be loaded into this
123 ;;; SC by a move function.
124 (defmacro define-storage-class (name number sb-name &key (element-size '1)
125 (alignment '1) locations reserve-locations
126 save-p alternate-scs constant-scs)
127 (declare (type symbol name))
128 (declare (type sc-number number))
129 (declare (type symbol sb-name))
130 (declare (type list locations reserve-locations alternate-scs constant-scs))
131 (declare (type boolean save-p))
132 (unless (= (logcount alignment) 1)
133 (error "alignment not a power of two: ~W" alignment))
135 (let ((sb (meta-sb-or-lose sb-name)))
136 (if (eq (sb-kind sb) :finite)
137 (let ((size (sb-size sb))
138 (element-size (eval element-size)))
139 (declare (type unsigned-byte element-size))
140 (dolist (el locations)
141 (declare (type unsigned-byte el))
142 (unless (<= 1 (+ el element-size) size)
143 (error "SC element ~W out of bounds for ~S" el sb))))
145 (error ":LOCATIONS is meaningless in a ~S SB." (sb-kind sb))))
147 (unless (subsetp reserve-locations locations)
148 (error "RESERVE-LOCATIONS not a subset of LOCATIONS."))
150 (when (and (or alternate-scs constant-scs)
151 (eq (sb-kind sb) :non-packed))
153 "It's meaningless to specify alternate or constant SCs in a ~S SB."
157 (if (or (eq sb-name 'non-descriptor-stack)
158 (find 'non-descriptor-stack
159 (mapcar #'meta-sc-or-lose alternate-scs)
161 (sb-name (sc-sb x)))))
164 (eval-when (:compile-toplevel :load-toplevel :execute)
165 (let ((res (make-sc :name ',name :number ',number
166 :sb (meta-sb-or-lose ',sb-name)
167 :element-size ,element-size
168 :alignment ,alignment
169 :locations ',locations
170 :reserve-locations ',reserve-locations
172 :number-stack-p ,nstack-p
173 :alternate-scs (mapcar #'meta-sc-or-lose
175 :constant-scs (mapcar #'meta-sc-or-lose
177 (setf (gethash ',name *backend-meta-sc-names*) res)
178 (setf (svref *backend-meta-sc-numbers* ',number) res)
179 (setf (svref (sc-load-costs res) ',number) 0)))
181 (let ((old (svref *backend-sc-numbers* ',number)))
182 (when (and old (not (eq (sc-name old) ',name)))
183 (warn "redefining SC number ~W from ~S to ~S" ',number
184 (sc-name old) ',name)))
186 (setf (svref *backend-sc-numbers* ',number)
187 (meta-sc-or-lose ',name))
188 (setf (gethash ',name *backend-sc-names*)
189 (meta-sc-or-lose ',name))
190 (setf (sc-sb (sc-or-lose ',name)) (sb-or-lose ',sb-name))
193 ;;;; move/coerce definition
195 ;;; Given a list of pairs of lists of SCs (as given to DEFINE-MOVE-VOP,
196 ;;; etc.), bind TO-SC and FROM-SC to all the combinations.
197 (defmacro do-sc-pairs ((from-sc-var to-sc-var scs) &body body)
198 `(do ((froms ,scs (cddr froms))
199 (tos (cdr ,scs) (cddr tos)))
201 (dolist (from (car froms))
202 (let ((,from-sc-var (meta-sc-or-lose from)))
203 (dolist (to (car tos))
204 (let ((,to-sc-var (meta-sc-or-lose to)))
207 ;;; Define the function NAME and note it as the function used for
208 ;;; moving operands from the From-SCs to the To-SCs. Cost is the cost
209 ;;; of this move operation. The function is called with three
210 ;;; arguments: the VOP (for context), and the source and destination
211 ;;; TNs. An ASSEMBLE form is wrapped around the body. All uses of
212 ;;; DEFINE-MOVE-FUN should be compiled before any uses of
214 (defmacro define-move-fun ((name cost) lambda-list scs &body body)
215 (declare (type index cost))
216 (when (or (oddp (length scs)) (null scs))
217 (error "malformed SCs spec: ~S" scs))
219 (eval-when (:compile-toplevel :load-toplevel :execute)
220 (do-sc-pairs (from-sc to-sc ',scs)
221 (unless (eq from-sc to-sc)
222 (let ((num (sc-number from-sc)))
223 (setf (svref (sc-move-funs to-sc) num) ',name)
224 (setf (svref (sc-load-costs to-sc) num) ',cost)))))
226 (defun ,name ,lambda-list
227 (sb!assem:assemble (*code-segment* ,(first lambda-list))
230 (eval-when (:compile-toplevel :load-toplevel :execute)
231 (defparameter *sc-vop-slots*
232 '((:move . sc-move-vops)
233 (:move-arg . sc-move-arg-vops))))
235 ;;; Make NAME be the VOP used to move values in the specified FROM-SCs
236 ;;; to the representation of the TO-SCs of each SC pair in SCS.
238 ;;; If KIND is :MOVE-ARG, then the VOP takes an extra argument,
239 ;;; which is the frame pointer of the frame to move into.
241 ;;; We record the VOP and costs for all SCs that we can move between
242 ;;; (including implicit loading).
243 (defmacro define-move-vop (name kind &rest scs)
244 (when (or (oddp (length scs)) (null scs))
245 (error "malformed SCs spec: ~S" scs))
246 (let ((accessor (or (cdr (assoc kind *sc-vop-slots*))
247 (error "unknown kind ~S" kind))))
249 ,@(when (eq kind :move)
250 `((eval-when (:compile-toplevel :load-toplevel :execute)
251 (do-sc-pairs (from-sc to-sc ',scs)
252 (compute-move-costs from-sc to-sc
254 (vop-parse-or-lose name)))))))
256 (let ((vop (template-or-lose ',name)))
257 (do-sc-pairs (from-sc to-sc ',scs)
258 (dolist (dest-sc (cons to-sc (sc-alternate-scs to-sc)))
259 (let ((vec (,accessor dest-sc)))
260 (let ((scn (sc-number from-sc)))
261 (setf (svref vec scn)
262 (adjoin-template vop (svref vec scn))))
263 (dolist (sc (append (sc-alternate-scs from-sc)
264 (sc-constant-scs from-sc)))
265 (let ((scn (sc-number sc)))
266 (setf (svref vec scn)
267 (adjoin-template vop (svref vec scn))))))))))))
269 ;;;; primitive type definition
271 (defun meta-primitive-type-or-lose (name)
273 (or (gethash name *backend-meta-primitive-type-names*)
274 (error "~S is not a defined primitive type." name))))
276 ;;; Define a primitive type NAME. Each SCS entry specifies a storage
277 ;;; class that values of this type may be allocated in. TYPE is the
278 ;;; type descriptor for the Lisp type that is equivalent to this type.
279 (defmacro !def-primitive-type (name scs &key (type name))
280 (declare (type symbol name) (type list scs))
281 (let ((scns (mapcar #'meta-sc-number-or-lose scs)))
283 (/show0 "doing !DEF-PRIMITIVE-TYPE, NAME=..")
284 (/primitive-print ,(symbol-name name))
285 (eval-when (#-sb-xc :compile-toplevel :load-toplevel :execute)
286 (setf (gethash ',name *backend-meta-primitive-type-names*)
287 (make-primitive-type :name ',name
290 ,(once-only ((n-old `(gethash ',name *backend-primitive-type-names*)))
292 ;; If the PRIMITIVE-TYPE structure already exists, we
293 ;; destructively modify it so that existing references in
294 ;; templates won't be invalidated. FIXME: This should no
295 ;; longer be an issue in SBCL, since we don't try to do
296 ;; serious surgery on ourselves. Probably this should
297 ;; just become an assertion that N-OLD is NIL, so that we
298 ;; don't have to try to maintain the correctness of the
299 ;; never-ordinarily-used clause.
300 (/show0 "in !DEF-PRIMITIVE-TYPE, about to COND")
302 (/show0 "in ,N-OLD clause of COND")
303 (setf (primitive-type-scs ,n-old) ',scns)
304 (setf (primitive-type-specifier ,n-old) ',type))
306 (/show0 "in T clause of COND")
307 (setf (gethash ',name *backend-primitive-type-names*)
308 (make-primitive-type :name ',name
310 :specifier ',type))))
311 (/show0 "done with !DEF-PRIMITIVE-TYPE")
314 ;;; Define NAME to be an alias for RESULT in VOP operand type restrictions.
315 (defmacro !def-primitive-type-alias (name result)
316 ;; Just record the translation.
317 `(eval-when (:compile-toplevel :load-toplevel :execute)
318 (setf (gethash ',name *backend-primitive-type-aliases*) ',result)
321 (defparameter *primitive-type-slot-alist*
322 '((:check . primitive-type-check)))
324 ;;; Primitive-Type-VOP Vop (Kind*) Type*
326 ;;; Annotate all the specified primitive Types with the named VOP
327 ;;; under each of the specified kinds:
330 ;;; A one-argument one-result VOP that moves the argument to the
331 ;;; result, checking that the value is of this type in the process.
332 (defmacro primitive-type-vop (vop kinds &rest types)
333 (let ((n-vop (gensym))
335 `(let ((,n-vop (template-or-lose ',vop)))
338 `(let ((,n-type (primitive-type-or-lose ',type)))
341 (let ((slot (or (cdr (assoc kind
342 *primitive-type-slot-alist*))
343 (error "unknown kind: ~S" kind))))
344 `(setf (,slot ,n-type) ,n-vop)))
349 ;;; Return true if SC is either one of PTYPE's SC's, or one of those
350 ;;; SC's alternate or constant SCs.
351 (defun meta-sc-allowed-by-primitive-type (sc ptype)
352 (declare (type sc sc) (type primitive-type ptype))
353 (let ((scn (sc-number sc)))
354 (dolist (allowed (primitive-type-scs ptype) nil)
355 (when (eql allowed scn)
357 (let ((allowed-sc (svref *backend-meta-sc-numbers* allowed)))
358 (when (or (member sc (sc-alternate-scs allowed-sc))
359 (member sc (sc-constant-scs allowed-sc)))
362 ;;;; VOP definition structures
364 ;;;; DEFINE-VOP uses some fairly complex data structures at
365 ;;;; meta-compile time, both to hold the results of parsing the
366 ;;;; elaborate syntax and to retain the information so that it can be
367 ;;;; inherited by other VOPs.
369 ;;; A VOP-PARSE object holds everything we need to know about a VOP at
370 ;;; meta-compile time.
371 (def!struct (vop-parse
372 (:make-load-form-fun just-dump-it-normally)
373 #-sb-xc-host (:pure t))
374 ;; the name of this VOP
375 (name nil :type symbol)
376 ;; If true, then the name of the VOP we inherit from.
377 (inherits nil :type (or symbol null))
378 ;; lists of OPERAND-PARSE structures describing the arguments,
379 ;; results and temporaries of the VOP
380 (args nil :type list)
381 (results nil :type list)
382 (temps nil :type list)
383 ;; OPERAND-PARSE structures containing information about more args
384 ;; and results. If null, then there there are no more operands of
386 (more-args nil :type (or operand-parse null))
387 (more-results nil :type (or operand-parse null))
388 ;; a list of all the above together
389 (operands nil :type list)
390 ;; names of variables that should be declared IGNORE
391 (ignores () :type list)
392 ;; true if this is a :CONDITIONAL VOP. T if a branchful VOP,
393 ;; a list of condition descriptor otherwise. See $ARCH/pred.lisp
394 ;; for more information.
396 ;; argument and result primitive types. These are pulled out of the
397 ;; operands, since we often want to change them without respecifying
399 (arg-types :unspecified :type (or (member :unspecified) list))
400 (result-types :unspecified :type (or (member :unspecified) list))
401 ;; the guard expression specified, or NIL if none
403 ;; the cost of and body code for the generator
404 (cost 0 :type unsigned-byte)
405 (body :unspecified :type (or (member :unspecified) list))
406 ;; info for VOP variants. The list of forms to be evaluated to get
407 ;; the variant args for this VOP, and the list of variables to be
408 ;; bound to the variant args.
409 (variant () :type list)
410 (variant-vars () :type list)
411 ;; variables bound to the VOP and Vop-Node when in the generator body
412 (vop-var '.vop. :type symbol)
413 (node-var nil :type (or symbol null))
414 ;; a list of the names of the codegen-info arguments to this VOP
415 (info-args () :type list)
416 ;; an efficiency note associated with this VOP
417 (note nil :type (or string null))
418 ;; a list of the names of the Effects and Affected attributes for
420 (effects '#1=(any) :type list)
421 (affected '#1# :type list)
422 ;; a list of the names of functions this VOP is a translation of and
423 ;; the policy that allows this translation to be done. :FAST is a
424 ;; safe default, since it isn't a safe policy.
425 (translate () :type list)
426 (ltn-policy :fast :type ltn-policy)
427 ;; stuff used by life analysis
428 (save-p nil :type (member t nil :compute-only :force-to-stack))
429 ;; info about how to emit MOVE-ARG VOPs for the &MORE operand in
431 (move-args nil :type (member nil :local-call :full-call :known-return)))
432 (defprinter (vop-parse)
434 (inherits :test inherits)
438 (more-args :test more-args)
439 (more-results :test more-results)
440 (conditional-p :test conditional-p)
446 (variant :test variant)
447 (variant-vars :test variant-vars)
448 (info-args :test info-args)
454 (save-p :test save-p)
455 (move-args :test move-args))
457 ;;; An OPERAND-PARSE object contains stuff we need to know about an
458 ;;; operand or temporary at meta-compile time. Besides the obvious
459 ;;; stuff, we also store the names of per-operand temporaries here.
460 (def!struct (operand-parse
461 (:make-load-form-fun just-dump-it-normally)
462 #-sb-xc-host (:pure t))
463 ;; name of the operand (which we bind to the TN)
464 (name nil :type symbol)
465 ;; the way this operand is used:
467 :type (member :argument :result :temporary
468 :more-argument :more-result))
469 ;; If true, the name of an operand that this operand is targeted to.
470 ;; This is only meaningful in :ARGUMENT and :TEMPORARY operands.
471 (target nil :type (or symbol null))
472 ;; TEMP is a temporary that holds the TN-REF for this operand.
473 (temp (make-operand-parse-temp) :type symbol)
474 ;; the time that this operand is first live and the time at which it
475 ;; becomes dead again. These are TIME-SPECs, as returned by
479 ;; a list of the names of the SCs that this operand is allowed into.
480 ;; If false, there is no restriction.
482 ;; Variable that is bound to the load TN allocated for this operand, or to
483 ;; NIL if no load-TN was allocated.
484 (load-tn (make-operand-parse-load-tn) :type symbol)
485 ;; an expression that tests whether to do automatic operand loading
487 ;; In a wired or restricted temporary this is the SC the TN is to be
488 ;; packed in. Null otherwise.
489 (sc nil :type (or symbol null))
490 ;; If non-null, we are a temp wired to this offset in SC.
491 (offset nil :type (or unsigned-byte null)))
492 (defprinter (operand-parse)
495 (target :test target)
501 (offset :test offset))
503 ;;;; miscellaneous utilities
505 ;;; Find the operand or temporary with the specifed Name in the VOP
506 ;;; Parse. If there is no such operand, signal an error. Also error if
507 ;;; the operand kind isn't one of the specified Kinds. If Error-P is
508 ;;; NIL, just return NIL if there is no such operand.
509 (defun find-operand (name parse &optional
510 (kinds '(:argument :result :temporary))
512 (declare (symbol name) (type vop-parse parse) (list kinds))
513 (let ((found (find name (vop-parse-operands parse)
514 :key #'operand-parse-name)))
516 (unless (member (operand-parse-kind found) kinds)
517 (error "Operand ~S isn't one of these kinds: ~S." name kinds))
519 (error "~S is not an operand to ~S." name (vop-parse-name parse))))
522 ;;; Get the VOP-PARSE structure for NAME or die trying. For all
523 ;;; meta-compile time uses, the VOP-PARSE should be used instead of
525 (defun vop-parse-or-lose (name)
527 (or (gethash name *backend-parsed-vops*)
528 (error "~S is not the name of a defined VOP." name))))
530 ;;; Return a list of LET-forms to parse a TN-REF list into the temps
531 ;;; specified by the operand-parse structures. MORE-OPERAND is the
532 ;;; OPERAND-PARSE describing any more operand, or NIL if none. REFS is
533 ;;; an expression that evaluates into the first TN-REF.
534 (defun access-operands (operands more-operand refs)
535 (declare (list operands))
538 (dolist (op operands)
539 (let ((n-ref (operand-parse-temp op)))
540 (res `(,n-ref ,prev))
541 (setq prev `(tn-ref-across ,n-ref))))
544 (res `(,(operand-parse-name more-operand) ,prev))))
547 ;;; This is used with ACCESS-OPERANDS to prevent warnings for TN-REF
548 ;;; temps not used by some particular function. It returns the name of
549 ;;; the last operand, or NIL if OPERANDS is NIL.
550 (defun ignore-unreferenced-temps (operands)
552 (operand-parse-temp (car (last operands)))))
554 ;;; Grab an arg out of a VOP spec, checking the type and syntax and stuff.
555 (defun vop-spec-arg (spec type &optional (n 1) (last t))
556 (let ((len (length spec)))
558 (error "~:R argument missing: ~S" n spec))
559 (when (and last (> len (1+ n)))
560 (error "extra junk at end of ~S" spec))
561 (let ((thing (elt spec n)))
562 (unless (typep thing type)
563 (error "~:R argument is not a ~S: ~S" n type spec))
568 ;;; Return a time spec describing a time during the evaluation of a
569 ;;; VOP, used to delimit operand and temporary lifetimes. The
570 ;;; representation is a cons whose CAR is the number of the evaluation
571 ;;; phase and the CDR is the sub-phase. The sub-phase is 0 in the
572 ;;; :LOAD and :SAVE phases.
573 (defun parse-time-spec (spec)
574 (let ((dspec (if (atom spec) (list spec 0) spec)))
575 (unless (and (= (length dspec) 2)
576 (typep (second dspec) 'unsigned-byte))
577 (error "malformed time specifier: ~S" spec))
579 (cons (case (first dspec)
586 (error "unknown phase in time specifier: ~S" spec)))
589 ;;; Return true if the time spec X is the same or later time than Y.
590 (defun time-spec-order (x y)
591 (or (> (car x) (car y))
592 (and (= (car x) (car y))
593 (>= (cdr x) (cdr y)))))
595 ;;;; generation of emit functions
597 (defun compute-temporaries-description (parse)
598 (let ((temps (vop-parse-temps parse))
599 (element-type '(unsigned-byte 16)))
601 (let ((results (make-specializable-array
603 :element-type element-type))
606 (declare (type operand-parse temp))
607 (let ((sc (operand-parse-sc temp))
608 (offset (operand-parse-offset temp)))
610 (setf (aref results index)
612 (+ (ash offset (1+ sc-bits))
613 (ash (meta-sc-number-or-lose sc) 1)
615 (ash (meta-sc-number-or-lose sc) 1))))
617 ;; KLUDGE: The load-time MAKE-ARRAY here is an artifact of our
618 ;; cross-compilation strategy, and the conservative
619 ;; assumptions we are forced to make on which specialized
620 ;; arrays exist on the host lisp that the cross-compiler is
621 ;; running on. (We used to use COERCE here, but that caused
622 ;; SUBTYPEP calls too early in cold-init for comfort). --
624 `(make-array ,(length results) :element-type '(specializable ,element-type) :initial-contents ',results)))))
626 (defun compute-ref-ordering (parse)
627 (let* ((num-args (+ (length (vop-parse-args parse))
628 (if (vop-parse-more-args parse) 1 0)))
629 (num-results (+ (length (vop-parse-results parse))
630 (if (vop-parse-more-results parse) 1 0)))
632 (collect ((refs) (targets))
633 (dolist (op (vop-parse-operands parse))
634 (when (operand-parse-target op)
635 (unless (member (operand-parse-kind op) '(:argument :temporary))
636 (error "cannot target a ~S operand: ~S" (operand-parse-kind op)
637 (operand-parse-name op)))
638 (let ((target (find-operand (operand-parse-target op) parse
639 '(:temporary :result))))
640 ;; KLUDGE: These formulas must be consistent with those in
641 ;; %EMIT-GENERIC-VOP, and this is currently maintained by
642 ;; hand. -- WHN 2002-01-30, paraphrasing APD
643 (targets (+ (* index max-vop-tn-refs)
644 (ecase (operand-parse-kind target)
646 (+ (position-or-lose target
647 (vop-parse-results parse))
650 (+ (* (position-or-lose target
651 (vop-parse-temps parse))
656 (let ((born (operand-parse-born op))
657 (dies (operand-parse-dies op)))
658 (ecase (operand-parse-kind op)
660 (refs (cons (cons dies nil) index)))
662 (refs (cons (cons dies nil) index)))
664 (refs (cons (cons born t) index)))
666 (refs (cons (cons born t) index)))
668 (refs (cons (cons dies nil) index))
670 (refs (cons (cons born t) index))))
672 (let* ((sorted (stable-sort (refs)
674 (let ((x-time (car x))
676 (if (time-spec-order x-time y-time)
677 (if (time-spec-order y-time x-time)
678 (and (not (cdr x)) (cdr y))
682 ;; :REF-ORDERING element type
684 ;; KLUDGE: was (MOD #.MAX-VOP-TN-REFS), which is still right
685 (oe-type '(unsigned-byte 8))
686 ;; :TARGETS element-type
688 ;; KLUDGE: was (MOD #.(* MAX-VOP-TN-REFS 2)), which does
689 ;; not correspond to the definition in
690 ;; src/compiler/vop.lisp.
691 (te-type '(unsigned-byte 16))
692 (ordering (make-specializable-array
694 :element-type oe-type)))
697 (setf (aref ordering index) (cdr ref))
699 `(:num-args ,num-args
700 :num-results ,num-results
701 ;; KLUDGE: see the comment regarding MAKE-ARRAY in
702 ;; COMPUTE-TEMPORARIES-DESCRIPTION. -- CSR, 2009-10-30
703 :ref-ordering (make-array ,(length ordering)
704 :initial-contents ',ordering
705 :element-type '(specializable ,oe-type))
707 `(:targets (make-array ,(length (targets))
708 :initial-contents ',(targets)
709 :element-type '(specializable ,te-type)))))))))
711 (defun make-emit-function-and-friends (parse)
712 `(:emit-function #'emit-generic-vop
713 :temps ,(compute-temporaries-description parse)
714 ,@(compute-ref-ordering parse)))
716 ;;;; generator functions
718 ;;; Return an alist that translates from lists of SCs we can load OP
719 ;;; from to the move function used for loading those SCs. We quietly
720 ;;; ignore restrictions to :non-packed (constant) and :unbounded SCs,
721 ;;; since we don't load into those SCs.
722 (defun find-move-funs (op load-p)
724 (dolist (sc-name (operand-parse-scs op))
725 (let* ((sc (meta-sc-or-lose sc-name))
727 (load-scs (append (when load-p
728 (sc-constant-scs sc))
729 (sc-alternate-scs sc))))
732 (dolist (alt load-scs)
733 (unless (member (sc-name alt) (operand-parse-scs op) :test #'eq)
734 (let* ((altn (sc-number alt))
736 (svref (sc-move-funs sc) altn)
737 (svref (sc-move-funs alt) scn)))
738 (found (or (assoc alt (funs) :test #'member)
739 (rassoc name (funs)))))
741 (error "no move function defined to ~:[save~;load~] SC ~S ~
742 ~:[to~;from~] from SC ~S"
743 load-p sc-name load-p (sc-name alt)))
746 (unless (eq (cdr found) name)
747 (error "can't tell whether to ~:[save~;load~]~@
748 with ~S or ~S when operand is in SC ~S"
749 load-p name (cdr found) (sc-name alt)))
750 (pushnew alt (car found)))
752 (funs (cons (list alt) name))))))))
753 ((member (sb-kind (sc-sb sc)) '(:non-packed :unbounded)))
755 (error "SC ~S has no alternate~:[~; or constant~] SCs, yet it is~@
756 mentioned in the restriction for operand ~S"
757 sc-name load-p (operand-parse-name op))))))
760 ;;; Return a form to load/save the specified operand when it has a
761 ;;; load TN. For any given SC that we can load from, there must be a
762 ;;; unique load function. If all SCs we can load from have the same
763 ;;; move function, then we just call that when there is a load TN. If
764 ;;; there are multiple possible move functions, then we dispatch off
765 ;;; of the operand TN's type to see which move function to use.
766 (defun call-move-fun (parse op load-p)
767 (let ((funs (find-move-funs op load-p))
768 (load-tn (operand-parse-load-tn op)))
770 (let* ((tn `(tn-ref-tn ,(operand-parse-temp op)))
771 (n-vop (or (vop-parse-vop-var parse)
772 (setf (vop-parse-vop-var parse) '.vop.)))
773 (form (if (rest funs)
775 ,@(mapcar (lambda (x)
776 `(,(mapcar #'sc-name (car x))
778 `(,(cdr x) ,n-vop ,tn
780 `(,(cdr x) ,n-vop ,load-tn
784 `(,(cdr (first funs)) ,n-vop ,tn ,load-tn)
785 `(,(cdr (first funs)) ,n-vop ,load-tn ,tn)))))
786 (if (eq (operand-parse-load op) t)
787 `(when ,load-tn ,form)
788 `(when (eq ,load-tn ,(operand-parse-name op))
791 (error "load TN allocated, but no move function?~@
792 VM definition is inconsistent, recompile and try again.")))))
794 ;;; Return the TN that we should bind to the operand's var in the
795 ;;; generator body. In general, this involves evaluating the :LOAD-IF
797 (defun decide-to-load (parse op)
798 (let ((load (operand-parse-load op))
799 (load-tn (operand-parse-load-tn op))
800 (temp (operand-parse-temp op)))
802 `(or ,load-tn (tn-ref-tn ,temp))
805 (dolist (x (vop-parse-operands parse))
806 (when (member (operand-parse-kind x) '(:argument :result))
807 (let ((name (operand-parse-name x)))
808 (binds `(,name (tn-ref-tn ,(operand-parse-temp x))))
812 (declare (ignorable ,@(ignores)))
815 (tn-ref-tn ,temp))))))
817 ;;; Make a lambda that parses the VOP TN-REFS, does automatic operand
818 ;;; loading, and runs the appropriate code generator.
819 (defun make-generator-function (parse)
820 (declare (type vop-parse parse))
821 (let ((n-vop (vop-parse-vop-var parse))
822 (operands (vop-parse-operands parse))
823 (n-info (gensym)) (n-variant (gensym)))
827 (dolist (op operands)
828 (ecase (operand-parse-kind op)
830 (let ((temp (operand-parse-temp op))
831 (name (operand-parse-name op)))
832 (cond ((and (operand-parse-load op) (operand-parse-scs op))
833 (binds `(,(operand-parse-load-tn op)
834 (tn-ref-load-tn ,temp)))
835 (binds `(,name ,(decide-to-load parse op)))
836 (if (eq (operand-parse-kind op) :argument)
837 (loads (call-move-fun parse op t))
838 (saves (call-move-fun parse op nil))))
840 (binds `(,name (tn-ref-tn ,temp)))))))
842 (binds `(,(operand-parse-name op)
843 (tn-ref-tn ,(operand-parse-temp op)))))
844 ((:more-argument :more-result))))
847 (let* (,@(access-operands (vop-parse-args parse)
848 (vop-parse-more-args parse)
850 ,@(access-operands (vop-parse-results parse)
851 (vop-parse-more-results parse)
852 `(vop-results ,n-vop))
853 ,@(access-operands (vop-parse-temps parse) nil
855 ,@(when (vop-parse-info-args parse)
856 `((,n-info (vop-codegen-info ,n-vop))
857 ,@(mapcar (lambda (x) `(,x (pop ,n-info)))
858 (vop-parse-info-args parse))))
859 ,@(when (vop-parse-variant-vars parse)
860 `((,n-variant (vop-info-variant (vop-info ,n-vop)))
861 ,@(mapcar (lambda (x) `(,x (pop ,n-variant)))
862 (vop-parse-variant-vars parse))))
863 ,@(when (vop-parse-node-var parse)
864 `((,(vop-parse-node-var parse) (vop-node ,n-vop))))
866 (declare (ignore ,@(vop-parse-ignores parse)))
868 (sb!assem:assemble (*code-segment* ,n-vop)
869 ,@(vop-parse-body parse))
872 (defvar *parse-vop-operand-count*)
873 (defun make-operand-parse-temp ()
874 (without-package-locks
875 (intern (format nil "OPERAND-PARSE-TEMP-~D" *parse-vop-operand-count*)
876 (symbol-package '*parse-vop-operand-count*))))
877 (defun make-operand-parse-load-tn ()
878 (without-package-locks
879 (intern (format nil "OPERAND-PARSE-LOAD-TN-~D" *parse-vop-operand-count*)
880 (symbol-package '*parse-vop-operand-count*))))
882 ;;; Given a list of operand specifications as given to DEFINE-VOP,
883 ;;; return a list of OPERAND-PARSE structures describing the fixed
884 ;;; operands, and a single OPERAND-PARSE describing any more operand.
885 ;;; If we are inheriting a VOP, we default attributes to the inherited
886 ;;; operand of the same name.
887 (defun !parse-vop-operands (parse specs kind)
888 (declare (list specs)
889 (type (member :argument :result) kind))
892 (collect ((operands))
894 (unless (and (consp spec) (symbolp (first spec)) (oddp (length spec)))
895 (error "malformed operand specifier: ~S" spec))
897 (error "The MORE operand isn't the last operand: ~S" specs))
898 (incf *parse-vop-operand-count*)
899 (let* ((name (first spec))
900 (old (if (vop-parse-inherits parse)
903 (vop-parse-inherits parse))
911 :target (operand-parse-target old)
912 :born (operand-parse-born old)
913 :dies (operand-parse-dies old)
914 :scs (operand-parse-scs old)
915 :load-tn (operand-parse-load-tn old)
916 :load (operand-parse-load old))
922 :born (parse-time-spec :load)
923 :dies (parse-time-spec `(:argument ,(incf num)))))
928 :born (parse-time-spec `(:result ,(incf num)))
929 :dies (parse-time-spec :save)))))))
930 (do ((key (rest spec) (cddr key)))
932 (let ((value (second key)))
935 (aver (typep value 'list))
936 (setf (operand-parse-scs res) (remove-duplicates value)))
938 (aver (typep value 'symbol))
939 (setf (operand-parse-load-tn res) value))
941 (setf (operand-parse-load res) value))
943 (aver (typep value 'boolean))
944 (setf (operand-parse-kind res)
945 (if (eq kind :argument) :more-argument :more-result))
946 (setf (operand-parse-load res) nil)
949 (aver (typep value 'symbol))
950 (setf (operand-parse-target res) value))
952 (unless (eq kind :result)
953 (error "can only specify :FROM in a result: ~S" spec))
954 (setf (operand-parse-born res) (parse-time-spec value)))
956 (unless (eq kind :argument)
957 (error "can only specify :TO in an argument: ~S" spec))
958 (setf (operand-parse-dies res) (parse-time-spec value)))
960 (error "unknown keyword in operand specifier: ~S" spec)))))
964 ((operand-parse-target more)
965 (error "cannot specify :TARGET in a :MORE operand"))
966 ((operand-parse-load more)
967 (error "cannot specify :LOAD-IF in a :MORE operand")))))
968 (values (the list (operands)) more))))
970 ;;; Parse a temporary specification, putting the OPERAND-PARSE
971 ;;; structures in the PARSE structure.
972 (defun parse-temporary (spec parse)
974 (type vop-parse parse))
975 (let ((len (length spec)))
977 (error "malformed temporary spec: ~S" spec))
978 (unless (listp (second spec))
979 (error "malformed options list: ~S" (second spec)))
980 (unless (evenp (length (second spec)))
981 (error "odd number of arguments in keyword options: ~S" spec))
982 (unless (consp (cddr spec))
983 (warn "temporary spec allocates no temps:~% ~S" spec))
984 (dolist (name (cddr spec))
985 (unless (symbolp name)
986 (error "bad temporary name: ~S" name))
987 (incf *parse-vop-operand-count*)
988 (let ((res (make-operand-parse :name name
990 :born (parse-time-spec :load)
991 :dies (parse-time-spec :save))))
992 (do ((opt (second spec) (cddr opt)))
996 (setf (operand-parse-target res)
997 (vop-spec-arg opt 'symbol 1 nil)))
999 (setf (operand-parse-sc res)
1000 (vop-spec-arg opt 'symbol 1 nil)))
1002 (let ((offset (eval (second opt))))
1003 (aver (typep offset 'unsigned-byte))
1004 (setf (operand-parse-offset res) offset)))
1006 (setf (operand-parse-born res) (parse-time-spec (second opt))))
1008 (setf (operand-parse-dies res) (parse-time-spec (second opt))))
1009 ;; backward compatibility...
1011 (let ((scs (vop-spec-arg opt 'list 1 nil)))
1012 (unless (= (length scs) 1)
1013 (error "must specify exactly one SC for a temporary"))
1014 (setf (operand-parse-sc res) (first scs))))
1017 (error "unknown temporary option: ~S" opt))))
1019 (unless (and (time-spec-order (operand-parse-dies res)
1020 (operand-parse-born res))
1021 (not (time-spec-order (operand-parse-born res)
1022 (operand-parse-dies res))))
1023 (error "Temporary lifetime doesn't begin before it ends: ~S" spec))
1025 (unless (operand-parse-sc res)
1026 (error "must specify :SC for all temporaries: ~S" spec))
1028 (setf (vop-parse-temps parse)
1030 (remove name (vop-parse-temps parse)
1031 :key #'operand-parse-name))))))
1034 (defun compute-parse-vop-operand-count (parse)
1035 (declare (type vop-parse parse))
1036 (labels ((compute-count-aux (parse)
1037 (declare (type vop-parse parse))
1038 (if (null (vop-parse-inherits parse))
1039 (length (vop-parse-operands parse))
1040 (+ (length (vop-parse-operands parse))
1042 (vop-parse-or-lose (vop-parse-inherits parse)))))))
1043 (if (null (vop-parse-inherits parse))
1045 (compute-count-aux (vop-parse-or-lose (vop-parse-inherits parse))))))
1047 ;;; the top level parse function: clobber PARSE to represent the
1048 ;;; specified options.
1049 (defun parse-define-vop (parse specs)
1050 (declare (type vop-parse parse) (list specs))
1051 (let ((*parse-vop-operand-count* (compute-parse-vop-operand-count parse)))
1052 (dolist (spec specs)
1053 (unless (consp spec)
1054 (error "malformed option specification: ~S" spec))
1057 (multiple-value-bind (fixed more)
1058 (!parse-vop-operands parse (rest spec) :argument)
1059 (setf (vop-parse-args parse) fixed)
1060 (setf (vop-parse-more-args parse) more)))
1062 (multiple-value-bind (fixed more)
1063 (!parse-vop-operands parse (rest spec) :result)
1064 (setf (vop-parse-results parse) fixed)
1065 (setf (vop-parse-more-results parse) more))
1066 (setf (vop-parse-conditional-p parse) nil))
1068 (setf (vop-parse-result-types parse) ())
1069 (setf (vop-parse-results parse) ())
1070 (setf (vop-parse-more-results parse) nil)
1071 (setf (vop-parse-conditional-p parse) (or (rest spec) t)))
1073 (parse-temporary spec parse))
1075 (setf (vop-parse-cost parse)
1076 (vop-spec-arg spec 'unsigned-byte 1 nil))
1077 (setf (vop-parse-body parse) (cddr spec)))
1079 (setf (vop-parse-effects parse) (rest spec)))
1081 (setf (vop-parse-affected parse) (rest spec)))
1083 (setf (vop-parse-info-args parse) (rest spec)))
1085 (setf (vop-parse-ignores parse) (rest spec)))
1087 (setf (vop-parse-variant parse) (rest spec)))
1089 (let ((vars (rest spec)))
1090 (setf (vop-parse-variant-vars parse) vars)
1091 (setf (vop-parse-variant parse)
1092 (make-list (length vars) :initial-element nil))))
1094 (setf (vop-parse-cost parse) (vop-spec-arg spec 'unsigned-byte)))
1096 (setf (vop-parse-vop-var parse) (vop-spec-arg spec 'symbol)))
1098 (setf (vop-parse-move-args parse)
1099 (vop-spec-arg spec '(member nil :local-call :full-call
1102 (setf (vop-parse-node-var parse) (vop-spec-arg spec 'symbol)))
1104 (setf (vop-parse-note parse) (vop-spec-arg spec '(or string null))))
1106 (setf (vop-parse-arg-types parse)
1107 (!parse-vop-operand-types (rest spec) t)))
1109 (setf (vop-parse-result-types parse)
1110 (!parse-vop-operand-types (rest spec) nil)))
1112 (setf (vop-parse-translate parse) (rest spec)))
1114 (setf (vop-parse-guard parse) (vop-spec-arg spec t)))
1115 ;; FIXME: :LTN-POLICY would be a better name for this. It
1116 ;; would probably be good to leave it unchanged for a while,
1117 ;; though, at least until the first port to some other
1118 ;; architecture, since the renaming would be a change to the
1119 ;; interface between
1121 (setf (vop-parse-ltn-policy parse)
1122 (vop-spec-arg spec 'ltn-policy)))
1124 (setf (vop-parse-save-p parse)
1126 '(member t nil :compute-only :force-to-stack))))
1128 (error "unknown option specifier: ~S" (first spec)))))
1131 ;;;; making costs and restrictions
1133 ;;; Given an operand, returns two values:
1134 ;;; 1. A SC-vector of the cost for the operand being in that SC,
1135 ;;; including both the costs for move functions and coercion VOPs.
1136 ;;; 2. A SC-vector holding the SC that we load into, for any SC
1137 ;;; that we can directly load from.
1139 ;;; In both vectors, unused entries are NIL. LOAD-P specifies the
1140 ;;; direction: if true, we are loading, if false we are saving.
1141 (defun compute-loading-costs (op load-p)
1142 (declare (type operand-parse op))
1143 (let ((scs (operand-parse-scs op))
1144 (costs (make-array sc-number-limit :initial-element nil))
1145 (load-scs (make-array sc-number-limit :initial-element nil)))
1146 (dolist (sc-name scs)
1147 (let* ((load-sc (meta-sc-or-lose sc-name))
1148 (load-scn (sc-number load-sc)))
1149 (setf (svref costs load-scn) 0)
1150 (setf (svref load-scs load-scn) t)
1151 (dolist (op-sc (append (when load-p
1152 (sc-constant-scs load-sc))
1153 (sc-alternate-scs load-sc)))
1154 (let* ((op-scn (sc-number op-sc))
1156 (aref (sc-load-costs load-sc) op-scn)
1157 (aref (sc-load-costs op-sc) load-scn))))
1159 (error "no move function defined to move ~:[from~;to~] SC ~
1160 ~S~%~:[to~;from~] alternate or constant SC ~S"
1161 load-p sc-name load-p (sc-name op-sc)))
1163 (let ((op-cost (svref costs op-scn)))
1164 (when (or (not op-cost) (< load op-cost))
1165 (setf (svref costs op-scn) load)))
1167 (let ((op-load (svref load-scs op-scn)))
1168 (unless (eq op-load t)
1169 (pushnew load-scn (svref load-scs op-scn))))))
1171 (dotimes (i sc-number-limit)
1172 (unless (svref costs i)
1173 (let ((op-sc (svref *backend-meta-sc-numbers* i)))
1175 (let ((cost (if load-p
1176 (svref (sc-move-costs load-sc) i)
1177 (svref (sc-move-costs op-sc) load-scn))))
1179 (setf (svref costs i) cost)))))))))
1181 (values costs load-scs)))
1183 (defparameter *no-costs*
1184 (make-array sc-number-limit :initial-element 0))
1186 (defparameter *no-loads*
1187 (make-array sc-number-limit :initial-element t))
1189 ;;; Pick off the case of operands with no restrictions.
1190 (defun compute-loading-costs-if-any (op load-p)
1191 (declare (type operand-parse op))
1192 (if (operand-parse-scs op)
1193 (compute-loading-costs op load-p)
1194 (values *no-costs* *no-loads*)))
1196 (defun compute-costs-and-restrictions-list (ops load-p)
1197 (declare (list ops))
1201 (multiple-value-bind (costs scs) (compute-loading-costs-if-any op load-p)
1204 (values (costs) (scs))))
1206 (defun make-costs-and-restrictions (parse)
1207 (multiple-value-bind (arg-costs arg-scs)
1208 (compute-costs-and-restrictions-list (vop-parse-args parse) t)
1209 (multiple-value-bind (result-costs result-scs)
1210 (compute-costs-and-restrictions-list (vop-parse-results parse) nil)
1212 :cost ,(vop-parse-cost parse)
1214 :arg-costs ',arg-costs
1215 :arg-load-scs ',arg-scs
1216 :result-costs ',result-costs
1217 :result-load-scs ',result-scs
1220 ',(if (vop-parse-more-args parse)
1221 (compute-loading-costs-if-any (vop-parse-more-args parse) t)
1225 ',(if (vop-parse-more-results parse)
1226 (compute-loading-costs-if-any (vop-parse-more-results parse) nil)
1229 ;;;; operand checking and stuff
1231 ;;; Given a list of arg/result restrictions, check for valid syntax
1232 ;;; and convert to canonical form.
1233 (defun !parse-vop-operand-types (specs args-p)
1234 (declare (list specs))
1235 (labels ((parse-operand-type (spec)
1236 (cond ((eq spec '*) spec)
1238 (let ((alias (gethash spec
1239 *backend-primitive-type-aliases*)))
1241 (parse-operand-type alias)
1244 (error "bad thing to be a operand type: ~S" spec))
1248 (collect ((results))
1250 (dolist (item (cdr spec))
1251 (unless (symbolp item)
1252 (error "bad PRIMITIVE-TYPE name in ~S: ~S"
1256 *backend-primitive-type-aliases*)))
1258 (let ((alias (parse-operand-type alias)))
1259 (unless (eq (car alias) :or)
1260 (error "can't include primitive-type ~
1261 alias ~S in an :OR restriction: ~S"
1263 (dolist (x (cdr alias))
1266 (remove-duplicates (results)
1271 (error "can't :CONSTANT for a result"))
1272 (unless (= (length spec) 2)
1273 (error "bad :CONSTANT argument type spec: ~S" spec))
1276 (error "bad thing to be a operand type: ~S" spec)))))))
1277 (mapcar #'parse-operand-type specs)))
1279 ;;; Check the consistency of OP's SC restrictions with the specified
1280 ;;; primitive-type restriction. :CONSTANT operands have already been
1281 ;;; filtered out, so only :OR and * restrictions are left.
1283 ;;; We check that every representation allowed by the type can be
1284 ;;; directly loaded into some SC in the restriction, and that the type
1285 ;;; allows every SC in the restriction. With *, we require that T
1286 ;;; satisfy the first test, and omit the second.
1287 (defun check-operand-type-scs (parse op type load-p)
1288 (declare (type vop-parse parse) (type operand-parse op))
1289 (let ((ptypes (if (eq type '*) (list t) (rest type)))
1290 (scs (operand-parse-scs op)))
1292 (multiple-value-bind (costs load-scs) (compute-loading-costs op load-p)
1293 (declare (ignore costs))
1294 (dolist (ptype ptypes)
1295 (unless (dolist (rep (primitive-type-scs
1296 (meta-primitive-type-or-lose ptype))
1298 (when (svref load-scs rep) (return t)))
1299 (error "In the ~A ~:[result~;argument~] to VOP ~S,~@
1300 none of the SCs allowed by the operand type ~S can ~
1301 directly be loaded~@
1302 into any of the restriction's SCs:~% ~S~:[~;~@
1303 [* type operand must allow T's SCs.]~]"
1304 (operand-parse-name op) load-p (vop-parse-name parse)
1306 scs (eq type '*)))))
1309 (unless (or (eq type '*)
1310 (dolist (ptype ptypes nil)
1311 (when (meta-sc-allowed-by-primitive-type
1312 (meta-sc-or-lose sc)
1313 (meta-primitive-type-or-lose ptype))
1315 (warn "~:[Result~;Argument~] ~A to VOP ~S~@
1316 has SC restriction ~S which is ~
1317 not allowed by the operand type:~% ~S"
1318 load-p (operand-parse-name op) (vop-parse-name parse)
1323 ;;; If the operand types are specified, then check the number specified
1324 ;;; against the number of defined operands.
1325 (defun check-operand-types (parse ops more-op types load-p)
1326 (declare (type vop-parse parse) (list ops)
1327 (type (or list (member :unspecified)) types)
1328 (type (or operand-parse null) more-op))
1329 (unless (eq types :unspecified)
1330 (let ((num (+ (length ops) (if more-op 1 0))))
1331 (unless (= (count-if-not (lambda (x)
1333 (eq (car x) :constant)))
1336 (error "expected ~W ~:[result~;argument~] type~P: ~S"
1337 num load-p types num)))
1340 (let ((mtype (car (last types))))
1341 (when (and (consp mtype) (eq (first mtype) :constant))
1342 (error "can't use :CONSTANT on VOP more args")))))
1344 (when (vop-parse-translate parse)
1345 (let ((types (specify-operand-types types ops more-op)))
1347 (check-operand-type-scs parse x y load-p))
1348 (if more-op (butlast ops) ops)
1349 (remove-if (lambda (x)
1351 (eq (car x) ':constant)))
1352 (if more-op (butlast types) types)))))
1356 ;;; Compute stuff that can only be computed after we are done parsing
1357 ;;; everying. We set the VOP-PARSE-OPERANDS, and do various error checks.
1358 (defun !grovel-vop-operands (parse)
1359 (declare (type vop-parse parse))
1361 (setf (vop-parse-operands parse)
1362 (append (vop-parse-args parse)
1363 (if (vop-parse-more-args parse)
1364 (list (vop-parse-more-args parse)))
1365 (vop-parse-results parse)
1366 (if (vop-parse-more-results parse)
1367 (list (vop-parse-more-results parse)))
1368 (vop-parse-temps parse)))
1370 (check-operand-types parse
1371 (vop-parse-args parse)
1372 (vop-parse-more-args parse)
1373 (vop-parse-arg-types parse)
1376 (check-operand-types parse
1377 (vop-parse-results parse)
1378 (vop-parse-more-results parse)
1379 (vop-parse-result-types parse)
1384 ;;;; function translation stuff
1386 ;;; Return forms to establish this VOP as a IR2 translation template
1387 ;;; for the :TRANSLATE functions specified in the VOP-PARSE. We also
1388 ;;; set the PREDICATE attribute for each translated function when the
1389 ;;; VOP is conditional, causing IR1 conversion to ensure that a call
1390 ;;; to the translated is always used in a predicate position.
1391 (defun !set-up-fun-translation (parse n-template)
1392 (declare (type vop-parse parse))
1393 (mapcar (lambda (name)
1394 `(let ((info (fun-info-or-lose ',name)))
1395 (setf (fun-info-templates info)
1396 (adjoin-template ,n-template (fun-info-templates info)))
1397 ,@(when (vop-parse-conditional-p parse)
1398 '((setf (fun-info-attributes info)
1400 (ir1-attributes predicate)
1401 (fun-info-attributes info)))))))
1402 (vop-parse-translate parse)))
1404 ;;; Return a form that can be evaluated to get the TEMPLATE operand type
1405 ;;; restriction from the given specification.
1406 (defun make-operand-type (type)
1407 (cond ((eq type '*) ''*)
1409 ``(:or ,(primitive-type-or-lose ',type)))
1413 ``(:or ,,@(mapcar (lambda (type)
1414 `(primitive-type-or-lose ',type))
1417 ``(:constant ,#'(lambda (x)
1418 (sb!xc:typep x ',(second type)))
1419 ,',(second type)))))))
1421 (defun specify-operand-types (types ops more-ops)
1422 (if (eq types :unspecified)
1423 (make-list (+ (length ops) (if more-ops 1 0)) :initial-element '*)
1426 ;;; Return a list of forms to use as &KEY args to MAKE-VOP-INFO for
1427 ;;; setting up the template argument and result types. Here we make an
1428 ;;; initial dummy TEMPLATE-TYPE, since it is awkward to compute the
1429 ;;; type until the template has been made.
1430 (defun make-vop-info-types (parse)
1431 (let* ((more-args (vop-parse-more-args parse))
1432 (all-args (specify-operand-types (vop-parse-arg-types parse)
1433 (vop-parse-args parse)
1435 (args (if more-args (butlast all-args) all-args))
1436 (more-arg (when more-args (car (last all-args))))
1437 (more-results (vop-parse-more-results parse))
1438 (all-results (specify-operand-types (vop-parse-result-types parse)
1439 (vop-parse-results parse)
1441 (results (if more-results (butlast all-results) all-results))
1442 (more-result (when more-results (car (last all-results))))
1443 (conditional (vop-parse-conditional-p parse)))
1445 `(:type (specifier-type '(function () nil))
1446 :arg-types (list ,@(mapcar #'make-operand-type args))
1447 :more-args-type ,(when more-args (make-operand-type more-arg))
1448 :result-types ,(cond ((eq conditional t)
1451 `'(:conditional . ,conditional))
1453 `(list ,@(mapcar #'make-operand-type results))))
1454 :more-results-type ,(when more-results
1455 (make-operand-type more-result)))))
1457 ;;;; setting up VOP-INFO
1459 (eval-when (:compile-toplevel :load-toplevel :execute)
1460 (defparameter *slot-inherit-alist*
1461 '((:generator-function . vop-info-generator-function))))
1463 ;;; This is something to help with inheriting VOP-INFO slots. We
1464 ;;; return a keyword/value pair that can be passed to the constructor.
1465 ;;; SLOT is the keyword name of the slot, Parse is a form that
1466 ;;; evaluates to the VOP-PARSE structure for the VOP inherited. If
1467 ;;; PARSE is NIL, then we do nothing. If the TEST form evaluates to
1468 ;;; true, then we return a form that selects the named slot from the
1469 ;;; VOP-INFO structure corresponding to PARSE. Otherwise, we return
1470 ;;; the FORM so that the slot is recomputed.
1471 (defmacro inherit-vop-info (slot parse test form)
1472 `(if (and ,parse ,test)
1473 (list ,slot `(,',(or (cdr (assoc slot *slot-inherit-alist*))
1474 (error "unknown slot ~S" slot))
1475 (template-or-lose ',(vop-parse-name ,parse))))
1476 (list ,slot ,form)))
1478 ;;; Return a form that creates a VOP-INFO structure which describes VOP.
1479 (defun set-up-vop-info (iparse parse)
1480 (declare (type vop-parse parse) (type (or vop-parse null) iparse))
1481 (let ((same-operands
1483 (equal (vop-parse-operands parse)
1484 (vop-parse-operands iparse))
1485 (equal (vop-parse-info-args iparse)
1486 (vop-parse-info-args parse))))
1487 (variant (vop-parse-variant parse)))
1489 (let ((nvars (length (vop-parse-variant-vars parse))))
1490 (unless (= (length variant) nvars)
1491 (error "expected ~W variant values: ~S" nvars variant)))
1494 :name ',(vop-parse-name parse)
1495 ,@(make-vop-info-types parse)
1496 :guard ,(when (vop-parse-guard parse)
1497 `(lambda () ,(vop-parse-guard parse)))
1498 :note ',(vop-parse-note parse)
1499 :info-arg-count ,(length (vop-parse-info-args parse))
1500 :ltn-policy ',(vop-parse-ltn-policy parse)
1501 :save-p ',(vop-parse-save-p parse)
1502 :move-args ',(vop-parse-move-args parse)
1503 :effects (vop-attributes ,@(vop-parse-effects parse))
1504 :affected (vop-attributes ,@(vop-parse-affected parse))
1505 ,@(make-costs-and-restrictions parse)
1506 ,@(make-emit-function-and-friends parse)
1507 ,@(inherit-vop-info :generator-function iparse
1509 (equal (vop-parse-body parse) (vop-parse-body iparse)))
1510 (unless (eq (vop-parse-body parse) :unspecified)
1511 (make-generator-function parse)))
1512 :variant (list ,@variant))))
1514 ;;; Define the symbol NAME to be a Virtual OPeration in the compiler.
1515 ;;; If specified, INHERITS is the name of a VOP that we default
1516 ;;; unspecified information from. Each SPEC is a list beginning with a
1517 ;;; keyword indicating the interpretation of the other forms in the
1520 ;;; :ARGS {(Name {Key Value}*)}*
1521 ;;; :RESULTS {(Name {Key Value}*)}*
1522 ;;; The Args and Results are specifications of the operand TNs passed
1523 ;;; to the VOP. If there is an inherited VOP, any unspecified options
1524 ;;; are defaulted from the inherited argument (or result) of the same
1525 ;;; name. The following operand options are defined:
1528 ;;; :SCs specifies good SCs for this operand. Other SCs will
1529 ;;; be penalized according to move costs. A load TN will be
1530 ;;; allocated if necessary, guaranteeing that the operand is
1531 ;;; always one of the specified SCs.
1533 ;;; :LOAD-TN Load-Name
1534 ;;; Load-Name is bound to the load TN allocated for this
1535 ;;; operand, or to NIL if no load TN was allocated.
1537 ;;; :LOAD-IF EXPRESSION
1538 ;;; Controls whether automatic operand loading is done.
1539 ;;; EXPRESSION is evaluated with the fixed operand TNs bound.
1540 ;;; If EXPRESSION is true, then loading is done and the variable
1541 ;;; is bound to the load TN in the generator body. Otherwise,
1542 ;;; loading is not done, and the variable is bound to the actual
1546 ;;; If specified, NAME is bound to the TN-REF for the first
1547 ;;; argument or result following the fixed arguments or results.
1548 ;;; A :MORE operand must appear last, and cannot be targeted or
1552 ;;; This operand is targeted to the named operand, indicating a
1553 ;;; desire to pack in the same location. Not legal for results.
1557 ;;; Specify the beginning or end of the operand's lifetime.
1558 ;;; :FROM can only be used with results, and :TO only with
1559 ;;; arguments. The default for the N'th argument/result is
1560 ;;; (:ARGUMENT N)/(:RESULT N). These options are necessary
1561 ;;; primarily when operands are read or written out of order.
1563 ;;; :CONDITIONAL [Condition-descriptor+]
1564 ;;; This is used in place of :RESULTS with conditional branch VOPs.
1565 ;;; There are no result values: the result is a transfer of control.
1566 ;;; The target label is passed as the first :INFO arg. The second
1567 ;;; :INFO arg is true if the sense of the test should be negated.
1568 ;;; A side effect is to set the PREDICATE attribute for functions
1569 ;;; in the :TRANSLATE option.
1571 ;;; If some condition descriptors are provided, this is a flag-setting
1572 ;;; VOP. Descriptors are interpreted in an architecture-dependent
1573 ;;; manner. See the BRANCH-IF VOP in $ARCH/pred.lisp.
1575 ;;; :TEMPORARY ({Key Value}*) Name*
1576 ;;; Allocate a temporary TN for each Name, binding that variable to
1577 ;;; the TN within the body of the generators. In addition to :TARGET
1578 ;;; (which is is the same as for operands), the following options are
1582 ;;; :OFFSET SB-Offset
1583 ;;; Force the temporary to be allocated in the specified SC
1584 ;;; with the specified offset. Offset is evaluated at
1585 ;;; macroexpand time. If Offset is omitted, the register
1586 ;;; allocator chooses a free location in SC. If both SC and
1587 ;;; Offset are omitted, then the temporary is packed according
1588 ;;; to its primitive type.
1592 ;;; Similar to the argument/result option, this specifies the
1593 ;;; start and end of the temporaries' lives. The defaults are
1594 ;;; :LOAD and :SAVE, i.e. the duration of the VOP. The other
1595 ;;; intervening phases are :ARGUMENT, :EVAL and :RESULT.
1596 ;;; Non-zero sub-phases can be specified by a list, e.g. by
1597 ;;; default the second argument's life ends at (:ARGUMENT 1).
1599 ;;; :GENERATOR Cost Form*
1600 ;;; Specifies the translation into assembly code. Cost is the
1601 ;;; estimated cost of the code emitted by this generator. The body
1602 ;;; is arbitrary Lisp code that emits the assembly language
1603 ;;; translation of the VOP. An ASSEMBLE form is wrapped around
1604 ;;; the body, so code may be emitted by using the local INST macro.
1605 ;;; During the evaluation of the body, the names of the operands
1606 ;;; and temporaries are bound to the actual TNs.
1608 ;;; :EFFECTS Effect*
1609 ;;; :AFFECTED Effect*
1610 ;;; Specifies the side effects that this VOP has and the side
1611 ;;; effects that effect its execution. If unspecified, these
1612 ;;; default to the worst case.
1615 ;;; Define some magic arguments that are passed directly to the code
1616 ;;; generator. The corresponding trailing arguments to VOP or
1617 ;;; %PRIMITIVE are stored in the VOP structure. Within the body
1618 ;;; of the generators, the named variables are bound to these
1619 ;;; values. Except in the case of :CONDITIONAL VOPs, :INFO arguments
1620 ;;; cannot be specified for VOPS that are the direct translation
1621 ;;; for a function (specified by :TRANSLATE).
1624 ;;; Causes the named variables to be declared IGNORE in the
1628 ;;; :VARIANT-VARS Name*
1629 ;;; These options provide a way to parameterize families of VOPs
1630 ;;; that differ only trivially. :VARIANT makes the specified
1631 ;;; evaluated Things be the "variant" associated with this VOP.
1632 ;;; :VARIANT-VARS causes the named variables to be bound to the
1633 ;;; corresponding Things within the body of the generator.
1635 ;;; :VARIANT-COST Cost
1636 ;;; Specifies the cost of this VOP, overriding the cost of any
1637 ;;; inherited generator.
1639 ;;; :NOTE {String | NIL}
1640 ;;; A short noun-like phrase describing what this VOP "does", i.e.
1641 ;;; the implementation strategy. If supplied, efficiency notes will
1642 ;;; be generated when type uncertainty prevents :TRANSLATE from
1643 ;;; working. NIL inhibits any efficiency note.
1645 ;;; :ARG-TYPES {* | PType | (:OR PType*) | (:CONSTANT Type)}*
1646 ;;; :RESULT-TYPES {* | PType | (:OR PType*)}*
1647 ;;; Specify the template type restrictions used for automatic
1648 ;;; translation. If there is a :MORE operand, the last type is the
1649 ;;; more type. :CONSTANT specifies that the argument must be a
1650 ;;; compile-time constant of the specified Lisp type. The constant
1651 ;;; values of :CONSTANT arguments are passed as additional :INFO
1652 ;;; arguments rather than as :ARGS.
1654 ;;; :TRANSLATE Name*
1655 ;;; This option causes the VOP template to be entered as an IR2
1656 ;;; translation for the named functions.
1658 ;;; :POLICY {:SMALL | :FAST | :SAFE | :FAST-SAFE}
1659 ;;; Specifies the policy under which this VOP is the best translation.
1662 ;;; Specifies a Form that is evaluated in the global environment.
1663 ;;; If form returns NIL, then emission of this VOP is prohibited
1664 ;;; even when all other restrictions are met.
1668 ;;; In the generator, bind the specified variable to the VOP or
1669 ;;; the Node that generated this VOP.
1671 ;;; :SAVE-P {NIL | T | :COMPUTE-ONLY | :FORCE-TO-STACK}
1672 ;;; Indicates how a VOP wants live registers saved.
1674 ;;; :MOVE-ARGS {NIL | :FULL-CALL | :LOCAL-CALL | :KNOWN-RETURN}
1675 ;;; Indicates if and how the more args should be moved into a
1676 ;;; different frame.
1677 (def!macro define-vop ((name &optional inherits) &body specs)
1678 (declare (type symbol name))
1679 ;; Parse the syntax into a VOP-PARSE structure, and then expand into
1680 ;; code that creates the appropriate VOP-INFO structure at load time.
1681 ;; We implement inheritance by copying the VOP-PARSE structure for
1682 ;; the inherited structure.
1683 (let* ((inherited-parse (when inherits
1684 (vop-parse-or-lose inherits)))
1686 (copy-vop-parse inherited-parse)
1689 (setf (vop-parse-name parse) name)
1690 (setf (vop-parse-inherits parse) inherits)
1692 (parse-define-vop parse specs)
1693 (!grovel-vop-operands parse)
1696 (eval-when (:compile-toplevel :load-toplevel :execute)
1697 (setf (gethash ',name *backend-parsed-vops*)
1700 (let ((,n-res ,(set-up-vop-info inherited-parse parse)))
1701 (setf (gethash ',name *backend-template-names*) ,n-res)
1702 (setf (template-type ,n-res)
1703 (specifier-type (template-type-specifier ,n-res)))
1704 ,@(!set-up-fun-translation parse n-res))
1707 ;;;; emission macros
1709 ;;; Return code to make a list of VOP arguments or results, linked by
1710 ;;; TN-REF-ACROSS. The first value is code, the second value is LET*
1711 ;;; forms, and the third value is a variable that evaluates to the
1712 ;;; head of the list, or NIL if there are no operands. Fixed is a list
1713 ;;; of forms that evaluate to TNs for the fixed operands. TN-REFS will
1714 ;;; be made for these operands according using the specified value of
1715 ;;; WRITE-P. More is an expression that evaluates to a list of TN-REFS
1716 ;;; that will be made the tail of the list. If it is constant NIL,
1717 ;;; then we don't bother to set the tail.
1718 (defun make-operand-list (fixed more write-p)
1724 (let ((n-ref (gensym)))
1725 (binds `(,n-ref (reference-tn ,op ,write-p)))
1727 (forms `(setf (tn-ref-across ,n-prev) ,n-ref))
1728 (setq n-head n-ref))
1729 (setq n-prev n-ref)))
1732 (let ((n-more (gensym)))
1733 (binds `(,n-more ,more))
1735 (forms `(setf (tn-ref-across ,n-prev) ,n-more))
1736 (setq n-head n-more))))
1738 (values (forms) (binds) n-head))))
1740 ;;; Emit-Template Node Block Template Args Results [Info]
1742 ;;; Call the emit function for TEMPLATE, linking the result in at the
1744 (defmacro emit-template (node block template args results &optional info)
1745 (with-unique-names (first last)
1746 (once-only ((n-node node)
1748 (n-template template))
1749 `(multiple-value-bind (,first ,last)
1750 (funcall (template-emit-function ,n-template)
1751 ,n-node ,n-block ,n-template ,args ,results
1752 ,@(when info `(,info)))
1753 (insert-vop-sequence ,first ,last ,n-block nil)))))
1755 ;;; VOP Name Node Block Arg* Info* Result*
1757 ;;; Emit the VOP (or other template) NAME at the end of the IR2-BLOCK
1758 ;;; BLOCK, using NODE for the source context. The interpretation of
1759 ;;; the remaining arguments depends on the number of operands of
1760 ;;; various kinds that are declared in the template definition. VOP
1761 ;;; cannot be used for templates that have more-args or more-results,
1762 ;;; since the number of arguments and results is indeterminate for
1763 ;;; these templates. Use VOP* instead.
1765 ;;; ARGS and RESULTS are the TNs that are to be referenced by the
1766 ;;; template as arguments and results. If the template has
1767 ;;; codegen-info arguments, then the appropriate number of INFO forms
1768 ;;; following the arguments are used for codegen info.
1769 (defmacro vop (name node block &rest operands)
1770 (let* ((parse (vop-parse-or-lose name))
1771 (arg-count (length (vop-parse-args parse)))
1772 (result-count (length (vop-parse-results parse)))
1773 (info-count (length (vop-parse-info-args parse)))
1774 (noperands (+ arg-count result-count info-count))
1777 (n-template (gensym)))
1779 (when (or (vop-parse-more-args parse) (vop-parse-more-results parse))
1780 (error "cannot use VOP with variable operand count templates"))
1781 (unless (= noperands (length operands))
1782 (error "called with ~W operands, but was expecting ~W"
1783 (length operands) noperands))
1785 (multiple-value-bind (acode abinds n-args)
1786 (make-operand-list (subseq operands 0 arg-count) nil nil)
1787 (multiple-value-bind (rcode rbinds n-results)
1788 (make-operand-list (subseq operands (+ arg-count info-count)) nil t)
1792 (dolist (info (subseq operands arg-count (+ arg-count info-count)))
1793 (let ((temp (gensym)))
1794 (ibinds `(,temp ,info))
1797 `(let* ((,n-node ,node)
1799 (,n-template (template-or-lose ',name))
1805 (emit-template ,n-node ,n-block ,n-template ,n-args
1808 `((list ,@(ivars)))))
1811 ;;; VOP* Name Node Block (Arg* More-Args) (Result* More-Results) Info*
1813 ;;; This is like VOP, but allows for emission of templates with
1814 ;;; arbitrary numbers of arguments, and for emission of templates
1815 ;;; using already-created TN-REF lists.
1817 ;;; The ARGS and RESULTS are TNs to be referenced as the first
1818 ;;; arguments and results to the template. More-Args and More-Results
1819 ;;; are heads of TN-REF lists that are added onto the end of the
1820 ;;; TN-REFS for the explicitly supplied operand TNs. The TN-REFS for
1821 ;;; the more operands must have the TN and WRITE-P slots correctly
1824 ;;; As with VOP, the INFO forms are evaluated and passed as codegen
1826 (defmacro vop* (name node block args results &rest info)
1827 (declare (type cons args results))
1828 (let* ((parse (vop-parse-or-lose name))
1829 (arg-count (length (vop-parse-args parse)))
1830 (result-count (length (vop-parse-results parse)))
1831 (info-count (length (vop-parse-info-args parse)))
1832 (fixed-args (butlast args))
1833 (fixed-results (butlast results))
1836 (n-template (gensym)))
1838 (unless (or (vop-parse-more-args parse)
1839 (<= (length fixed-args) arg-count))
1840 (error "too many fixed arguments"))
1841 (unless (or (vop-parse-more-results parse)
1842 (<= (length fixed-results) result-count))
1843 (error "too many fixed results"))
1844 (unless (= (length info) info-count)
1845 (error "expected ~W info args" info-count))
1847 (multiple-value-bind (acode abinds n-args)
1848 (make-operand-list fixed-args (car (last args)) nil)
1849 (multiple-value-bind (rcode rbinds n-results)
1850 (make-operand-list fixed-results (car (last results)) t)
1852 `(let* ((,n-node ,node)
1854 (,n-template (template-or-lose ',name))
1859 (emit-template ,n-node ,n-block ,n-template ,n-args ,n-results
1864 ;;;; miscellaneous macros
1866 ;;; SC-Case TN {({(SC-Name*) | SC-Name | T} Form*)}*
1868 ;;; Case off of TN's SC. The first clause containing TN's SC is
1869 ;;; evaluated, returning the values of the last form. A clause
1870 ;;; beginning with T specifies a default. If it appears, it must be
1871 ;;; last. If no default is specified, and no clause matches, then an
1872 ;;; error is signalled.
1873 (def!macro sc-case (tn &body forms)
1874 (let ((n-sc (gensym))
1876 (collect ((clauses))
1877 (do ((cases forms (rest cases)))
1879 (clauses `(t (error "unknown SC to SC-CASE for ~S:~% ~S" ,n-tn
1880 (sc-name (tn-sc ,n-tn))))))
1881 (let ((case (first cases)))
1883 (error "illegal SC-CASE clause: ~S" case))
1884 (let ((head (first case)))
1887 (error "T case is not last in SC-CASE."))
1888 (clauses `(t nil ,@(rest case)))
1890 (clauses `((or ,@(mapcar (lambda (x)
1891 `(eql ,(meta-sc-number-or-lose x)
1893 (if (atom head) (list head) head)))
1894 nil ,@(rest case))))))
1897 (,n-sc (sc-number (tn-sc ,n-tn))))
1898 (cond ,@(clauses))))))
1900 ;;; Return true if TNs SC is any of the named SCs, false otherwise.
1901 (defmacro sc-is (tn &rest scs)
1902 (once-only ((n-sc `(sc-number (tn-sc ,tn))))
1903 `(or ,@(mapcar (lambda (x)
1904 `(eql ,n-sc ,(meta-sc-number-or-lose x)))
1907 ;;; Iterate over the IR2 blocks in component, in emission order.
1908 (defmacro do-ir2-blocks ((block-var component &optional result)
1910 `(do ((,block-var (block-info (component-head ,component))
1911 (ir2-block-next ,block-var)))
1912 ((null ,block-var) ,result)
1915 ;;; Iterate over all the TNs live at some point, with the live set
1916 ;;; represented by a local conflicts bit-vector and the IR2-BLOCK
1917 ;;; containing the location.
1918 (defmacro do-live-tns ((tn-var live block &optional result) &body body)
1919 (with-unique-names (conf bod i ltns)
1920 (once-only ((n-live live)
1923 (flet ((,bod (,tn-var) ,@body))
1924 ;; Do component-live TNs.
1925 (dolist (,tn-var (ir2-component-component-tns
1928 (ir2-block-block ,n-block)))))
1931 (let ((,ltns (ir2-block-local-tns ,n-block)))
1932 ;; Do TNs always-live in this block and live :MORE TNs.
1933 (do ((,conf (ir2-block-global-tns ,n-block)
1934 (global-conflicts-next-blockwise ,conf)))
1936 (when (or (eq (global-conflicts-kind ,conf) :live)
1937 (let ((,i (global-conflicts-number ,conf)))
1938 (and (eq (svref ,ltns ,i) :more)
1939 (not (zerop (sbit ,n-live ,i))))))
1940 (,bod (global-conflicts-tn ,conf))))
1941 ;; Do TNs locally live in the designated live set.
1942 (dotimes (,i (ir2-block-local-tn-count ,n-block) ,result)
1943 (unless (zerop (sbit ,n-live ,i))
1944 (let ((,tn-var (svref ,ltns ,i)))
1945 (when (and ,tn-var (not (eq ,tn-var :more)))
1946 (,bod ,tn-var)))))))))))
1948 ;;; Iterate over all the IR2 blocks in PHYSENV, in emit order.
1949 (defmacro do-physenv-ir2-blocks ((block-var physenv &optional result)
1951 (once-only ((n-physenv physenv))
1952 (once-only ((n-first `(lambda-block (physenv-lambda ,n-physenv))))
1953 (once-only ((n-tail `(block-info
1955 (block-component ,n-first)))))
1956 `(do ((,block-var (block-info ,n-first)
1957 (ir2-block-next ,block-var)))
1958 ((or (eq ,block-var ,n-tail)
1959 (not (eq (ir2-block-physenv ,block-var) ,n-physenv)))