-;;; Parse the syntax into a VOP-Parse structure, and then expand into code
-;;; that creates the appropriate VOP-Info structure at load time. We implement
-;;; inheritance by copying the VOP-Parse structure for the inherited structure.
-(def!macro define-vop ((name &optional inherits) &rest specs)
- #!+sb-doc
- "Define-VOP (Name [Inherits]) Spec*
- Define the symbol Name to be a Virtual OPeration in the compiler. If
- specified, Inherits is the name of a VOP that we default unspecified
- information from. Each Spec is a list beginning with a keyword indicating
- the interpretation of the other forms in the Spec:
-
- :Args {(Name {Key Value}*)}*
- :Results {(Name {Key Value}*)}*
- The Args and Results are specifications of the operand TNs passed to the
- VOP. If there is an inherited VOP, any unspecified options are defaulted
- from the inherited argument (or result) of the same name. The following
- operand options are defined:
-
- :SCs (SC*)
- :SCs specifies good SCs for this operand. Other SCs will be
- penalized according to move costs. A load TN will be allocated if
- necessary, guaranteeing that the operand is always one of the
- specified SCs.
-
- :Load-TN Load-Name
- Load-Name is bound to the load TN allocated for this operand, or to
- NIL if no load TN was allocated.
-
- :Load-If Expression
- Controls whether automatic operand loading is done. Expression is
- evaluated with the fixed operand TNs bound. If Expression is true,
- then loading is done and the variable is bound to the load TN in
- the generator body. Otherwise, loading is not done, and the variable
- is bound to the actual operand.
-
- :More T-or-NIL
- If specified, Name is bound to the TN-Ref for the first argument or
- result following the fixed arguments or results. A more operand must
- appear last, and cannot be targeted or restricted.
-
- :Target Operand
- This operand is targeted to the named operand, indicating a desire to
- pack in the same location. Not legal for results.
-
- :From Time-Spec
- :To Time-Spec
- Specify the beginning or end of the operand's lifetime. :From can
- only be used with results, and :To only with arguments. The default
- for the N'th argument/result is (:ARGUMENT N)/(:RESULT N). These
- options are necessary primarily when operands are read or written out
- of order.
-
- :Conditional
- This is used in place of :RESULTS with conditional branch VOPs. There
- are no result values: the result is a transfer of control. The target
- label is passed as the first :INFO arg. The second :INFO arg is true if
- the sense of the test should be negated. A side-effect is to set the
- PREDICATE attribute for functions in the :TRANSLATE option.
-
- :Temporary ({Key Value}*) Name*
- Allocate a temporary TN for each Name, binding that variable to the TN
- within the body of the generators. In addition to :Target (which is
- is the same as for operands), the following options are
- defined:
-
- :SC SC-Name
- :Offset SB-Offset
- Force the temporary to be allocated in the specified SC with the
- specified offset. Offset is evaluated at macroexpand time. If
- Offset is emitted, the register allocator chooses a free location in
- SC. If both SC and Offset are omitted, then the temporary is packed
- according to its primitive type.
-
- :From Time-Spec
- :To Time-Spec
- Similar to the argument/result option, this specifies the start and
- end of the temporaries' lives. The defaults are :Load and :Save,
- i.e. the duration of the VOP. The other intervening phases are
- :Argument,:Eval and :Result. Non-zero sub-phases can be specified
- by a list, e.g. by default the second argument's life ends at
- (:Argument 1).
-
- :Generator Cost Form*
- Specifies the translation into assembly code. Cost is the estimated cost
- of the code emitted by this generator. The body is arbitrary Lisp code
- that emits the assembly language translation of the VOP. An Assemble
- form is wrapped around the body, so code may be emitted by using the
- local Inst macro. During the evaluation of the body, the names of the
- operands and temporaries are bound to the actual TNs.
-
- :Effects Effect*
- :Affected Effect*
- Specifies the side effects that this VOP has and the side effects that
- effect its execution. If unspecified, these default to the worst case.
-
- :Info Name*
- Define some magic arguments that are passed directly to the code
- generator. The corresponding trailing arguments to VOP or %Primitive are
- stored in the VOP structure. Within the body of the generators, the
- named variables are bound to these values. Except in the case of
- :Conditional VOPs, :Info arguments cannot be specified for VOPS that are
- the direct translation for a function (specified by :Translate).
-
- :Ignore Name*
- Causes the named variables to be declared IGNORE in the generator body.
-
- :Variant Thing*
- :Variant-Vars Name*
- These options provide a way to parameterize families of VOPs that differ
- only trivially. :Variant makes the specified evaluated Things be the
- \"variant\" associated with this VOP. :Variant-Vars causes the named
- variables to be bound to the corresponding Things within the body of the
- generator.
-
- :Variant-Cost Cost
- Specifies the cost of this VOP, overriding the cost of any inherited
- generator.
-
- :Note {String | NIL}
- A short noun-like phrase describing what this VOP \"does\", i.e. the
- implementation strategy. If supplied, efficency notes will be generated
- when type uncertainty prevents :TRANSLATE from working. NIL inhibits any
- efficency note.
-
- :Arg-Types {* | PType | (:OR PType*) | (:CONSTANT Type)}*
- :Result-Types {* | PType | (:OR PType*)}*
- Specify the template type restrictions used for automatic translation.
- If there is a :More operand, the last type is the more type. :CONSTANT
- specifies that the argument must be a compile-time constant of the
- specified Lisp type. The constant values of :CONSTANT arguments are
- passed as additional :INFO arguments rather than as :ARGS.
-
- :Translate Name*
- This option causes the VOP template to be entered as an IR2 translation
- for the named functions.
-
- :Policy {:Small | :Fast | :Safe | :Fast-Safe}
- Specifies the policy under which this VOP is the best translation.
-
- :Guard Form
- Specifies a Form that is evaluated in the global environment. If
- form returns NIL, then emission of this VOP is prohibited even when
- all other restrictions are met.
-
- :VOP-Var Name
- :Node-Var Name
- In the generator, bind the specified variable to the VOP or the Node that
- generated this VOP.
-
- :Save-P {NIL | T | :Compute-Only | :Force-To-Stack}
- Indicates how a VOP wants live registers saved.
-
- :Move-Args {NIL | :Full-Call | :Local-Call | :Known-Return}
- Indicates if and how the more args should be moved into a different
- frame."
- (check-type name symbol)
-
- (let* ((iparse (when inherits
- (vop-parse-or-lose inherits)))
- (parse (if inherits
- (copy-vop-parse iparse)
- (make-vop-parse)))
- (n-res (gensym)))
+;;; Define the symbol NAME to be a Virtual OPeration in the compiler.
+;;; If specified, INHERITS is the name of a VOP that we default
+;;; unspecified information from. Each SPEC is a list beginning with a
+;;; keyword indicating the interpretation of the other forms in the
+;;; SPEC:
+;;;
+;;; :ARGS {(Name {Key Value}*)}*
+;;; :RESULTS {(Name {Key Value}*)}*
+;;; The Args and Results are specifications of the operand TNs passed
+;;; to the VOP. If there is an inherited VOP, any unspecified options
+;;; are defaulted from the inherited argument (or result) of the same
+;;; name. The following operand options are defined:
+;;;
+;;; :SCs (SC*)
+;;; :SCs specifies good SCs for this operand. Other SCs will
+;;; be penalized according to move costs. A load TN will be
+;;; allocated if necessary, guaranteeing that the operand is
+;;; always one of the specified SCs.
+;;;
+;;; :LOAD-TN Load-Name
+;;; Load-Name is bound to the load TN allocated for this
+;;; operand, or to NIL if no load TN was allocated.
+;;;
+;;; :LOAD-IF EXPRESSION
+;;; Controls whether automatic operand loading is done.
+;;; EXPRESSION is evaluated with the fixed operand TNs bound.
+;;; If EXPRESSION is true,then loading is done and the variable
+;;; is bound to the load TN in the generator body. Otherwise,
+;;; loading is not done, and the variable is bound to the actual
+;;; operand.
+;;;
+;;; :MORE T-or-NIL
+;;; If specified, NAME is bound to the TN-REF for the first
+;;; argument or result following the fixed arguments or results.
+;;; A :MORE operand must appear last, and cannot be targeted or
+;;; restricted.
+;;;
+;;; :TARGET Operand
+;;; This operand is targeted to the named operand, indicating a
+;;; desire to pack in the same location. Not legal for results.
+;;;
+;;; :FROM Time-Spec
+;;; :TO Time-Spec
+;;; Specify the beginning or end of the operand's lifetime.
+;;; :FROM can only be used with results, and :TO only with
+;;; arguments. The default for the N'th argument/result is
+;;; (:ARGUMENT N)/(:RESULT N). These options are necessary
+;;; primarily when operands are read or written out of order.
+;;;
+;;; :CONDITIONAL [Condition-descriptor+]
+;;; This is used in place of :RESULTS with conditional branch VOPs.
+;;; There are no result values: the result is a transfer of control.
+;;; The target label is passed as the first :INFO arg. The second
+;;; :INFO arg is true if the sense of the test should be negated.
+;;; A side effect is to set the PREDICATE attribute for functions
+;;; in the :TRANSLATE option.
+;;;
+;;; If some condition descriptors are provided, this is a flag-setting
+;;; VOP. Descriptors are interpreted in an architecture-dependent
+;;; manner. See the BRANCH-IF VOP in $ARCH/pred.lisp.
+;;;
+;;; :TEMPORARY ({Key Value}*) Name*
+;;; Allocate a temporary TN for each Name, binding that variable to
+;;; the TN within the body of the generators. In addition to :TARGET
+;;; (which is is the same as for operands), the following options are
+;;; defined:
+;;;
+;;; :SC SC-Name
+;;; :OFFSET SB-Offset
+;;; Force the temporary to be allocated in the specified SC
+;;; with the specified offset. Offset is evaluated at
+;;; macroexpand time. If Offset is omitted, the register
+;;; allocator chooses a free location in SC. If both SC and
+;;; Offset are omitted, then the temporary is packed according
+;;; to its primitive type.
+;;;
+;;; :FROM Time-Spec
+;;; :TO Time-Spec
+;;; Similar to the argument/result option, this specifies the
+;;; start and end of the temporaries' lives. The defaults are
+;;; :LOAD and :SAVE, i.e. the duration of the VOP. The other
+;;; intervening phases are :ARGUMENT, :EVAL and :RESULT.
+;;; Non-zero sub-phases can be specified by a list, e.g. by
+;;; default the second argument's life ends at (:ARGUMENT 1).
+;;;
+;;; :GENERATOR Cost Form*
+;;; Specifies the translation into assembly code. Cost is the
+;;; estimated cost of the code emitted by this generator. The body
+;;; is arbitrary Lisp code that emits the assembly language
+;;; translation of the VOP. An ASSEMBLE form is wrapped around
+;;; the body, so code may be emitted by using the local INST macro.
+;;; During the evaluation of the body, the names of the operands
+;;; and temporaries are bound to the actual TNs.
+;;;
+;;; :EFFECTS Effect*
+;;; :AFFECTED Effect*
+;;; Specifies the side effects that this VOP has and the side
+;;; effects that effect its execution. If unspecified, these
+;;; default to the worst case.
+;;;
+;;; :INFO Name*
+;;; Define some magic arguments that are passed directly to the code
+;;; generator. The corresponding trailing arguments to VOP or
+;;; %PRIMITIVE are stored in the VOP structure. Within the body
+;;; of the generators, the named variables are bound to these
+;;; values. Except in the case of :CONDITIONAL VOPs, :INFO arguments
+;;; cannot be specified for VOPS that are the direct translation
+;;; for a function (specified by :TRANSLATE).
+;;;
+;;; :IGNORE Name*
+;;; Causes the named variables to be declared IGNORE in the
+;;; generator body.
+;;;
+;;; :VARIANT Thing*
+;;; :VARIANT-VARS Name*
+;;; These options provide a way to parameterize families of VOPs
+;;; that differ only trivially. :VARIANT makes the specified
+;;; evaluated Things be the "variant" associated with this VOP.
+;;; :VARIANT-VARS causes the named variables to be bound to the
+;;; corresponding Things within the body of the generator.
+;;;
+;;; :VARIANT-COST Cost
+;;; Specifies the cost of this VOP, overriding the cost of any
+;;; inherited generator.
+;;;
+;;; :NOTE {String | NIL}
+;;; A short noun-like phrase describing what this VOP "does", i.e.
+;;; the implementation strategy. If supplied, efficiency notes will
+;;; be generated when type uncertainty prevents :TRANSLATE from
+;;; working. NIL inhibits any efficiency note.
+;;;
+;;; :ARG-TYPES {* | PType | (:OR PType*) | (:CONSTANT Type)}*
+;;; :RESULT-TYPES {* | PType | (:OR PType*)}*
+;;; Specify the template type restrictions used for automatic
+;;; translation. If there is a :MORE operand, the last type is the
+;;; more type. :CONSTANT specifies that the argument must be a
+;;; compile-time constant of the specified Lisp type. The constant
+;;; values of :CONSTANT arguments are passed as additional :INFO
+;;; arguments rather than as :ARGS.
+;;;
+;;; :TRANSLATE Name*
+;;; This option causes the VOP template to be entered as an IR2
+;;; translation for the named functions.
+;;;
+;;; :POLICY {:SMALL | :FAST | :SAFE | :FAST-SAFE}
+;;; Specifies the policy under which this VOP is the best translation.
+;;;
+;;; :GUARD Form
+;;; Specifies a Form that is evaluated in the global environment.
+;;; If form returns NIL, then emission of this VOP is prohibited
+;;; even when all other restrictions are met.
+;;;
+;;; :VOP-VAR Name
+;;; :NODE-VAR Name
+;;; In the generator, bind the specified variable to the VOP or
+;;; the Node that generated this VOP.
+;;;
+;;; :SAVE-P {NIL | T | :COMPUTE-ONLY | :FORCE-TO-STACK}
+;;; Indicates how a VOP wants live registers saved.
+;;;
+;;; :MOVE-ARGS {NIL | :FULL-CALL | :LOCAL-CALL | :KNOWN-RETURN}
+;;; Indicates if and how the more args should be moved into a
+;;; different frame.
+(def!macro define-vop ((name &optional inherits) &body specs)
+ (declare (type symbol name))
+ ;; Parse the syntax into a VOP-PARSE structure, and then expand into
+ ;; code that creates the appropriate VOP-INFO structure at load time.
+ ;; We implement inheritance by copying the VOP-PARSE structure for
+ ;; the inherited structure.
+ (let* ((inherited-parse (when inherits
+ (vop-parse-or-lose inherits)))
+ (parse (if inherits
+ (copy-vop-parse inherited-parse)
+ (make-vop-parse)))
+ (n-res (gensym)))