0.7.8.12:
[sbcl.git] / src / compiler / macros.lisp
index 5844829..197ffbe 100644 (file)
 ;;; If the desirability of the transformation depends on the current
 ;;; OPTIMIZE parameters, then the POLICY macro should be used to
 ;;; determine when to pass.
-(defmacro def-source-transform (name lambda-list &body body)
+(defmacro define-source-transform (name lambda-list &body body)
   (let ((fn-name
         (if (listp name)
             (collect ((pieces))
             ,@decls
             ,body))
         (setf (info :function :source-transform ',name) #',fn-name)))))
-
-;;; Define a function that converts a use of (%PRIMITIVE NAME ..)
-;;; into Lisp code. LAMBDA-LIST is a DEFMACRO-style lambda list.
-(defmacro def-primitive-translator (name lambda-list &body body)
-  (let ((fn-name (symbolicate "PRIMITIVE-TRANSLATE-" name))
-       (n-form (gensym))
-       (n-env (gensym)))
-    (multiple-value-bind (body decls)
-       (parse-defmacro lambda-list n-form body name "%primitive"
-                       :environment n-env
-                       :error-fun 'convert-condition-into-compiler-error)
-      `(progn
-        (defun ,fn-name (,n-form)
-          (let ((,n-env *lexenv*))
-            ,@decls
-            ,body))
-        (setf (gethash ',name *primitive-translators*) ',fn-name)))))
 \f
 ;;;; boolean attribute utilities
 ;;;;
 ) ; EVAL-WHEN
 
 ;;; Define a new class of boolean attributes, with the attributes
-;;; having the specified Attribute-Names. Name is the name of the
+;;; having the specified ATTRIBUTE-NAMES. NAME is the name of the
 ;;; class, which is used to generate some macros to manipulate sets of
 ;;; the attributes:
 ;;;
 ;;;   those in Attr2.
 (defmacro attributes-union (&rest attributes)
   `(the attributes
-       (logior ,@(mapcar #'(lambda (x) `(the attributes ,x)) attributes))))
+       (logior ,@(mapcar (lambda (x) `(the attributes ,x)) attributes))))
 (defmacro attributes-intersection (&rest attributes)
   `(the attributes
-       (logand ,@(mapcar #'(lambda (x) `(the attributes ,x)) attributes))))
+       (logand ,@(mapcar (lambda (x) `(the attributes ,x)) attributes))))
 (declaim (ftype (function (attributes attributes) boolean) attributes=))
 #!-sb-fluid (declaim (inline attributes=))
 (defun attributes= (attr1 attr2)
 ;;;             which means efficiency notes will be generated when this
 ;;;             transform fails even if INHIBIT-WARNINGS=SPEED (but not if
 ;;;             INHIBIT-WARNINGS>SPEED).
-;;;   :WHEN {:NATIVE | :BYTE | :BOTH}
-;;;           - Indicates whether this transform applies to native code,
-;;;             byte-code or both (default :native.)
 (defmacro deftransform (name (lambda-list &optional (arg-types '*)
                                          (result-type '*)
                                          &key result policy node defun-only
-                                         eval-name important (when :native))
+                                         eval-name important)
                             &body body-decls-doc)
   (when (and eval-name defun-only)
     (error "can't specify both DEFUN-ONLY and EVAL-NAME"))
                ,(if eval-name
                     ``(function ,,arg-types ,,result-type)
                     `'(function ,arg-types ,result-type))
-               #'(lambda ,@stuff)
+               (lambda ,@stuff)
                ,doc
-               ,(if important t nil)
-               ,when)))))))
+               ,(if important t nil))))))))
 \f
 ;;;; DEFKNOWN and DEFOPTIMIZER
 
 ;;; Declare the function NAME to be a known function. We construct a
 ;;; type specifier for the function by wrapping (FUNCTION ...) around
 ;;; the ARG-TYPES and RESULT-TYPE. ATTRIBUTES is an unevaluated list
-;;; of boolean attributes of the function. These attributes are
-;;; meaningful here:
-;;;
-;;;     CALL
-;;;        May call functions that are passed as arguments. In order
-;;;        to determine what other effects are present, we must find
-;;;        the effects of all arguments that may be functions.
-;;;
-;;;     UNSAFE
-;;;        May incorporate arguments in the result or somehow pass
-;;;        them upward.
-;;;
-;;;     UNWIND
-;;;        May fail to return during correct execution. Errors
-;;;        are O.K.
-;;;
-;;;     ANY
-;;;        The (default) worst case. Includes all the other bad
-;;;        things, plus any other possible bad thing.
-;;;
-;;;     FOLDABLE
-;;;        May be constant-folded. The function has no side effects,
-;;;        but may be affected by side effects on the arguments. E.g.
-;;;        SVREF, MAPC.
-;;;
-;;;     FLUSHABLE
-;;;        May be eliminated if value is unused. The function has
-;;;        no side effects except possibly CONS. If a function is
-;;;        defined to signal errors, then it is not flushable even
-;;;        if it is movable or foldable.
-;;;
-;;;     MOVABLE
-;;;        May be moved with impunity. Has no side effects except
-;;;        possibly CONS, and is affected only by its arguments.
-;;;
-;;;     PREDICATE
-;;;         A true predicate likely to be open-coded. This is a
-;;;         hint to IR1 conversion that it should ensure calls always
-;;;         appear as an IF test. Not usually specified to DEFKNOWN,
-;;;         since this is implementation dependent, and is usually
-;;;         automatically set by the DEFINE-VOP :CONDITIONAL option.
-;;;
-;;; NAME may also be a list of names, in which case the same
-;;; information is given to all the names. The keywords specify the
-;;; initial values for various optimizers that the function might
-;;; have.
+;;; of boolean attributes of the function. See their description in
+;;; (DEF-BOOLEAN-ATTRIBUTE IR1). NAME may also be a list of names, in
+;;; which case the same information is given to all the names. The
+;;; keywords specify the initial values for various optimizers that
+;;; the function might have.
 (defmacro defknown (name arg-types result-type &optional (attributes '(any))
                         &rest keys)
   (when (and (intersection attributes '(any call unwind))
             (intersection attributes '(movable)))
     (error "function cannot have both good and bad attributes: ~S" attributes))
 
+  (when (member 'any attributes)
+    (setf attributes (union '(call unsafe unwind) attributes)))
+  (when (member 'flushable attributes)
+    (pushnew 'unsafely-flushable attributes))
+
   `(%defknown ',(if (and (consp name)
                         (not (eq (car name) 'setf)))
                    name
                    (list name))
              '(function ,arg-types ,result-type)
-             (ir1-attributes ,@(if (member 'any attributes)
-                                   (union '(call unsafe unwind) attributes)
-                                   attributes))
+             (ir1-attributes ,@attributes)
              ,@keys))
 
 ;;; Create a function which parses combination args according to WHAT
 ;;; and LAMBDA-LIST, where WHAT is either a function name or a list
-;;; (FUNCTION-NAME KIND) and does some KIND of optimization.
+;;; (FUN-NAME KIND) and does some KIND of optimization.
 ;;;
-;;; The FUNCTION-NAME must name a known function. LAMBDA-LIST is used
+;;; The FUN-NAME must name a known function. LAMBDA-LIST is used
 ;;; to parse the arguments to the combination as in DEFTRANSFORM. If
 ;;; the argument syntax is invalid or there are non-constant keys,
 ;;; then we simply return NIL.
            ,(parse-deftransform lambda-list body n-args
                                 `(return-from ,name nil))))
        ,@(when (consp what)
-           `((setf (,(symbolicate "FUNCTION-INFO-" (second what))
-                    (function-info-or-lose ',(first what)))
+           `((setf (,(symbolicate "FUN-INFO-" (second what))
+                    (fun-info-or-lose ',(first what)))
                    #',name)))))))
 \f
 ;;;; IR groveling macros
                    `(eq ,node-var (block-last ,n-block))
                    `(eq ,cont-var ,n-last-cont))
           (return nil))))))
-;;; like Do-Nodes, only iterating in reverse order
+;;; like DO-NODES, only iterating in reverse order
 (defmacro do-nodes-backwards ((node-var cont-var block) &body body)
   (let ((n-block (gensym))
        (n-start (gensym))
         (when (eq ,n-next ,n-start)
           (return nil))))))
 
-;;; Bind the IR1 context variables so that IR1 conversion can be done
-;;; after the main conversion pass has finished.
-;;;
-;;; The lexical environment is presumably already null...
-(defmacro with-ir1-environment (node &rest forms)
-  (let ((n-node (gensym)))
-    `(let* ((,n-node ,node)
-           (*current-component* (block-component (node-block ,n-node)))
-           (*lexenv* (node-lexenv ,n-node))
-           (*current-path* (node-source-path ,n-node)))
-       ,@forms)))
+;;; Bind the IR1 context variables to the values associated with NODE,
+;;; so that new, extra IR1 conversion related to NODE can be done
+;;; after the original conversion pass has finished.
+(defmacro with-ir1-environment-from-node (node &rest forms)
+  `(flet ((closure-needing-ir1-environment-from-node ()
+           ,@forms))
+     (%with-ir1-environment-from-node
+      ,node
+      #'closure-needing-ir1-environment-from-node)))
+(defun %with-ir1-environment-from-node (node fun)
+  (declare (type node node) (type function fun))
+  (let ((*current-component* (node-component node))
+       (*lexenv* (node-lexenv node))
+       (*current-path* (node-source-path node)))
+    (aver-live-component *current-component*)
+    (funcall fun)))
 
 ;;; Bind the hashtables used for keeping track of global variables,
-;;; functions, &c. Also establish condition handlers.
+;;; functions, etc. Also establish condition handlers.
 (defmacro with-ir1-namespace (&body forms)
-  `(let ((*free-variables* (make-hash-table :test 'eq))
-        (*free-functions* (make-hash-table :test 'equal))
+  `(let ((*free-vars* (make-hash-table :test 'eq))
+        (*free-funs* (make-hash-table :test 'equal))
         (*constants* (make-hash-table :test 'equal))
         (*source-paths* (make-hash-table :test 'eq)))
      (handler-bind ((compiler-error #'compiler-error-handler)
     `(if ,n-res
         (values (cdr ,n-res) t)
         (values nil nil))))
+
+;;;
+(defmacro with-continuation-type-assertion ((cont ctype context) &body body)
+  `(let ((*lexenv* (ir1ize-the-or-values ,ctype ,cont *lexenv* ,context)))
+     ,@body))
 \f
 ;;;; the EVENT statistics/trace utility
 
 
 (defstruct (event-info (:copier nil))
   ;; The name of this event.
-  (name (required-argument) :type symbol)
+  (name (missing-arg) :type symbol)
   ;; The string rescribing this event.
-  (description (required-argument) :type string)
+  (description (missing-arg) :type string)
   ;; The name of the variable we stash this in.
-  (var (required-argument) :type symbol)
+  (var (missing-arg) :type symbol)
   ;; The number of times this event has happened.
   (count 0 :type fixnum)
   ;; The level of significance of this event.
-  (level (required-argument) :type unsigned-byte)
+  (level (missing-arg) :type unsigned-byte)
   ;; If true, a function that gets called with the node that the event
   ;; happened to.
   (action nil :type (or function null)))
 (declaim (ftype (function (&optional unsigned-byte stream) (values)) event-statistics))
 (defun event-statistics (&optional (min-count 1) (stream *standard-output*))
   (collect ((info))
-    (maphash #'(lambda (k v)
-                (declare (ignore k))
-                (when (>= (event-info-count v) min-count)
-                  (info v)))
+    (maphash (lambda (k v)
+              (declare (ignore k))
+              (when (>= (event-info-count v) min-count)
+                (info v)))
             *event-info*)
     (dolist (event (sort (info) #'> :key #'event-info-count))
       (format stream "~6D: ~A~%" (event-info-count event)
 
 (declaim (ftype (function nil (values)) clear-event-statistics))
 (defun clear-event-statistics ()
-  (maphash #'(lambda (k v)
-              (declare (ignore k))
-              (setf (event-info-count v) 0))
+  (maphash (lambda (k v)
+            (declare (ignore k))
+            (setf (event-info-count v) 0))
           *event-info*)
   (values))
 \f