8b88ecd5954912219cd93ac9f91fdbeea032c4f2
[sbcl.git] / src / compiler / meta-vmdef.lisp
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.
6 ;;;;
7 ;;;; FIXME: The "trashing the running [CMU CL] compiler" motivation no
8 ;;;; longer makes sense in SBCL, since we can cross-compile cleanly.
9
10 ;;;; This software is part of the SBCL system. See the README file for
11 ;;;; more information.
12 ;;;;
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.
18
19 (in-package "SB!C")
20 \f
21 ;;;; storage class and storage base definition
22
23 ;;; Enter the basic structure at meta-compile time, and then fill in the
24 ;;; missing slots at load time.
25 (defmacro define-storage-base (name kind &key size)
26   #!+sb-doc
27   "Define-Storage-Base Name Kind {Key Value}*
28   Define a storage base having the specified Name. Kind may be :Finite,
29   :Unbounded or :Non-Packed. The following keywords are legal:
30
31   :Size <Size>
32       Specify the number of locations in a :Finite SB or the initial size of a
33       :Unbounded SB."
34
35   ;; FIXME: Replace with DECLARE.
36   (check-type name symbol)
37   (check-type kind (member :finite :unbounded :non-packed))
38
39   ;; SIZE is either mandatory or forbidden.
40   (ecase kind
41     (:non-packed
42      (when size
43        (error "A size specification is meaningless in a ~S SB." kind)))
44     ((:finite :unbounded)
45      (unless size (error "Size is not specified in a ~S SB." kind))
46      (check-type size unsigned-byte)))
47
48   (let ((res (if (eq kind :non-packed)
49                  (make-sb :name name :kind kind)
50                  (make-finite-sb :name name :kind kind :size size))))
51     `(progn
52        (eval-when (:compile-toplevel :load-toplevel :execute)
53          (/show0 "about to SETF GETHASH META-SB-NAMES in DEFINE-STORAGE-BASE")
54          (setf (gethash ',name *backend-meta-sb-names*)
55                ',res))
56        (/show0 "about to SETF GETHASH SB-NAMES in DEFINE-STORAGE-BASE")
57        ,(if (eq kind :non-packed)
58             `(setf (gethash ',name *backend-sb-names*)
59                    (copy-sb ',res))
60             `(let ((res (copy-finite-sb ',res)))
61                (/show0 "not :NON-PACKED, i.e. hairy case")
62                (setf (finite-sb-always-live res)
63                      (make-array ',size
64                                  :initial-element
65                                  #-(or sb-xc sb-xc-host) #*
66                                  ;; The cross-compiler isn't very good
67                                  ;; at dumping specialized arrays; we
68                                  ;; work around that by postponing
69                                  ;; generation of the specialized
70                                  ;; array 'til runtime.
71                                  #+(or sb-xc sb-xc-host)
72                                  (make-array 0 :element-type 'bit)))
73                (/show0 "doing second SETF")
74                (setf (finite-sb-conflicts res)
75                      (make-array ',size :initial-element '#()))
76                (/show0 "doing third SETF")
77                (setf (finite-sb-live-tns res)
78                      (make-array ',size :initial-element nil))
79                (/show0 "doing fourth and final SETF")
80                (setf (gethash ',name *backend-sb-names*)
81                      res)))
82
83        (/show0 "about to put SB onto/into SB-LIST")
84        (setf *backend-sb-list*
85              (cons (sb-or-lose ',name)
86                    (remove ',name *backend-sb-list* :key #'sb-name)))
87        (/show0 "finished with DEFINE-STORAGE-BASE expansion")
88        ',name)))
89
90 (defmacro define-storage-class (name number sb-name &key (element-size '1)
91                                      (alignment '1) locations reserve-locations
92                                      save-p alternate-scs constant-scs)
93   #!+sb-doc
94   "Define-Storage-Class Name Number Storage-Base {Key Value}*
95   Define a storage class Name that uses the named Storage-Base. Number is a
96   small, non-negative integer that is used as an alias. The following
97   keywords are defined:
98
99   :Element-Size Size
100       The size of objects in this SC in whatever units the SB uses. This
101       defaults to 1.
102
103   :Alignment Size
104       The alignment restrictions for this SC. TNs will only be allocated at
105       offsets that are an even multiple of this number. Defaults to 1.
106
107   :Locations (Location*)
108       If the SB is :Finite, then this is a list of the offsets within the SB
109       that are in this SC.
110
111   :Reserve-Locations (Location*)
112       A subset of the Locations that the register allocator should try to
113       reserve for operand loading (instead of to hold variable values.)
114
115   :Save-P {T | NIL}
116       If T, then values stored in this SC must be saved in one of the
117       non-save-p :Alternate-SCs across calls.
118
119   :Alternate-SCs (SC*)
120       Indicates other SCs that can be used to hold values from this SC across
121       calls or when storage in this SC is exhausted. The SCs should be
122       specified in order of decreasing \"goodness\". There must be at least
123       one SC in an unbounded SB, unless this SC is only used for restricted or
124       wired TNs.
125
126   :Constant-SCs (SC*)
127       A list of the names of all the constant SCs that can be loaded into this
128       SC by a move function."
129
130   (check-type name symbol)
131   (check-type number sc-number)
132   (check-type sb-name symbol)
133   (check-type locations list)
134   (check-type reserve-locations list)
135   (check-type save-p boolean)
136   (check-type alternate-scs list)
137   (check-type constant-scs list)
138   (unless (= (logcount alignment) 1)
139     (error "alignment not a power of two: ~D" alignment))
140
141   (let ((sb (meta-sb-or-lose sb-name)))
142     (if (eq (sb-kind sb) :finite)
143         (let ((size (sb-size sb))
144               (element-size (eval element-size)))
145           (check-type element-size unsigned-byte)
146           (dolist (el locations)
147             (check-type el unsigned-byte)
148             (unless (<= 1 (+ el element-size) size)
149               (error "SC element ~D out of bounds for ~S" el sb))))
150         (when locations
151           (error ":LOCATIONS is meaningless in a ~S SB." (sb-kind sb))))
152
153     (unless (subsetp reserve-locations locations)
154       (error "RESERVE-LOCATIONS not a subset of LOCATIONS."))
155
156     (when (and (or alternate-scs constant-scs)
157                (eq (sb-kind sb) :non-packed))
158       (error
159        "It's meaningless to specify alternate or constant SCs in a ~S SB."
160        (sb-kind sb))))
161
162   (let ((nstack-p
163          (if (or (eq sb-name 'non-descriptor-stack)
164                  (find 'non-descriptor-stack
165                        (mapcar #'meta-sc-or-lose alternate-scs)
166                        :key #'(lambda (x)
167                                 (sb-name (sc-sb x)))))
168              t nil)))
169     `(progn
170        (eval-when (:compile-toplevel :load-toplevel :execute)
171          (let ((res (make-sc :name ',name :number ',number
172                              :sb (meta-sb-or-lose ',sb-name)
173                              :element-size ,element-size
174                              :alignment ,alignment
175                              :locations ',locations
176                              :reserve-locations ',reserve-locations
177                              :save-p ',save-p
178                              :number-stack-p ,nstack-p
179                              :alternate-scs (mapcar #'meta-sc-or-lose
180                                                     ',alternate-scs)
181                              :constant-scs (mapcar #'meta-sc-or-lose
182                                                    ',constant-scs))))
183            (setf (gethash ',name *backend-meta-sc-names*) res)
184            (setf (svref *backend-meta-sc-numbers* ',number) res)
185            (setf (svref (sc-load-costs res) ',number) 0)))
186
187        (let ((old (svref *backend-sc-numbers* ',number)))
188          (when (and old (not (eq (sc-name old) ',name)))
189            (warn "redefining SC number ~D from ~S to ~S" ',number
190                  (sc-name old) ',name)))
191
192        (setf (svref *backend-sc-numbers* ',number)
193              (meta-sc-or-lose ',name))
194        (setf (gethash ',name *backend-sc-names*)
195              (meta-sc-or-lose ',name))
196        (setf (sc-sb (sc-or-lose ',name)) (sb-or-lose ',sb-name))
197        ',name)))
198 \f
199 ;;;; move/coerce definition
200
201 ;;; Given a list of pairs of lists of SCs (as given to DEFINE-MOVE-VOP,
202 ;;; etc.), bind TO-SC and FROM-SC to all the combinations.
203 (defmacro do-sc-pairs ((from-sc-var to-sc-var scs) &body body)
204   `(do ((froms ,scs (cddr froms))
205         (tos (cdr ,scs) (cddr tos)))
206        ((null froms))
207      (dolist (from (car froms))
208        (let ((,from-sc-var (meta-sc-or-lose from)))
209          (dolist (to (car tos))
210            (let ((,to-sc-var (meta-sc-or-lose to)))
211              ,@body))))))
212
213 (defmacro define-move-function ((name cost) lambda-list scs &body body)
214   #!+sb-doc
215   "Define-Move-Function (Name Cost) lambda-list ({(From-SC*) (To-SC*)}*) form*
216   Define the function Name and note it as the function used for moving operands
217   from the From-SCs to the To-SCs. Cost is the cost of this move operation.
218   The function is called with three arguments: the VOP (for context), and the
219   source and destination TNs. An ASSEMBLE form is wrapped around the body.
220   All uses of DEFINE-MOVE-FUNCTION should be compiled before any uses of
221   DEFINE-VOP."
222   (when (or (oddp (length scs)) (null scs))
223     (error "malformed SCs spec: ~S" scs))
224   (check-type cost index)
225   `(progn
226      (eval-when (:compile-toplevel :load-toplevel :execute)
227        (do-sc-pairs (from-sc to-sc ',scs)
228          (unless (eq from-sc to-sc)
229            (let ((num (sc-number from-sc)))
230              (setf (svref (sc-move-functions to-sc) num) ',name)
231              (setf (svref (sc-load-costs to-sc) num) ',cost)))))
232
233      (defun ,name ,lambda-list
234        (sb!assem:assemble (*code-segment* ,(first lambda-list))
235          ,@body))))
236
237 (eval-when (:compile-toplevel :load-toplevel :execute)
238   (defparameter *sc-vop-slots*
239     '((:move . sc-move-vops)
240       (:move-argument . sc-move-arg-vops))))
241
242 ;;; We record the VOP and costs for all SCs that we can move between
243 ;;; (including implicit loading).
244 (defmacro define-move-vop (name kind &rest scs)
245   #!+sb-doc
246   "Define-Move-VOP Name {:Move | :Move-Argument} {(From-SC*) (To-SC*)}*
247   Make Name be the VOP used to move values in the specified From-SCs to the
248   representation of the To-SCs. If kind is :Move-Argument, then the VOP takes
249   an extra argument, which is the frame pointer of the frame to move into."
250   (when (or (oddp (length scs)) (null scs))
251     (error "malformed SCs spec: ~S" scs))
252   (let ((accessor (or (cdr (assoc kind *sc-vop-slots*))
253                       (error "unknown kind ~S" kind))))
254     `(progn
255        ,@(when (eq kind :move)
256            `((eval-when (:compile-toplevel :load-toplevel :execute)
257                (do-sc-pairs (from-sc to-sc ',scs)
258                  (compute-move-costs from-sc to-sc
259                                      ,(vop-parse-cost
260                                        (vop-parse-or-lose name)))))))
261
262        (let ((vop (template-or-lose ',name)))
263          (do-sc-pairs (from-sc to-sc ',scs)
264            (dolist (dest-sc (cons to-sc (sc-alternate-scs to-sc)))
265              (let ((vec (,accessor dest-sc)))
266                (let ((scn (sc-number from-sc)))
267                  (setf (svref vec scn)
268                        (adjoin-template vop (svref vec scn))))
269                (dolist (sc (append (sc-alternate-scs from-sc)
270                                    (sc-constant-scs from-sc)))
271                  (let ((scn (sc-number sc)))
272                    (setf (svref vec scn)
273                          (adjoin-template vop (svref vec scn))))))))))))
274 \f
275 ;;;; primitive type definition
276
277 (defun meta-primitive-type-or-lose (name)
278   (the primitive-type
279        (or (gethash name *backend-meta-primitive-type-names*)
280            (error "~S is not a defined primitive type." name))))
281
282 ;;; Define a primitive type NAME. Each SCS entry specifies a storage
283 ;;; class that values of this type may be allocated in. TYPE is the
284 ;;; type descriptor for the Lisp type that is equivalent to this type.
285 (defmacro !def-primitive-type (name scs &key (type name))
286   (check-type name symbol)
287   (check-type scs list)
288   (let ((scns (mapcar #'meta-sc-number-or-lose scs))
289         (get-type `(specifier-type ',type)))
290     `(progn
291        (/show0 "doing !DEF-PRIMITIVE-TYPE, NAME=..")
292        (/primitive-print ,(symbol-name name))
293        (eval-when (#-sb-xc :compile-toplevel :load-toplevel :execute)
294          (setf (gethash ',name *backend-meta-primitive-type-names*)
295                (make-primitive-type :name ',name
296                                     :scs ',scns
297                                     :type ,get-type)))
298        ,(once-only ((n-old `(gethash ',name *backend-primitive-type-names*))
299                     (n-type get-type))
300           `(progn
301              ;; If the PRIMITIVE-TYPE structure already exists, we
302              ;; destructively modify it so that existing references in
303              ;; templates won't be invalidated. FIXME: This should no
304              ;; longer be an issue in SBCL, since we don't try to do
305              ;; serious surgery on ourselves. Probably this should
306              ;; just become an assertion that N-OLD is NIL, so that we
307              ;; don't have to try to maintain the correctness of the
308              ;; never-ordinarily-used clause.
309              (/show0 "in !DEF-PRIMITIVE-TYPE, about to COND")
310              (cond (,n-old
311                     (/show0 "in ,N-OLD clause of COND")
312                     (setf (primitive-type-scs ,n-old) ',scns)
313                     (setf (primitive-type-type ,n-old) ,n-type))
314                    (t
315                     (/show0 "in T clause of COND")
316                     (setf (gethash ',name *backend-primitive-type-names*)
317                           (make-primitive-type :name ',name
318                                                :scs ',scns
319                                                :type ,n-type))))
320              (/show0 "done with !DEF-PRIMITIVE-TYPE")
321              ',name)))))
322
323 ;;; Define NAME to be an alias for RESULT in VOP operand type restrictions.
324 (defmacro !def-primitive-type-alias (name result)
325   ;; Just record the translation.
326   `(eval-when (:compile-toplevel :load-toplevel :execute)
327      (setf (gethash ',name *backend-primitive-type-aliases*) ',result)
328      ',name))
329
330 (defparameter *primitive-type-slot-alist*
331   '((:check . primitive-type-check)))
332
333 (defmacro primitive-type-vop (vop kinds &rest types)
334   #!+sb-doc
335   "Primitive-Type-VOP Vop (Kind*) Type*
336   Annotate all the specified primitive Types with the named VOP under each of
337   the specified kinds:
338
339   :Check
340       A one argument one result VOP that moves the argument to the result,
341       checking that the value is of this type in the process."
342   (let ((n-vop (gensym))
343         (n-type (gensym)))
344     `(let ((,n-vop (template-or-lose ',vop)))
345        ,@(mapcar
346           #'(lambda (type)
347               `(let ((,n-type (primitive-type-or-lose ',type)))
348                  ,@(mapcar
349                     #'(lambda (kind)
350                         (let ((slot (or (cdr (assoc kind
351                                                     *primitive-type-slot-alist*))
352                                         (error "unknown kind: ~S" kind))))
353                           `(setf (,slot ,n-type) ,n-vop)))
354                     kinds)))
355           types)
356        nil)))
357
358 ;;; Return true if SC is either one of Ptype's SC's, or one of those SC's
359 ;;; alternate or constant SCs.
360 (defun meta-sc-allowed-by-primitive-type (sc ptype)
361   (declare (type sc sc) (type primitive-type ptype))
362   (let ((scn (sc-number sc)))
363     (dolist (allowed (primitive-type-scs ptype) nil)
364       (when (eql allowed scn)
365         (return t))
366       (let ((allowed-sc (svref *backend-meta-sc-numbers* allowed)))
367         (when (or (member sc (sc-alternate-scs allowed-sc))
368                   (member sc (sc-constant-scs allowed-sc)))
369           (return t))))))
370 \f
371 ;;;; VOP definition structures
372 ;;;;
373 ;;;; DEFINE-VOP uses some fairly complex data structures at
374 ;;;; meta-compile time, both to hold the results of parsing the
375 ;;;; elaborate syntax and to retain the information so that it can be
376 ;;;; inherited by other VOPs.
377
378 ;;; A VOP-PARSE object holds everything we need to know about a VOP at
379 ;;; meta-compile time.
380 (def!struct (vop-parse
381              (:make-load-form-fun just-dump-it-normally)
382              #-sb-xc-host (:pure t))
383   ;; the name of this VOP
384   (name nil :type symbol)
385   ;; If true, then the name of the VOP we inherit from.
386   (inherits nil :type (or symbol null))
387   ;; lists of OPERAND-PARSE structures describing the arguments,
388   ;; results and temporaries of the VOP
389   (args nil :type list)
390   (results nil :type list)
391   (temps nil :type list)
392   ;; OPERAND-PARSE structures containing information about more args
393   ;; and results. If null, then there there are no more operands of
394   ;; that kind
395   (more-args nil :type (or operand-parse null))
396   (more-results nil :type (or operand-parse null))
397   ;; a list of all the above together
398   (operands nil :type list)
399   ;; names of variables that should be declared IGNORE
400   (ignores () :type list)
401   ;; true if this is a :CONDITIONAL VOP
402   (conditional-p nil)
403   ;; argument and result primitive types. These are pulled out of the
404   ;; operands, since we often want to change them without respecifying
405   ;; the operands.
406   (arg-types :unspecified :type (or (member :unspecified) list))
407   (result-types :unspecified :type (or (member :unspecified) list))
408   ;; the guard expression specified, or NIL if none
409   (guard nil)
410   ;; the cost of and body code for the generator
411   (cost 0 :type unsigned-byte)
412   (body :unspecified :type (or (member :unspecified) list))
413   ;; info for VOP variants. The list of forms to be evaluated to get
414   ;; the variant args for this VOP, and the list of variables to be
415   ;; bound to the variant args.
416   (variant () :type list)
417   (variant-vars () :type list)
418   ;; variables bound to the VOP and Vop-Node when in the generator body
419   (vop-var (gensym) :type symbol)
420   (node-var nil :type (or symbol null))
421   ;; a list of the names of the codegen-info arguments to this VOP
422   (info-args () :type list)
423   ;; an efficiency note associated with this VOP
424   (note nil :type (or string null))
425   ;; a list of the names of the Effects and Affected attributes for
426   ;; this VOP
427   (effects '(any) :type list)
428   (affected '(any) :type list)
429   ;; a list of the names of functions this VOP is a translation of and
430   ;; the policy that allows this translation to be done. :Fast is a
431   ;; safe default, since it isn't a safe policy.
432   (translate () :type list)
433   (ltn-policy :fast :type ltn-policy)
434   ;; stuff used by life analysis
435   (save-p nil :type (member t nil :compute-only :force-to-stack))
436   ;; info about how to emit move-argument VOPs for the more operand in
437   ;; call/return VOPs
438   (move-args nil :type (member nil :local-call :full-call :known-return)))
439 (defprinter (vop-parse)
440   name
441   (inherits :test inherits)
442   args
443   results
444   temps
445   (more-args :test more-args)
446   (more-results :test more-results)
447   (conditional-p :test conditional-p)
448   ignores
449   arg-types
450   result-types
451   cost
452   body
453   (variant :test variant)
454   (variant-vars :test variant-vars)
455   (info-args :test info-args)
456   (note :test note)
457   effects
458   affected
459   translate
460   ltn-policy
461   (save-p :test save-p)
462   (move-args :test move-args))
463
464 ;;; An OPERAND-PARSE object contains stuff we need to know about an
465 ;;; operand or temporary at meta-compile time. Besides the obvious
466 ;;; stuff, we also store the names of per-operand temporaries here.
467 (def!struct (operand-parse
468              (:make-load-form-fun just-dump-it-normally)
469              #-sb-xc-host (:pure t))
470   ;; name of the operand (which we bind to the TN)
471   (name nil :type symbol)
472   ;; the way this operand is used:
473   (kind (required-argument)
474         :type (member :argument :result :temporary
475                       :more-argument :more-result))
476   ;; If true, the name of an operand that this operand is targeted to.
477   ;; This is only meaningful in :ARGUMENT and :TEMPORARY operands.
478   (target nil :type (or symbol null))
479   ;; TEMP is a temporary that holds the TN-REF for this operand.
480   ;; TEMP-TEMP holds the write reference that begins a temporary's
481   ;; lifetime.
482   (temp (gensym) :type symbol)
483   (temp-temp nil :type (or symbol null))
484   ;; the time that this operand is first live and the time at which it
485   ;; becomes dead again. These are TIME-SPECs, as returned by
486   ;; PARSE-TIME-SPEC.
487   born
488   dies
489   ;; a list of the names of the SCs that this operand is allowed into.
490   ;; If false, there is no restriction.
491   (scs nil :type list)
492   ;; Variable that is bound to the load TN allocated for this operand, or to
493   ;; NIL if no load-TN was allocated.
494   (load-tn (gensym) :type symbol)
495   ;; an expression that tests whether to do automatic operand loading
496   (load t)
497   ;; In a wired or restricted temporary this is the SC the TN is to be
498   ;; packed in. Null otherwise.
499   (sc nil :type (or symbol null))
500   ;; If non-null, we are a temp wired to this offset in SC.
501   (offset nil :type (or unsigned-byte null)))
502 (defprinter (operand-parse)
503   name
504   kind
505   (target :test target)
506   born
507   dies
508   (scs :test scs)
509   (load :test load)
510   (sc :test sc)
511   (offset :test offset))
512 \f
513 ;;;; miscellaneous utilities
514
515 ;;; Find the operand or temporary with the specifed Name in the VOP
516 ;;; Parse. If there is no such operand, signal an error. Also error if
517 ;;; the operand kind isn't one of the specified Kinds. If Error-P is
518 ;;; NIL, just return NIL if there is no such operand.
519 (defun find-operand (name parse &optional
520                           (kinds '(:argument :result :temporary))
521                           (error-p t))
522   (declare (symbol name) (type vop-parse parse) (list kinds))
523   (let ((found (find name (vop-parse-operands parse)
524                      :key #'operand-parse-name)))
525     (if found
526         (unless (member (operand-parse-kind found) kinds)
527           (error "Operand ~S isn't one of these kinds: ~S." name kinds))
528         (when error-p
529           (error "~S is not an operand to ~S." name (vop-parse-name parse))))
530     found))
531
532 ;;; Get the VOP-Parse structure for NAME or die trying. For all
533 ;;; meta-compile time uses, the VOP-Parse should be used instead of
534 ;;; the VOP-Info.
535 (defun vop-parse-or-lose (name)
536   (the vop-parse
537        (or (gethash name *backend-parsed-vops*)
538            (error "~S is not the name of a defined VOP." name))))
539
540 ;;; Return a list of LET-forms to parse a TN-REF list into the temps
541 ;;; specified by the operand-parse structures. MORE-OPERAND is the
542 ;;; Operand-Parse describing any more operand, or NIL if none. REFS is
543 ;;; an expression that evaluates into the first tn-ref.
544 (defun access-operands (operands more-operand refs)
545   (declare (list operands))
546   (collect ((res))
547     (let ((prev refs))
548       (dolist (op operands)
549         (let ((n-ref (operand-parse-temp op)))
550           (res `(,n-ref ,prev))
551           (setq prev `(tn-ref-across ,n-ref))))
552
553       (when more-operand
554         (res `(,(operand-parse-name more-operand) ,prev))))
555     (res)))
556
557 ;;; This is used with ACCESS-OPERANDS to prevent warnings for TN-Ref
558 ;;; temps not used by some particular function. It returns the name of
559 ;;; the last operand, or NIL if Operands is NIL.
560 (defun ignore-unreferenced-temps (operands)
561   (when operands
562     (operand-parse-temp (car (last operands)))))
563
564 ;;; Grab an arg out of a VOP spec, checking the type and syntax and stuff.
565 (defun vop-spec-arg (spec type &optional (n 1) (last t))
566   (let ((len (length spec)))
567     (when (<= len n)
568       (error "~:R argument missing: ~S" n spec))
569     (when (and last (> len (1+ n)))
570       (error "extra junk at end of ~S" spec))
571     (let ((thing (elt spec n)))
572       (unless (typep thing type)
573         (error "~:R argument is not a ~S: ~S" n type spec))
574       thing)))
575 \f
576 ;;;; time specs
577
578 ;;; Return a time spec describing a time during the evaluation of a
579 ;;; VOP, used to delimit operand and temporary lifetimes. The
580 ;;; representation is a cons whose CAR is the number of the evaluation
581 ;;; phase and the CDR is the sub-phase. The sub-phase is 0 in the
582 ;;; :LOAD and :SAVE phases.
583 (defun parse-time-spec (spec)
584   (let ((dspec (if (atom spec) (list spec 0) spec)))
585     (unless (and (= (length dspec) 2)
586                  (typep (second dspec) 'unsigned-byte))
587       (error "malformed time specifier: ~S" spec))
588
589     (cons (case (first dspec)
590             (:load 0)
591             (:argument 1)
592             (:eval 2)
593             (:result 3)
594             (:save 4)
595             (t
596              (error "unknown phase in time specifier: ~S" spec)))
597           (second dspec))))
598
599 ;;; Return true if the time spec X is the same or later time than Y.
600 (defun time-spec-order (x y)
601   (or (> (car x) (car y))
602       (and (= (car x) (car y))
603            (>= (cdr x) (cdr y)))))
604 \f
605 ;;;; generation of emit functions
606
607 (defun compute-temporaries-description (parse)
608   (let ((temps (vop-parse-temps parse))
609         (element-type '(unsigned-byte 16)))
610     (when temps
611       (let ((results (make-specializable-array
612                       (length temps)
613                       :element-type element-type))
614             (index 0))
615         (dolist (temp temps)
616           (declare (type operand-parse temp))
617           (let ((sc (operand-parse-sc temp))
618                 (offset (operand-parse-offset temp)))
619             (assert sc)
620             (setf (aref results index)
621                   (if offset
622                       (+ (ash offset (1+ sc-bits))
623                          (ash (meta-sc-number-or-lose sc) 1)
624                          1)
625                       (ash (meta-sc-number-or-lose sc) 1))))
626           (incf index))
627         ;; KLUDGE: As in the other COERCEs wrapped around with
628         ;; MAKE-SPECIALIZABLE-ARRAY results in COMPUTE-REF-ORDERING,
629         ;; this coercion could be removed by a sufficiently smart
630         ;; compiler, but I dunno whether Python is that smart. It
631         ;; would be good to check this and help it if it's not smart
632         ;; enough to remove it for itself. However, it's probably not
633         ;; urgent, since the overhead of an extra no-op conversion is
634         ;; unlikely to be large compared to consing and corresponding
635         ;; GC. -- WHN ca. 19990701
636         `(coerce ,results '(specializable-vector ,element-type))))))
637
638 (defun compute-ref-ordering (parse)
639   (let* ((num-args (+ (length (vop-parse-args parse))
640                       (if (vop-parse-more-args parse) 1 0)))
641          (num-results (+ (length (vop-parse-results parse))
642                          (if (vop-parse-more-results parse) 1 0)))
643          (index 0))
644     (collect ((refs) (targets))
645       (dolist (op (vop-parse-operands parse))
646         (when (operand-parse-target op)
647           (unless (member (operand-parse-kind op) '(:argument :temporary))
648             (error "cannot target a ~S operand: ~S" (operand-parse-kind op)
649                    (operand-parse-name op)))
650           (let ((target (find-operand (operand-parse-target op) parse
651                                       '(:temporary :result))))
652             (targets (+ (* index max-vop-tn-refs)
653                         (ecase (operand-parse-kind target)
654                           (:result
655                            (+ (position-or-lose target
656                                                 (vop-parse-results parse))
657                               num-args))
658                           (:temporary
659                            (+ (* (position-or-lose target
660                                                    (vop-parse-temps parse))
661                                  2)
662                               num-args num-results)))))))
663         (let ((born (operand-parse-born op))
664               (dies (operand-parse-dies op)))
665           (ecase (operand-parse-kind op)
666             (:argument
667              (refs (cons (cons dies nil) index)))
668             (:more-argument
669              (refs (cons (cons dies nil) index)))
670             (:result
671              (refs (cons (cons born t) index)))
672             (:more-result
673              (refs (cons (cons born t) index)))
674             (:temporary
675              (refs (cons (cons dies nil) index))
676              (incf index)
677              (refs (cons (cons born t) index))))
678           (incf index)))
679       (let* ((sorted (sort (refs)
680                            #'(lambda (x y)
681                                (let ((x-time (car x))
682                                      (y-time (car y)))
683                                  (if (time-spec-order x-time y-time)
684                                      (if (time-spec-order y-time x-time)
685                                          (and (not (cdr x)) (cdr y))
686                                          nil)
687                                      t)))
688                            :key #'car))
689              (oe-type '(mod #.max-vop-tn-refs)) ; :REF-ORDERING element type
690              (te-type '(mod #.(* max-vop-tn-refs 2))) ; :TARGETS element type
691              (ordering (make-specializable-array
692                         (length sorted)
693                         :element-type oe-type)))
694         (let ((index 0))
695           (dolist (ref sorted)
696             (setf (aref ordering index) (cdr ref))
697             (incf index)))
698         `(:num-args ,num-args
699           :num-results ,num-results
700           ;; KLUDGE: The (COERCE .. (SPECIALIZABLE-VECTOR ..)) wrapper
701           ;; here around the result returned by
702           ;; MAKE-SPECIALIZABLE-ARRAY above was of course added to
703           ;; help with cross-compilation. "A sufficiently smart
704           ;; compiler" should be able to optimize all this away in the
705           ;; final target Lisp, leaving a single MAKE-ARRAY with no
706           ;; subsequent coercion. However, I don't know whether Python
707           ;; is that smart. (Can it figure out the return type of
708           ;; MAKE-ARRAY? Does it know that COERCE can be optimized
709           ;; away if the input type is known to be the same as the
710           ;; COERCEd-to type?) At some point it would be good to test
711           ;; to see whether this construct is in fact causing run-time
712           ;; overhead, and fix it if so. (Some declarations of the
713           ;; types returned by MAKE-ARRAY might be enough to fix it.)
714           ;; However, it's probably not urgent to fix this, since it's
715           ;; hard to imagine that any overhead caused by calling
716           ;; COERCE and letting it decide to bail out could be large
717           ;; compared to the cost of consing and GCing the vectors in
718           ;; the first place. -- WHN ca. 19990701
719           :ref-ordering (coerce ',ordering
720                                 '(specializable-vector ,oe-type))
721           ,@(when (targets)
722               `(:targets (coerce ',(targets)
723                                  '(specializable-vector ,te-type)))))))))
724
725 (defun make-emit-function-and-friends (parse)
726   `(:emit-function #'emit-generic-vop
727     :temps ,(compute-temporaries-description parse)
728     ,@(compute-ref-ordering parse)))
729 \f
730 ;;;; generator functions
731
732 ;;; Return an alist that translates from lists of SCs we can load OP
733 ;;; from to the move function used for loading those SCs. We quietly
734 ;;; ignore restrictions to :non-packed (constant) and :unbounded SCs,
735 ;;; since we don't load into those SCs.
736 (defun find-move-functions (op load-p)
737   (collect ((funs))
738     (dolist (sc-name (operand-parse-scs op))
739       (let* ((sc (meta-sc-or-lose sc-name))
740              (scn (sc-number sc))
741              (load-scs (append (when load-p
742                                  (sc-constant-scs sc))
743                                (sc-alternate-scs sc))))
744         (cond
745          (load-scs
746           (dolist (alt load-scs)
747             (unless (member (sc-name alt) (operand-parse-scs op) :test #'eq)
748               (let* ((altn (sc-number alt))
749                      (name (if load-p
750                                (svref (sc-move-functions sc) altn)
751                                (svref (sc-move-functions alt) scn)))
752                      (found (or (assoc alt (funs) :test #'member)
753                                 (rassoc name (funs)))))
754                 (unless name
755                   (error "no move function defined to ~:[save~;load~] SC ~S ~
756                           with ~S ~:[to~;from~] from SC ~S"
757                          load-p sc-name load-p (sc-name alt)))
758                 
759                 (cond (found
760                        (unless (eq (cdr found) name)
761                          (error "can't tell whether to ~:[save~;load~]~@
762                                  or ~S when operand is in SC ~S"
763                                 load-p name (cdr found) (sc-name alt)))
764                        (pushnew alt (car found)))
765                       (t
766                        (funs (cons (list alt) name))))))))
767          ((member (sb-kind (sc-sb sc)) '(:non-packed :unbounded)))
768          (t
769           (error "SC ~S has no alternate~:[~; or constant~] SCs, yet it is~@
770                   mentioned in the restriction for operand ~S"
771                  sc-name load-p (operand-parse-name op))))))
772     (funs)))
773
774 ;;; Return a form to load/save the specified operand when it has a
775 ;;; load TN. For any given SC that we can load from, there must be a
776 ;;; unique load function. If all SCs we can load from have the same
777 ;;; move function, then we just call that when there is a load TN. If
778 ;;; there are multiple possible move functions, then we dispatch off
779 ;;; of the operand TN's type to see which move function to use.
780 (defun call-move-function (parse op load-p)
781   (let ((funs (find-move-functions op load-p))
782         (load-tn (operand-parse-load-tn op)))
783     (if funs
784         (let* ((tn `(tn-ref-tn ,(operand-parse-temp op)))
785                (n-vop (or (vop-parse-vop-var parse)
786                           (setf (vop-parse-vop-var parse) (gensym))))
787                (form (if (rest funs)
788                          `(sc-case ,tn
789                             ,@(mapcar #'(lambda (x)
790                                           `(,(mapcar #'sc-name (car x))
791                                             ,(if load-p
792                                                  `(,(cdr x) ,n-vop ,tn
793                                                    ,load-tn)
794                                                  `(,(cdr x) ,n-vop ,load-tn
795                                                    ,tn))))
796                                       funs))
797                          (if load-p
798                              `(,(cdr (first funs)) ,n-vop ,tn ,load-tn)
799                              `(,(cdr (first funs)) ,n-vop ,load-tn ,tn)))))
800           (if (eq (operand-parse-load op) t)
801               `(when ,load-tn ,form)
802               `(when (eq ,load-tn ,(operand-parse-name op))
803                  ,form)))
804         `(when ,load-tn
805            (error "load TN allocated, but no move function?~@
806                    VM definition is inconsistent, recompile and try again.")))))
807
808 ;;; Return the TN that we should bind to the operand's var in the
809 ;;; generator body. In general, this involves evaluating the :LOAD-IF
810 ;;; test expression.
811 (defun decide-to-load (parse op)
812   (let ((load (operand-parse-load op))
813         (load-tn (operand-parse-load-tn op))
814         (temp (operand-parse-temp op)))
815     (if (eq load t)
816         `(or ,load-tn (tn-ref-tn ,temp))
817         (collect ((binds)
818                   (ignores))
819           (dolist (x (vop-parse-operands parse))
820             (when (member (operand-parse-kind x) '(:argument :result))
821               (let ((name (operand-parse-name x)))
822                 (binds `(,name (tn-ref-tn ,(operand-parse-temp x))))
823                 (ignores name))))
824           `(if (and ,load-tn
825                     (let ,(binds)
826                       (declare (ignorable ,@(ignores)))
827                       ,load))
828                ,load-tn
829                (tn-ref-tn ,temp))))))
830
831 ;;; Make a lambda that parses the VOP TN-Refs, does automatic operand
832 ;;; loading, and runs the appropriate code generator.
833 (defun make-generator-function (parse)
834   (declare (type vop-parse parse))
835   (let ((n-vop (vop-parse-vop-var parse))
836         (operands (vop-parse-operands parse))
837         (n-info (gensym)) (n-variant (gensym)))
838     (collect ((binds)
839               (loads)
840               (saves))
841       (dolist (op operands)
842         (ecase (operand-parse-kind op)
843           ((:argument :result)
844            (let ((temp (operand-parse-temp op))
845                  (name (operand-parse-name op)))
846              (cond ((and (operand-parse-load op) (operand-parse-scs op))
847                     (binds `(,(operand-parse-load-tn op)
848                              (tn-ref-load-tn ,temp)))
849                     (binds `(,name ,(decide-to-load parse op)))
850                     (if (eq (operand-parse-kind op) :argument)
851                         (loads (call-move-function parse op t))
852                         (saves (call-move-function parse op nil))))
853                    (t
854                     (binds `(,name (tn-ref-tn ,temp)))))))
855           (:temporary
856            (binds `(,(operand-parse-name op)
857                     (tn-ref-tn ,(operand-parse-temp op)))))
858           ((:more-argument :more-result))))
859
860       `#'(lambda (,n-vop)
861            (let* (,@(access-operands (vop-parse-args parse)
862                                      (vop-parse-more-args parse)
863                                      `(vop-args ,n-vop))
864                   ,@(access-operands (vop-parse-results parse)
865                                      (vop-parse-more-results parse)
866                                      `(vop-results ,n-vop))
867                   ,@(access-operands (vop-parse-temps parse) nil
868                                      `(vop-temps ,n-vop))
869                   ,@(when (vop-parse-info-args parse)
870                       `((,n-info (vop-codegen-info ,n-vop))
871                         ,@(mapcar #'(lambda (x) `(,x (pop ,n-info)))
872                                   (vop-parse-info-args parse))))
873                   ,@(when (vop-parse-variant-vars parse)
874                       `((,n-variant (vop-info-variant (vop-info ,n-vop)))
875                         ,@(mapcar #'(lambda (x) `(,x (pop ,n-variant)))
876                                   (vop-parse-variant-vars parse))))
877                   ,@(when (vop-parse-node-var parse)
878                       `((,(vop-parse-node-var parse) (vop-node ,n-vop))))
879                   ,@(binds))
880              (declare (ignore ,@(vop-parse-ignores parse)))
881              ,@(loads)
882              (sb!assem:assemble (*code-segment* ,n-vop)
883                ,@(vop-parse-body parse))
884              ,@(saves))))))
885 \f
886 ;;; Given a list of operand specifications as given to DEFINE-VOP,
887 ;;; return a list of OPERAND-PARSE structures describing the fixed
888 ;;; operands, and a single OPERAND-PARSE describing any more operand.
889 ;;; If we are inheriting a VOP, we default attributes to the inherited
890 ;;; operand of the same name.
891 (defun parse-operands (parse specs kind)
892   (declare (list specs)
893            (type (member :argument :result) kind))
894   (let ((num -1)
895         (more nil))
896     (collect ((operands))
897       (dolist (spec specs)
898         (unless (and (consp spec) (symbolp (first spec)) (oddp (length spec)))
899           (error "malformed operand specifier: ~S" spec))
900         (when more
901           (error "The MORE operand isn't the last operand: ~S" specs))
902         (let* ((name (first spec))
903                (old (if (vop-parse-inherits parse)
904                         (find-operand name
905                                       (vop-parse-or-lose
906                                        (vop-parse-inherits parse))
907                                       (list kind)
908                                       nil)
909                         nil))
910                (res (if old
911                         (make-operand-parse
912                          :name name
913                          :kind kind
914                          :target (operand-parse-target old)
915                          :born (operand-parse-born old)
916                          :dies (operand-parse-dies old)
917                          :scs (operand-parse-scs old)
918                          :load-tn (operand-parse-load-tn old)
919                          :load (operand-parse-load old))
920                         (ecase kind
921                           (:argument
922                            (make-operand-parse
923                             :name (first spec)
924                             :kind :argument
925                             :born (parse-time-spec :load)
926                             :dies (parse-time-spec `(:argument ,(incf num)))))
927                           (:result
928                            (make-operand-parse
929                             :name (first spec)
930                             :kind :result
931                             :born (parse-time-spec `(:result ,(incf num)))
932                             :dies (parse-time-spec :save)))))))
933           (do ((key (rest spec) (cddr key)))
934               ((null key))
935             (let ((value (second key)))
936               (case (first key)
937                 (:scs
938                  (check-type value list)
939                  (setf (operand-parse-scs res) (remove-duplicates value)))
940                 (:load-tn
941                  (check-type value symbol)
942                  (setf (operand-parse-load-tn res) value))
943                 (:load-if
944                  (setf (operand-parse-load res) value))
945                 (:more
946                  (check-type value boolean)
947                  (setf (operand-parse-kind res)
948                        (if (eq kind :argument) :more-argument :more-result))
949                  (setf (operand-parse-load res) nil)
950                  (setq more res))
951                 (:target
952                  (check-type value symbol)
953                  (setf (operand-parse-target res) value))
954                 (:from
955                  (unless (eq kind :result)
956                    (error "can only specify :FROM in a result: ~S" spec))
957                  (setf (operand-parse-born res) (parse-time-spec value)))
958                 (:to
959                  (unless (eq kind :argument)
960                    (error "can only specify :TO in an argument: ~S" spec))
961                  (setf (operand-parse-dies res) (parse-time-spec value)))
962                 (t
963                  (error "unknown keyword in operand specifier: ~S" spec)))))
964
965           (cond ((not more)
966                  (operands res))
967                 ((operand-parse-target more)
968                  (error "cannot specify :TARGET in a :MORE operand"))
969                 ((operand-parse-load more)
970                  (error "cannot specify :LOAD-IF in a :MORE operand")))))
971       (values (the list (operands)) more))))
972 \f
973 ;;; Parse a temporary specification, putting the OPERAND-PARSE
974 ;;; structures in the PARSE structure.
975 (defun parse-temporary (spec parse)
976   (declare (list spec)
977            (type vop-parse parse))
978   (let ((len (length spec)))
979     (unless (>= len 2)
980       (error "malformed temporary spec: ~S" spec))
981     (unless (listp (second spec))
982       (error "malformed options list: ~S" (second spec)))
983     (unless (evenp (length (second spec)))
984       (error "odd number of arguments in keyword options: ~S" spec))
985     (unless (consp (cddr spec))
986       (warn "temporary spec allocates no temps:~%  ~S" spec))
987     (dolist (name (cddr spec))
988       (unless (symbolp name)
989         (error "bad temporary name: ~S" name))
990       (let ((res (make-operand-parse :name name
991                                      :kind :temporary
992                                      :temp-temp (gensym)
993                                      :born (parse-time-spec :load)
994                                      :dies (parse-time-spec :save))))
995         (do ((opt (second spec) (cddr opt)))
996             ((null opt))
997           (case (first opt)
998             (:target
999              (setf (operand-parse-target res)
1000                    (vop-spec-arg opt 'symbol 1 nil)))
1001             (:sc
1002              (setf (operand-parse-sc res)
1003                    (vop-spec-arg opt 'symbol 1 nil)))
1004             (:offset
1005              (let ((offset (eval (second opt))))
1006                (check-type offset unsigned-byte)
1007                (setf (operand-parse-offset res) offset)))
1008             (:from
1009              (setf (operand-parse-born res) (parse-time-spec (second opt))))
1010             (:to
1011              (setf (operand-parse-dies res) (parse-time-spec (second opt))))
1012             ;; Backward compatibility...
1013             (:scs
1014              (let ((scs (vop-spec-arg opt 'list 1 nil)))
1015                (unless (= (length scs) 1)
1016                  (error "must specify exactly one SC for a temporary"))
1017                (setf (operand-parse-sc res) (first scs))))
1018             (:type)
1019             (t
1020              (error "unknown temporary option: ~S" opt))))
1021
1022         (unless (and (time-spec-order (operand-parse-dies res)
1023                                       (operand-parse-born res))
1024                      (not (time-spec-order (operand-parse-born res)
1025                                            (operand-parse-dies res))))
1026           (error "Temporary lifetime doesn't begin before it ends: ~S" spec))
1027
1028         (unless (operand-parse-sc res)
1029           (error "must specify :SC for all temporaries: ~S" spec))
1030
1031         (setf (vop-parse-temps parse)
1032               (cons res
1033                     (remove name (vop-parse-temps parse)
1034                             :key #'operand-parse-name))))))
1035   (values))
1036 \f
1037 ;;; the top-level parse function: clobber PARSE to represent the
1038 ;;; specified options.
1039 (defun parse-define-vop (parse specs)
1040   (declare (type vop-parse parse) (list specs))
1041   (dolist (spec specs)
1042     (unless (consp spec)
1043       (error "malformed option specification: ~S" spec))
1044     (case (first spec)
1045       (:args
1046        (multiple-value-bind (fixed more)
1047            (parse-operands parse (rest spec) :argument)
1048          (setf (vop-parse-args parse) fixed)
1049          (setf (vop-parse-more-args parse) more)))
1050       (:results
1051        (multiple-value-bind (fixed more)
1052            (parse-operands parse (rest spec) :result)
1053          (setf (vop-parse-results parse) fixed)
1054          (setf (vop-parse-more-results parse) more))
1055        (setf (vop-parse-conditional-p parse) nil))
1056       (:conditional
1057        (setf (vop-parse-result-types parse) ())
1058        (setf (vop-parse-results parse) ())
1059        (setf (vop-parse-more-results parse) nil)
1060        (setf (vop-parse-conditional-p parse) t))
1061       (:temporary
1062        (parse-temporary spec parse))
1063       (:generator
1064        (setf (vop-parse-cost parse)
1065              (vop-spec-arg spec 'unsigned-byte 1 nil))
1066        (setf (vop-parse-body parse) (cddr spec)))
1067       (:effects
1068        (setf (vop-parse-effects parse) (rest spec)))
1069       (:affected
1070        (setf (vop-parse-affected parse) (rest spec)))
1071       (:info
1072        (setf (vop-parse-info-args parse) (rest spec)))
1073       (:ignore
1074        (setf (vop-parse-ignores parse) (rest spec)))
1075       (:variant
1076        (setf (vop-parse-variant parse) (rest spec)))
1077       (:variant-vars
1078        (let ((vars (rest spec)))
1079          (setf (vop-parse-variant-vars parse) vars)
1080          (setf (vop-parse-variant parse)
1081                (make-list (length vars) :initial-element nil))))
1082       (:variant-cost
1083        (setf (vop-parse-cost parse) (vop-spec-arg spec 'unsigned-byte)))
1084       (:vop-var
1085        (setf (vop-parse-vop-var parse) (vop-spec-arg spec 'symbol)))
1086       (:move-args
1087        (setf (vop-parse-move-args parse)
1088              (vop-spec-arg spec '(member nil :local-call :full-call
1089                                          :known-return))))
1090       (:node-var
1091        (setf (vop-parse-node-var parse) (vop-spec-arg spec 'symbol)))
1092       (:note
1093        (setf (vop-parse-note parse) (vop-spec-arg spec '(or string null))))
1094       (:arg-types
1095        (setf (vop-parse-arg-types parse)
1096              (parse-operand-types (rest spec) t)))
1097       (:result-types
1098        (setf (vop-parse-result-types parse)
1099              (parse-operand-types (rest spec) nil)))
1100       (:translate
1101        (setf (vop-parse-translate parse) (rest spec)))
1102       (:guard
1103        (setf (vop-parse-guard parse) (vop-spec-arg spec t)))
1104       ;; FIXME: :LTN-POLICY would be a better name for this. It would
1105       ;; probably be good to leave it unchanged for a while, though,
1106       ;; at least until the first port to some other architecture,
1107       ;; since the renaming would be a change to the interface between
1108       (:policy
1109        (setf (vop-parse-ltn-policy parse)
1110              (vop-spec-arg spec 'ltn-policy)))
1111       (:save-p
1112        (setf (vop-parse-save-p parse)
1113              (vop-spec-arg spec
1114                            '(member t nil :compute-only :force-to-stack))))
1115       (t
1116        (error "unknown option specifier: ~S" (first spec)))))
1117   (values))
1118 \f
1119 ;;;; making costs and restrictions
1120
1121 ;;; Given an operand, returns two values:
1122 ;;; 1. A SC-vector of the cost for the operand being in that SC,
1123 ;;;    including both the costs for move functions and coercion VOPs.
1124 ;;; 2. A SC-vector holding the SC that we load into, for any SC
1125 ;;;    that we can directly load from.
1126 ;;;
1127 ;;; In both vectors, unused entries are NIL. LOAD-P specifies the
1128 ;;; direction: if true, we are loading, if false we are saving.
1129 (defun compute-loading-costs (op load-p)
1130   (declare (type operand-parse op))
1131   (let ((scs (operand-parse-scs op))
1132         (costs (make-array sc-number-limit :initial-element nil))
1133         (load-scs (make-array sc-number-limit :initial-element nil)))
1134     (dolist (sc-name scs)
1135       (let* ((load-sc (meta-sc-or-lose sc-name))
1136              (load-scn (sc-number load-sc)))
1137         (setf (svref costs load-scn) 0)
1138         (setf (svref load-scs load-scn) t)
1139         (dolist (op-sc (append (when load-p
1140                                  (sc-constant-scs load-sc))
1141                                (sc-alternate-scs load-sc)))
1142           (let* ((op-scn (sc-number op-sc))
1143                  (load (if load-p
1144                            (aref (sc-load-costs load-sc) op-scn)
1145                            (aref (sc-load-costs op-sc) load-scn))))
1146             (unless load
1147               (error "no move function defined to move ~:[from~;to~] SC ~
1148                       ~S~%~:[to~;from~] alternate or constant SC ~S"
1149                      load-p sc-name load-p (sc-name op-sc)))
1150
1151             (let ((op-cost (svref costs op-scn)))
1152               (when (or (not op-cost) (< load op-cost))
1153                 (setf (svref costs op-scn) load)))
1154
1155             (let ((op-load (svref load-scs op-scn)))
1156               (unless (eq op-load t)
1157                 (pushnew load-scn (svref load-scs op-scn))))))
1158
1159         (dotimes (i sc-number-limit)
1160           (unless (svref costs i)
1161             (let ((op-sc (svref *backend-meta-sc-numbers* i)))
1162               (when op-sc
1163                 (let ((cost (if load-p
1164                                 (svref (sc-move-costs load-sc) i)
1165                                 (svref (sc-move-costs op-sc) load-scn))))
1166                   (when cost
1167                     (setf (svref costs i) cost)))))))))
1168
1169     (values costs load-scs)))
1170
1171 (defparameter *no-costs*
1172   (make-array sc-number-limit :initial-element 0))
1173
1174 (defparameter *no-loads*
1175   (make-array sc-number-limit :initial-element 't))
1176
1177 ;;; Pick off the case of operands with no restrictions.
1178 (defun compute-loading-costs-if-any (op load-p)
1179   (declare (type operand-parse op))
1180   (if (operand-parse-scs op)
1181       (compute-loading-costs op load-p)
1182       (values *no-costs* *no-loads*)))
1183
1184 (defun compute-costs-and-restrictions-list (ops load-p)
1185   (declare (list ops))
1186   (collect ((costs)
1187             (scs))
1188     (dolist (op ops)
1189       (multiple-value-bind (costs scs) (compute-loading-costs-if-any op load-p)
1190         (costs costs)
1191         (scs scs)))
1192     (values (costs) (scs))))
1193
1194 (defun make-costs-and-restrictions (parse)
1195   (multiple-value-bind (arg-costs arg-scs)
1196       (compute-costs-and-restrictions-list (vop-parse-args parse) t)
1197     (multiple-value-bind (result-costs result-scs)
1198         (compute-costs-and-restrictions-list (vop-parse-results parse) nil)
1199       `(
1200         :cost ,(vop-parse-cost parse)
1201         
1202         :arg-costs ',arg-costs
1203         :arg-load-scs ',arg-scs
1204         :result-costs ',result-costs
1205         :result-load-scs ',result-scs
1206         
1207         :more-arg-costs
1208         ',(if (vop-parse-more-args parse)
1209               (compute-loading-costs-if-any (vop-parse-more-args parse) t)
1210               nil)
1211         
1212         :more-result-costs
1213         ',(if (vop-parse-more-results parse)
1214               (compute-loading-costs-if-any (vop-parse-more-results parse) nil)
1215               nil)))))
1216 \f
1217 ;;;; operand checking and stuff
1218
1219 ;;; Given a list of arg/result restrictions, check for valid syntax and
1220 ;;; convert to canonical form.
1221 (defun parse-operand-types (specs args-p)
1222   (declare (list specs))
1223   (labels ((parse-operand-type (spec)
1224              (cond ((eq spec '*) spec)
1225                    ((symbolp spec)
1226                     (let ((alias (gethash spec
1227                                           *backend-primitive-type-aliases*)))
1228                       (if alias
1229                           (parse-operand-type alias)
1230                           `(:or ,spec))))
1231                    ((atom spec)
1232                     (error "bad thing to be a operand type: ~S" spec))
1233                    (t
1234                     (case (first spec)
1235                       (:or
1236                        (collect ((results))
1237                          (results :or)
1238                          (dolist (item (cdr spec))
1239                            (unless (symbolp item)
1240                              (error "bad PRIMITIVE-TYPE name in ~S: ~S"
1241                                     spec item))
1242                            (let ((alias
1243                                   (gethash item
1244                                            *backend-primitive-type-aliases*)))
1245                              (if alias
1246                                  (let ((alias (parse-operand-type alias)))
1247                                    (unless (eq (car alias) :or)
1248                                      (error "can't include primitive-type ~
1249                                              alias ~S in an :OR restriction: ~S"
1250                                             item spec))
1251                                    (dolist (x (cdr alias))
1252                                      (results x)))
1253                                  (results item))))
1254                          (remove-duplicates (results)
1255                                             :test #'eq
1256                                             :start 1)))
1257                       (:constant
1258                        (unless args-p
1259                          (error "can't :CONSTANT for a result"))
1260                        (unless (= (length spec) 2)
1261                          (error "bad :CONSTANT argument type spec: ~S" spec))
1262                        spec)
1263                       (t
1264                        (error "bad thing to be a operand type: ~S" spec)))))))
1265     (mapcar #'parse-operand-type specs)))
1266
1267 ;;; Check the consistency of Op's Sc restrictions with the specified
1268 ;;; primitive-type restriction. :CONSTANT operands have already been
1269 ;;; filtered out, so only :OR and * restrictions are left.
1270 ;;;
1271 ;;; We check that every representation allowed by the type can be
1272 ;;; directly loaded into some SC in the restriction, and that the type
1273 ;;; allows every SC in the restriction. With *, we require that T
1274 ;;; satisfy the first test, and omit the second.
1275 (defun check-operand-type-scs (parse op type load-p)
1276   (declare (type vop-parse parse) (type operand-parse op))
1277   (let ((ptypes (if (eq type '*) (list 't) (rest type)))
1278         (scs (operand-parse-scs op)))
1279     (when scs
1280       (multiple-value-bind (costs load-scs) (compute-loading-costs op load-p)
1281         (declare (ignore costs))
1282         (dolist (ptype ptypes)
1283           (unless (dolist (rep (primitive-type-scs
1284                                 (meta-primitive-type-or-lose ptype))
1285                                nil)
1286                     (when (svref load-scs rep) (return t)))
1287             (error "In the ~A ~:[result~;argument~] to VOP ~S,~@
1288                     none of the SCs allowed by the operand type ~S can ~
1289                     directly be loaded~@
1290                     into any of the restriction's SCs:~%  ~S~:[~;~@
1291                     [* type operand must allow T's SCs.]~]"
1292                    (operand-parse-name op) load-p (vop-parse-name parse)
1293                    ptype
1294                    scs (eq type '*)))))
1295
1296       (dolist (sc scs)
1297         (unless (or (eq type '*)
1298                     (dolist (ptype ptypes nil)
1299                       (when (meta-sc-allowed-by-primitive-type
1300                              (meta-sc-or-lose sc)
1301                              (meta-primitive-type-or-lose ptype))
1302                         (return t))))
1303           (warn "~:[Result~;Argument~] ~A to VOP ~S~@
1304                  has SC restriction ~S which is ~
1305                  not allowed by the operand type:~%  ~S"
1306                 load-p (operand-parse-name op) (vop-parse-name parse)
1307                 sc type)))))
1308
1309   (values))
1310
1311 ;;; If the operand types are specified, then check the number specified
1312 ;;; against the number of defined operands.
1313 (defun check-operand-types (parse ops more-op types load-p)
1314   (declare (type vop-parse parse) (list ops)
1315            (type (or list (member :unspecified)) types)
1316            (type (or operand-parse null) more-op))
1317   (unless (eq types :unspecified)
1318     (let ((num (+ (length ops) (if more-op 1 0))))
1319       (unless (= (count-if-not #'(lambda (x)
1320                                    (and (consp x)
1321                                         (eq (car x) :constant)))
1322                                types)
1323                  num)
1324         (error "expected ~D ~:[result~;argument~] type~P: ~S"
1325                num load-p types num)))
1326
1327     (when more-op
1328       (let ((mtype (car (last types))))
1329         (when (and (consp mtype) (eq (first mtype) :constant))
1330           (error "can't use :CONSTANT on VOP more args")))))
1331
1332   (when (vop-parse-translate parse)
1333     (let ((types (specify-operand-types types ops more-op)))
1334       (mapc #'(lambda (x y)
1335                 (check-operand-type-scs parse x y load-p))
1336             (if more-op (butlast ops) ops)
1337             (remove-if #'(lambda (x)
1338                            (and (consp x)
1339                                 (eq (car x) ':constant)))
1340                        (if more-op (butlast types) types)))))
1341
1342   (values))
1343
1344 ;;; Compute stuff that can only be computed after we are done parsing
1345 ;;; everying. We set the VOP-Parse-Operands, and do various error checks.
1346 (defun grovel-operands (parse)
1347   (declare (type vop-parse parse))
1348
1349   (setf (vop-parse-operands parse)
1350         (append (vop-parse-args parse)
1351                 (if (vop-parse-more-args parse)
1352                     (list (vop-parse-more-args parse)))
1353                 (vop-parse-results parse)
1354                 (if (vop-parse-more-results parse)
1355                     (list (vop-parse-more-results parse)))
1356                 (vop-parse-temps parse)))
1357
1358   (check-operand-types parse
1359                        (vop-parse-args parse)
1360                        (vop-parse-more-args parse)
1361                        (vop-parse-arg-types parse)
1362                        t)
1363
1364   (check-operand-types parse
1365                        (vop-parse-results parse)
1366                        (vop-parse-more-results parse)
1367                        (vop-parse-result-types parse)
1368                        nil)
1369
1370   (values))
1371 \f
1372 ;;;; function translation stuff
1373
1374 ;;; Return forms to establish this VOP as a IR2 translation template
1375 ;;; for the :TRANSLATE functions specified in the VOP-Parse. We also
1376 ;;; set the Predicate attribute for each translated function when the
1377 ;;; VOP is conditional, causing IR1 conversion to ensure that a call
1378 ;;; to the translated is always used in a predicate position.
1379 (defun set-up-function-translation (parse n-template)
1380   (declare (type vop-parse parse))
1381   (mapcar #'(lambda (name)
1382               `(let ((info (function-info-or-lose ',name)))
1383                  (setf (function-info-templates info)
1384                        (adjoin-template ,n-template
1385                                         (function-info-templates info)))
1386                  ,@(when (vop-parse-conditional-p parse)
1387                      '((setf (function-info-attributes info)
1388                              (attributes-union
1389                               (ir1-attributes predicate)
1390                               (function-info-attributes info)))))))
1391           (vop-parse-translate parse)))
1392
1393 ;;; Return a form that can be evaluated to get the TEMPLATE operand type
1394 ;;; restriction from the given specification.
1395 (defun make-operand-type (type)
1396   (cond ((eq type '*) ''*)
1397         ((symbolp type)
1398          ``(:or ,(primitive-type-or-lose ',type)))
1399         (t
1400          (ecase (first type)
1401            (:or
1402             ``(:or ,,@(mapcar #'(lambda (type)
1403                                    `(primitive-type-or-lose ',type))
1404                                (rest type))))
1405            (:constant
1406             ``(:constant ,#'(lambda (x)
1407                               (typep x ',(second type)))
1408                          ,',(second type)))))))
1409
1410 (defun specify-operand-types (types ops more-ops)
1411   (if (eq types :unspecified)
1412       (make-list (+ (length ops) (if more-ops 1 0)) :initial-element '*)
1413       types))
1414
1415 ;;; Return a list of forms to use as &KEY args to MAKE-VOP-INFO for
1416 ;;; setting up the template argument and result types. Here we make an
1417 ;;; initial dummy TEMPLATE-TYPE, since it is awkward to compute the
1418 ;;; type until the template has been made.
1419 (defun make-vop-info-types (parse)
1420   (let* ((more-args (vop-parse-more-args parse))
1421          (all-args (specify-operand-types (vop-parse-arg-types parse)
1422                                           (vop-parse-args parse)
1423                                           more-args))
1424          (args (if more-args (butlast all-args) all-args))
1425          (more-arg (when more-args (car (last all-args))))
1426          (more-results (vop-parse-more-results parse))
1427          (all-results (specify-operand-types (vop-parse-result-types parse)
1428                                              (vop-parse-results parse)
1429                                              more-results))
1430          (results (if more-results (butlast all-results) all-results))
1431          (more-result (when more-results (car (last all-results))))
1432          (conditional (vop-parse-conditional-p parse)))
1433
1434     `(
1435       :type (specifier-type '(function () nil))
1436       :arg-types (list ,@(mapcar #'make-operand-type args))
1437       :more-args-type ,(when more-args (make-operand-type more-arg))
1438       :result-types ,(if conditional
1439                          :conditional
1440                          `(list ,@(mapcar #'make-operand-type results)))
1441       :more-results-type ,(when more-results
1442                             (make-operand-type more-result)))))
1443 \f
1444 ;;;; setting up VOP-INFO
1445
1446 (eval-when (:compile-toplevel :load-toplevel :execute)
1447   (defparameter *slot-inherit-alist*
1448     '((:generator-function . vop-info-generator-function))))
1449
1450 ;;; Something to help with inheriting VOP-Info slots. We return a
1451 ;;; keyword/value pair that can be passed to the constructor. SLOT is
1452 ;;; the keyword name of the slot, Parse is a form that evaluates to
1453 ;;; the VOP-Parse structure for the VOP inherited. If PARSE is NIL,
1454 ;;; then we do nothing. If the TEST form evaluates to true, then we
1455 ;;; return a form that selects the named slot from the VOP-Info
1456 ;;; structure corresponding to PARSE. Otherwise, we return the FORM so
1457 ;;; that the slot is recomputed.
1458 (defmacro inherit-vop-info (slot parse test form)
1459   `(if (and ,parse ,test)
1460        (list ,slot `(,',(or (cdr (assoc slot *slot-inherit-alist*))
1461                             (error "unknown slot ~S" slot))
1462                      (template-or-lose ',(vop-parse-name ,parse))))
1463        (list ,slot ,form)))
1464
1465 ;;; Return a form that creates a VOP-Info structure which describes VOP.
1466 (defun set-up-vop-info (iparse parse)
1467   (declare (type vop-parse parse) (type (or vop-parse null) iparse))
1468   (let ((same-operands
1469          (and iparse
1470               (equal (vop-parse-operands parse)
1471                      (vop-parse-operands iparse))
1472               (equal (vop-parse-info-args iparse)
1473                      (vop-parse-info-args parse))))
1474         (variant (vop-parse-variant parse)))
1475
1476     (let ((nvars (length (vop-parse-variant-vars parse))))
1477       (unless (= (length variant) nvars)
1478         (error "expected ~D variant values: ~S" nvars variant)))
1479
1480     `(make-vop-info
1481       :name ',(vop-parse-name parse)
1482       ,@(make-vop-info-types parse)
1483       :guard ,(when (vop-parse-guard parse)
1484                 `#'(lambda () ,(vop-parse-guard parse)))
1485       :note ',(vop-parse-note parse)
1486       :info-arg-count ,(length (vop-parse-info-args parse))
1487       :ltn-policy ',(vop-parse-ltn-policy parse)
1488       :save-p ',(vop-parse-save-p parse)
1489       :move-args ',(vop-parse-move-args parse)
1490       :effects (vop-attributes ,@(vop-parse-effects parse))
1491       :affected (vop-attributes ,@(vop-parse-affected parse))
1492       ,@(make-costs-and-restrictions parse)
1493       ,@(make-emit-function-and-friends parse)
1494       ,@(inherit-vop-info :generator-function iparse
1495           (and same-operands
1496                (equal (vop-parse-body parse) (vop-parse-body iparse)))
1497           (unless (eq (vop-parse-body parse) :unspecified)
1498             (make-generator-function parse)))
1499       :variant (list ,@variant))))
1500 \f
1501 ;;; Define the symbol NAME to be a Virtual OPeration in the compiler. If
1502 ;;; specified, INHERITS is the name of a VOP that we default unspecified
1503 ;;; information from. Each SPEC is a list beginning with a keyword indicating
1504 ;;; the interpretation of the other forms in the SPEC:
1505 ;;;
1506 ;;; :Args {(Name {Key Value}*)}*
1507 ;;; :Results {(Name {Key Value}*)}*
1508 ;;;     The Args and Results are specifications of the operand TNs passed
1509 ;;;     to the VOP. If there is an inherited VOP, any unspecified options
1510 ;;;     are defaulted from the inherited argument (or result) of the same
1511 ;;;     name. The following operand options are defined:
1512 ;;;
1513 ;;; :SCs (SC*)
1514 ;;;     :SCs specifies good SCs for this operand. Other SCs will be
1515 ;;;     penalized according to move costs. A load TN will be allocated if
1516 ;;;     necessary, guaranteeing that the operand is always one of the
1517 ;;;     specified SCs.
1518 ;;;
1519 ;;;     :Load-TN Load-Name
1520 ;;;         Load-Name is bound to the load TN allocated for this operand, 
1521 ;;;         or to NIL if no load TN was allocated.
1522 ;;;
1523 ;;;     :Load-If EXPRESSION
1524 ;;;         Controls whether automatic operand loading is done.
1525 ;;;         EXPRESSION is evaluated with the fixed operand TNs bound.
1526 ;;;         If EXPRESSION is true,then loading is done and the variable
1527 ;;;         is bound to the load TN in the generator body. Otherwise,
1528 ;;;         loading is not done, and the variable is bound to the actual
1529 ;;;         operand.
1530 ;;;
1531 ;;;     :More T-or-NIL
1532 ;;;         If specified, Name is bound to the TN-Ref for the first
1533 ;;;         argument or result following the fixed arguments or results.
1534 ;;;         A :MORE operand must appear last, and cannot be targeted or
1535 ;;;         restricted.
1536 ;;;
1537 ;;;     :Target Operand
1538 ;;;         This operand is targeted to the named operand, indicating a
1539 ;;;         desire to pack in the same location. Not legal for results.
1540 ;;;
1541 ;;;     :From Time-Spec
1542 ;;;     :To Time-Spec
1543 ;;;         Specify the beginning or end of the operand's lifetime.
1544 ;;;         :FROM can only be used with results, and :TO only with
1545 ;;;         arguments. The default for the N'th argument/result is
1546 ;;;         (:ARGUMENT N)/(:RESULT N). These options are necessary
1547 ;;;         primarily when operands are read or written out of order.
1548 ;;;
1549 ;;; :Conditional
1550 ;;;     This is used in place of :RESULTS with conditional branch VOPs.
1551 ;;;     There are no result values: the result is a transfer of control.
1552 ;;;     The target label is passed as the first :INFO arg. The second
1553 ;;;     :INFO arg is true if the sense of the test should be negated.
1554 ;;;     A side-effect is to set the PREDICATE attribute for functions
1555 ;;;     in the :TRANSLATE option.
1556 ;;;
1557 ;;; :Temporary ({Key Value}*) Name*
1558 ;;;     Allocate a temporary TN for each Name, binding that variable to
1559 ;;;     the TN within the body of the generators. In addition to :TARGET
1560 ;;;     (which is is the same as for operands), the following options are
1561 ;;;     defined:
1562 ;;;
1563 ;;;     :SC SC-Name
1564 ;;;     :Offset SB-Offset
1565 ;;;         Force the temporary to be allocated in the specified SC with the
1566 ;;;         specified offset. Offset is evaluated at macroexpand time. If
1567 ;;;         Offset is emitted, the register allocator chooses a free
1568 ;;;         location in SC. If both SC and Offset are omitted, then the
1569 ;;;         temporary is packed according to its primitive type.
1570 ;;;
1571 ;;;     :From Time-Spec
1572 ;;;     :To Time-Spec
1573 ;;;         Similar to the argument/result option, this specifies the start and
1574 ;;;         end of the temporaries' lives. The defaults are :Load and :Save,
1575 ;;;         i.e. the duration of the VOP. The other intervening phases are
1576 ;;;         :Argument,:Eval and :Result. Non-zero sub-phases can be specified
1577 ;;;         by a list, e.g. by default the second argument's life ends at
1578 ;;;         (:Argument 1).
1579 ;;;
1580 ;;; :Generator Cost Form*
1581 ;;;     Specifies the translation into assembly code. Cost is the
1582 ;;;     estimated cost of the code emitted by this generator. The body
1583 ;;;     is arbitrary Lisp code that emits the assembly language
1584 ;;;     translation of the VOP. An ASSEMBLE form is wrapped around
1585 ;;;     the body, so code may be emitted by using the local INST macro.
1586 ;;;     During the evaluation of the body, the names of the operands
1587 ;;;     and temporaries are bound to the actual TNs.
1588 ;;;
1589 ;;; :Effects Effect*
1590 ;;; :Affected Effect*
1591 ;;;     Specifies the side effects that this VOP has and the side
1592 ;;;     effects that effect its execution. If unspecified, these
1593 ;;;     default to the worst case.
1594 ;;;
1595 ;;; :Info Name*
1596 ;;;     Define some magic arguments that are passed directly to the code
1597 ;;;     generator. The corresponding trailing arguments to VOP or
1598 ;;;     %PRIMITIVE are stored in the VOP structure. Within the body
1599 ;;;     of the generators, the named variables are bound to these
1600 ;;;     values. Except in the case of :Conditional VOPs, :Info arguments
1601 ;;;     cannot be specified for VOPS that are the direct translation
1602 ;;;     for a function (specified by :Translate).
1603 ;;;
1604 ;;; :Ignore Name*
1605 ;;;     Causes the named variables to be declared IGNORE in the
1606 ;;;     generator body.
1607 ;;;
1608 ;;; :Variant Thing*
1609 ;;; :Variant-Vars Name*
1610 ;;;     These options provide a way to parameterize families of VOPs
1611 ;;;     that differ only trivially. :Variant makes the specified
1612 ;;;     evaluated Things be the "variant" associated with this VOP.
1613 ;;;     :VARIANT-VARS causes the named variables to be bound to the
1614 ;;;     corresponding Things within the body of the generator.
1615 ;;;
1616 ;;; :Variant-Cost Cost
1617 ;;;     Specifies the cost of this VOP, overriding the cost of any 
1618 ;;;     inherited generator.
1619 ;;;
1620 ;;; :Note {String | NIL}
1621 ;;;     A short noun-like phrase describing what this VOP "does", i.e.
1622 ;;;     the implementation strategy. If supplied, efficency notes will
1623 ;;;     be generated when type uncertainty prevents :TRANSLATE from
1624 ;;;     working. NIL inhibits any efficency note.
1625 ;;;
1626 ;;; :Arg-Types    {* | PType | (:OR PType*) | (:CONSTANT Type)}*
1627 ;;; :Result-Types {* | PType | (:OR PType*)}*
1628 ;;;     Specify the template type restrictions used for automatic translation.
1629 ;;;     If there is a :More operand, the last type is the more type. :CONSTANT
1630 ;;;     specifies that the argument must be a compile-time constant of the
1631 ;;;     specified Lisp type. The constant values of :CONSTANT arguments are
1632 ;;;     passed as additional :INFO arguments rather than as :ARGS.
1633 ;;;
1634 ;;; :Translate Name*
1635 ;;;     This option causes the VOP template to be entered as an IR2
1636 ;;;     translation for the named functions.
1637 ;;;
1638 ;;; :Policy {:Small | :Fast | :Safe | :Fast-Safe}
1639 ;;;     Specifies the policy under which this VOP is the best translation.
1640 ;;;
1641 ;;; :Guard Form
1642 ;;;     Specifies a Form that is evaluated in the global environment. If
1643 ;;;     form returns NIL, then emission of this VOP is prohibited even when
1644 ;;;     all other restrictions are met.
1645 ;;;
1646 ;;; :VOP-Var Name
1647 ;;; :Node-Var Name
1648 ;;;     In the generator, bind the specified variable to the VOP or
1649 ;;;     the Node that generated this VOP.
1650 ;;;
1651 ;;; :Save-P {NIL | T | :Compute-Only | :Force-To-Stack}
1652 ;;;     Indicates how a VOP wants live registers saved.
1653 ;;;
1654 ;;; :Move-Args {NIL | :Full-Call | :Local-Call | :Known-Return}
1655 ;;;     Indicates if and how the more args should be moved into a
1656 ;;;     different frame.
1657 (def!macro define-vop ((name &optional inherits) &rest specs)
1658   ;; Parse the syntax into a VOP-PARSE structure, and then expand into
1659   ;; code that creates the appropriate VOP-INFO structure at load time.
1660   ;; We implement inheritance by copying the VOP-PARSE structure for
1661   ;; the inherited structure.
1662   (check-type name symbol)
1663   (let* ((inherited-parse (when inherits
1664                             (vop-parse-or-lose inherits)))
1665          (parse (if inherits
1666                     (copy-vop-parse inherited-parse)
1667                     (make-vop-parse)))
1668          (n-res (gensym)))
1669     (setf (vop-parse-name parse) name)
1670     (setf (vop-parse-inherits parse) inherits)
1671
1672     (parse-define-vop parse specs)
1673     (grovel-operands parse)
1674
1675     `(progn
1676        (eval-when (:compile-toplevel :load-toplevel :execute)
1677          (setf (gethash ',name *backend-parsed-vops*)
1678                ',parse))
1679
1680        (let ((,n-res ,(set-up-vop-info inherited-parse parse)))
1681          (setf (gethash ',name *backend-template-names*) ,n-res)
1682          (setf (template-type ,n-res)
1683                (specifier-type (template-type-specifier ,n-res)))
1684          ,@(set-up-function-translation parse n-res))
1685        ',name)))
1686 \f
1687 ;;;; emission macros
1688
1689 ;;; Return code to make a list of VOP arguments or results, linked by
1690 ;;; TN-Ref-Across. The first value is code, the second value is LET*
1691 ;;; forms, and the third value is a variable that evaluates to the
1692 ;;; head of the list, or NIL if there are no operands. Fixed is a list
1693 ;;; of forms that evaluate to TNs for the fixed operands. TN-Refs will
1694 ;;; be made for these operands according using the specified value of
1695 ;;; Write-P. More is an expression that evaluates to a list of TN-Refs
1696 ;;; that will be made the tail of the list. If it is constant NIL,
1697 ;;; then we don't bother to set the tail.
1698 (defun make-operand-list (fixed more write-p)
1699   (collect ((forms)
1700             (binds))
1701     (let ((n-head nil)
1702           (n-prev nil))
1703       (dolist (op fixed)
1704         (let ((n-ref (gensym)))
1705           (binds `(,n-ref (reference-tn ,op ,write-p)))
1706           (if n-prev
1707               (forms `(setf (tn-ref-across ,n-prev) ,n-ref))
1708               (setq n-head n-ref))
1709           (setq n-prev n-ref)))
1710
1711       (when more
1712         (let ((n-more (gensym)))
1713           (binds `(,n-more ,more))
1714           (if n-prev
1715               (forms `(setf (tn-ref-across ,n-prev) ,n-more))
1716               (setq n-head n-more))))
1717
1718       (values (forms) (binds) n-head))))
1719
1720 (defmacro emit-template (node block template args results &optional info)
1721   #!+sb-doc
1722   "Emit-Template Node Block Template Args Results [Info]
1723   Call the emit function for Template, linking the result in at the end of
1724   Block."
1725   (let ((n-first (gensym))
1726         (n-last (gensym)))
1727     (once-only ((n-node node)
1728                 (n-block block)
1729                 (n-template template))
1730       `(multiple-value-bind (,n-first ,n-last)
1731            (funcall (template-emit-function ,n-template)
1732                     ,n-node ,n-block ,n-template ,args ,results
1733                     ,@(when info `(,info)))
1734          (insert-vop-sequence ,n-first ,n-last ,n-block nil)))))
1735
1736 (defmacro vop (name node block &rest operands)
1737   #!+sb-doc
1738   "VOP Name Node Block Arg* Info* Result*
1739   Emit the VOP (or other template) Name at the end of the IR2-Block Block,
1740   using Node for the source context. The interpretation of the remaining
1741   arguments depends on the number of operands of various kinds that are
1742   declared in the template definition. VOP cannot be used for templates that
1743   have more-args or more-results, since the number of arguments and results is
1744   indeterminate for these templates. Use VOP* instead.
1745
1746   Args and Results are the TNs that are to be referenced by the template
1747   as arguments and results. If the template has codegen-info arguments, then
1748   the appropriate number of Info forms following the Arguments are used for
1749   codegen info."
1750   (let* ((parse (vop-parse-or-lose name))
1751          (arg-count (length (vop-parse-args parse)))
1752          (result-count (length (vop-parse-results parse)))
1753          (info-count (length (vop-parse-info-args parse)))
1754          (noperands (+ arg-count result-count info-count))
1755          (n-node (gensym))
1756          (n-block (gensym))
1757          (n-template (gensym)))
1758
1759     (when (or (vop-parse-more-args parse) (vop-parse-more-results parse))
1760       (error "cannot use VOP with variable operand count templates"))
1761     (unless (= noperands (length operands))
1762       (error "called with ~D operands, but was expecting ~D"
1763              (length operands) noperands))
1764
1765     (multiple-value-bind (acode abinds n-args)
1766         (make-operand-list (subseq operands 0 arg-count) nil nil)
1767       (multiple-value-bind (rcode rbinds n-results)
1768           (make-operand-list (subseq operands (+ arg-count info-count)) nil t)
1769         
1770         (collect ((ibinds)
1771                   (ivars))
1772           (dolist (info (subseq operands arg-count (+ arg-count info-count)))
1773             (let ((temp (gensym)))
1774               (ibinds `(,temp ,info))
1775               (ivars temp)))
1776
1777           `(let* ((,n-node ,node)
1778                   (,n-block ,block)
1779                   (,n-template (template-or-lose ',name))
1780                   ,@abinds
1781                   ,@(ibinds)
1782                   ,@rbinds)
1783              ,@acode
1784              ,@rcode
1785              (emit-template ,n-node ,n-block ,n-template ,n-args
1786                             ,n-results
1787                             ,@(when (ivars)
1788                                 `((list ,@(ivars)))))
1789              (values)))))))
1790
1791 (defmacro vop* (name node block args results &rest info)
1792   #!+sb-doc
1793   "VOP* Name Node Block (Arg* More-Args) (Result* More-Results) Info*
1794   Like VOP, but allows for emission of templates with arbitrary numbers of
1795   arguments, and for emission of templates using already-created TN-Ref lists.
1796
1797   The Arguments and Results are TNs to be referenced as the first arguments
1798   and results to the template. More-Args and More-Results are heads of TN-Ref
1799   lists that are added onto the end of the TN-Refs for the explicitly supplied
1800   operand TNs. The TN-Refs for the more operands must have the TN and Write-P
1801   slots correctly initialized.
1802
1803   As with VOP, the Info forms are evaluated and passed as codegen info
1804   arguments."
1805   (check-type args cons)
1806   (check-type results cons)
1807   (let* ((parse (vop-parse-or-lose name))
1808          (arg-count (length (vop-parse-args parse)))
1809          (result-count (length (vop-parse-results parse)))
1810          (info-count (length (vop-parse-info-args parse)))
1811          (fixed-args (butlast args))
1812          (fixed-results (butlast results))
1813          (n-node (gensym))
1814          (n-block (gensym))
1815          (n-template (gensym)))
1816
1817     (unless (or (vop-parse-more-args parse)
1818                 (<= (length fixed-args) arg-count))
1819       (error "too many fixed arguments"))
1820     (unless (or (vop-parse-more-results parse)
1821                 (<= (length fixed-results) result-count))
1822       (error "too many fixed results"))
1823     (unless (= (length info) info-count)
1824       (error "expected ~D info args" info-count))
1825
1826     (multiple-value-bind (acode abinds n-args)
1827         (make-operand-list fixed-args (car (last args)) nil)
1828       (multiple-value-bind (rcode rbinds n-results)
1829           (make-operand-list fixed-results (car (last results)) t)
1830         
1831         `(let* ((,n-node ,node)
1832                 (,n-block ,block)
1833                 (,n-template (template-or-lose ',name))
1834                 ,@abinds
1835                 ,@rbinds)
1836            ,@acode
1837            ,@rcode
1838            (emit-template ,n-node ,n-block ,n-template ,n-args ,n-results
1839                           ,@(when info
1840                               `((list ,@info))))
1841            (values))))))
1842 \f
1843 ;;;; miscellaneous macros
1844
1845 (def!macro sc-case (tn &rest forms)
1846   #!+sb-doc
1847   "SC-Case TN {({(SC-Name*) | SC-Name | T} Form*)}*
1848   Case off of TN's SC. The first clause containing TN's SC is evaluated,
1849   returning the values of the last form. A clause beginning with T specifies a
1850   default. If it appears, it must be last. If no default is specified, and no
1851   clause matches, then an error is signalled."
1852   (let ((n-sc (gensym))
1853         (n-tn (gensym)))
1854     (collect ((clauses))
1855       (do ((cases forms (rest cases)))
1856           ((null cases)
1857            (clauses `(t (error "unknown SC to SC-Case for ~S:~%  ~S" ,n-tn
1858                                (sc-name (tn-sc ,n-tn))))))
1859         (let ((case (first cases)))
1860           (when (atom case)
1861             (error "illegal SC-Case clause: ~S" case))
1862           (let ((head (first case)))
1863             (when (eq head t)
1864               (when (rest cases)
1865                 (error "T case is not last in SC-Case."))
1866               (clauses `(t nil ,@(rest case)))
1867               (return))
1868             (clauses `((or ,@(mapcar #'(lambda (x)
1869                                          `(eql ,(meta-sc-number-or-lose x)
1870                                                ,n-sc))
1871                                      (if (atom head) (list head) head)))
1872                        nil ,@(rest case))))))
1873
1874       `(let* ((,n-tn ,tn)
1875               (,n-sc (sc-number (tn-sc ,n-tn))))
1876          (cond ,@(clauses))))))
1877
1878 (defmacro sc-is (tn &rest scs)
1879   #!+sb-doc
1880   "SC-Is TN SC*
1881   Returns true if TNs SC is any of the named SCs, false otherwise."
1882   (once-only ((n-sc `(sc-number (tn-sc ,tn))))
1883     `(or ,@(mapcar #'(lambda (x)
1884                        `(eql ,n-sc ,(meta-sc-number-or-lose x)))
1885                    scs))))
1886
1887 (defmacro do-ir2-blocks ((block-var component &optional result)
1888                          &body forms)
1889   #!+sb-doc
1890   "Do-IR2-Blocks (Block-Var Component [Result]) Form*
1891   Iterate over the IR2 blocks in component, in emission order."
1892   `(do ((,block-var (block-info (component-head ,component))
1893                     (ir2-block-next ,block-var)))
1894        ((null ,block-var) ,result)
1895      ,@forms))
1896
1897 (defmacro do-live-tns ((tn-var live block &optional result) &body body)
1898   #!+sb-doc
1899   "DO-LIVE-TNS (TN-Var Live Block [Result]) Form*
1900   Iterate over all the TNs live at some point, with the live set represented by
1901   a local conflicts bit-vector and the IR2-Block containing the location."
1902   (let ((n-conf (gensym))
1903         (n-bod (gensym))
1904         (i (gensym))
1905         (ltns (gensym)))
1906     (once-only ((n-live live)
1907                 (n-block block))
1908       `(block nil
1909          (flet ((,n-bod (,tn-var) ,@body))
1910            ;; Do component-live TNs.
1911            (dolist (,tn-var (ir2-component-component-tns
1912                              (component-info
1913                               (block-component
1914                                (ir2-block-block ,n-block)))))
1915              (,n-bod ,tn-var))
1916
1917            (let ((,ltns (ir2-block-local-tns ,n-block)))
1918              ;; Do TNs always-live in this block and live :More TNs.
1919              (do ((,n-conf (ir2-block-global-tns ,n-block)
1920                            (global-conflicts-next ,n-conf)))
1921                  ((null ,n-conf))
1922                (when (or (eq (global-conflicts-kind ,n-conf) :live)
1923                          (let ((,i (global-conflicts-number ,n-conf)))
1924                            (and (eq (svref ,ltns ,i) :more)
1925                                 (not (zerop (sbit ,n-live ,i))))))
1926                  (,n-bod (global-conflicts-tn ,n-conf))))
1927              ;; Do TNs locally live in the designated live set.
1928              (dotimes (,i (ir2-block-local-tn-count ,n-block) ,result)
1929                (unless (zerop (sbit ,n-live ,i))
1930                  (let ((,tn-var (svref ,ltns ,i)))
1931                    (when (and ,tn-var (not (eq ,tn-var :more)))
1932                      (,n-bod ,tn-var)))))))))))
1933
1934 (defmacro do-environment-ir2-blocks ((block-var env &optional result)
1935                                      &body body)
1936   #!+sb-doc
1937   "DO-ENVIRONMENT-IR2-BLOCKS (Block-Var Env [Result]) Form*
1938   Iterate over all the IR2 blocks in the environment Env, in emit order."
1939   (once-only ((n-env env))
1940     (once-only ((n-first `(node-block
1941                            (lambda-bind
1942                             (environment-function ,n-env)))))
1943       (once-only ((n-tail `(block-info
1944                             (component-tail
1945                              (block-component ,n-first)))))
1946         `(do ((,block-var (block-info ,n-first)
1947                           (ir2-block-next ,block-var)))
1948              ((or (eq ,block-var ,n-tail)
1949                   (not (eq (ir2-block-environment ,block-var) ,n-env)))
1950               ,result)
1951            ,@body)))))