(in-package "SB!C")
-(file-comment
- "$Header$")
-
-;;; Give the user grief about optimizations that we weren't able to do. It
-;;; is assumed that they want to hear, or there wouldn't be any entries in the
-;;; table. If the node has been deleted or is no longer a known call, then do
-;;; nothing; some other optimization must have gotten to it.
+;;; Give the user grief about optimizations that we weren't able to
+;;; do. It is assumed that the user wants to hear about this, or there
+;;; wouldn't be any entries in the table. If the node has been deleted
+;;; or is no longer a known call, then do nothing; some other
+;;; optimization must have gotten to it.
(defun note-failed-optimization (node failures)
(declare (type combination node) (list failures))
(unless (or (node-deleted node)
- (not (function-info-p (combination-kind node))))
+ (not (eq :known (combination-kind node))))
(let ((*compiler-error-context* node))
(dolist (failure failures)
(let ((what (cdr failure))
(note (transform-note (car failure))))
(cond
((consp what)
- (compiler-note "unable to ~A because:~%~6T~?"
- note (first what) (rest what)))
- ((valid-function-use node what
- :argument-test #'types-intersect
- :result-test #'values-types-intersect)
+ (compiler-notify "~@<unable to ~2I~_~A ~I~_because: ~2I~_~?~:>"
+ note (first what) (rest what)))
+ ((valid-fun-use node what
+ :argument-test #'types-equal-or-intersect
+ :result-test #'values-types-equal-or-intersect)
(collect ((messages))
- (flet ((frob (string &rest stuff)
+ (flet ((give-grief (string &rest stuff)
(messages string)
(messages stuff)))
- (valid-function-use node what
- :warning-function #'frob
- :error-function #'frob))
-
- (compiler-note "unable to ~A due to type uncertainty:~@
- ~{~6T~?~^~&~}"
- note (messages))))))))))
+ (valid-fun-use node what
+ :unwinnage-fun #'give-grief
+ :lossage-fun #'give-grief))
+ (compiler-notify "~@<unable to ~
+ ~2I~_~A ~
+ ~I~_due to type uncertainty: ~
+ ~2I~_~{~?~^~@:_~}~:>"
+ note (messages))))
+ ;; As best I can guess, it's OK to fall off the end here
+ ;; because if it's not a VALID-FUNCTION-USE, the user
+ ;; doesn't want to hear about it. The things I caught when
+ ;; I put ERROR "internal error: unexpected FAILURE=~S" here
+ ;; didn't look like things we need to report. -- WHN 2001-02-07
+ ))))))
;;; For each named function with an XEP, note the definition of that
-;;; name, and add derived type information to the info environment. We
-;;; also delete the FUNCTIONAL from *FREE-FUNCTIONS* to eliminate the
+;;; name, and add derived type information to the INFO environment. We
+;;; also delete the FUNCTIONAL from *FREE-FUNS* to eliminate the
;;; possibility that new references might be converted to it.
(defun finalize-xep-definition (fun)
- (let* ((leaf (functional-entry-function fun))
- (name (leaf-name leaf))
- (dtype (definition-type leaf)))
- (setf (leaf-type leaf) dtype)
- (when (or (and name (symbolp name))
- (and (consp name) (eq (car name) 'setf)))
- (let* ((where (info :function :where-from name))
- (*compiler-error-context* (lambda-bind (main-entry leaf)))
- (global-def (gethash name *free-functions*))
- (global-p
- (and (defined-function-p global-def)
- (eq (defined-function-functional global-def) leaf))))
- (note-name-defined name :function)
- (when global-p
- (remhash name *free-functions*))
- (ecase where
- (:assumed
- (let ((approx-type (info :function :assumed-type name)))
- (when (and approx-type (function-type-p dtype))
- (valid-approximate-type approx-type dtype))
- (setf (info :function :type name) dtype)
- (setf (info :function :assumed-type name) nil))
- (setf (info :function :where-from name) :defined))
- (:declared); Just keep declared type.
- (:defined
- (when global-p
- (setf (info :function :type name) dtype)))))))
+ (let* ((leaf (functional-entry-fun fun))
+ (defined-ftype (definition-type leaf)))
+ (setf (leaf-type leaf) defined-ftype)
+ (when (and (leaf-has-source-name-p leaf)
+ (eq (leaf-source-name leaf) (functional-debug-name leaf)))
+ (let ((source-name (leaf-source-name leaf)))
+ (let* ((where (info :function :where-from source-name))
+ (*compiler-error-context* (lambda-bind (main-entry leaf)))
+ (global-def (gethash source-name *free-funs*))
+ (global-p (defined-fun-p global-def)))
+ (note-name-defined source-name :function)
+ (when global-p
+ (remhash source-name *free-funs*))
+ (ecase where
+ (:assumed
+ (let ((approx-type (info :function :assumed-type source-name)))
+ (when (and approx-type (fun-type-p defined-ftype))
+ (valid-approximate-type approx-type defined-ftype))
+ (setf (info :function :type source-name) defined-ftype)
+ (setf (info :function :assumed-type source-name) nil))
+ (setf (info :function :where-from source-name) :defined))
+ (:declared
+ (let ((declared-ftype (info :function :type source-name)))
+ (unless (defined-ftype-matches-declared-ftype-p
+ defined-ftype declared-ftype)
+ (compiler-style-warn
+ "~@<The previously declared FTYPE~2I ~_~S~I ~_~
+ conflicts with the definition type ~2I~_~S~:>"
+ (type-specifier declared-ftype)
+ (type-specifier defined-ftype)))))
+ (:defined
+ (setf (info :function :type source-name) defined-ftype)))))))
(values))
-;;; Find all calls in Component to assumed functions and update the assumed
-;;; type information. This is delayed until now so that we have the best
-;;; possible information about the actual argument types.
+;;; Find all calls in COMPONENT to assumed functions and update the
+;;; assumed type information. This is delayed until now so that we
+;;; have the best possible information about the actual argument
+;;; types.
(defun note-assumed-types (component name var)
(when (and (eq (leaf-where-from var) :assumed)
- (not (and (defined-function-p var)
- (eq (defined-function-inlinep var) :notinline)))
+ (not (and (defined-fun-p var)
+ (eq (defined-fun-inlinep var) :notinline)))
(eq (info :function :where-from name) :assumed)
(eq (info :function :kind name) :function))
(let ((atype (info :function :assumed-type name)))
(dolist (ref (leaf-refs var))
- (let ((dest (continuation-dest (node-cont ref))))
- (when (and (eq (block-component (node-block ref)) component)
+ (let ((dest (node-dest ref)))
+ (when (and (eq (node-component ref) component)
(combination-p dest)
- (eq (continuation-use (basic-combination-fun dest)) ref))
- (setq atype (note-function-use dest atype)))))
+ (eq (lvar-uses (basic-combination-fun dest)) ref))
+ (setq atype (note-fun-use dest atype)))))
(setf (info :function :assumed-type name) atype))))
-;;; Do miscellaneous things that we want to do once all optimization has
-;;; been done:
+;;; Merge CASTs with preceding/following nodes.
+(defun ir1-merge-casts (component)
+ (do-blocks-backwards (block component)
+ (do-nodes-backwards (node lvar block)
+ (let ((dest (when lvar (lvar-dest lvar))))
+ (cond ((and (cast-p dest)
+ (not (cast-type-check dest))
+ (immediately-used-p lvar node))
+ (when (values-types-equal-or-intersect
+ (node-derived-type node)
+ (cast-asserted-type dest))
+ ;; FIXME: We do not perform pathwise CAST->type-error
+ ;; conversion, and type errors can later cause
+ ;; backend failures. On the other hand, this version
+ ;; produces less efficient code.
+ (derive-node-type node (cast-asserted-type dest))))
+ ((and (cast-p node)
+ (eq (cast-type-check node) :external))
+ (aver (basic-combination-p dest))
+ (delete-filter node lvar (cast-value node))))))))
+
+;;; Do miscellaneous things that we want to do once all optimization
+;;; has been done:
;;; -- Record the derived result type before the back-end trashes the
;;; flow graph.
;;; -- Note definition of any entry points.
(maphash #'note-failed-optimization
(component-failed-optimizations component))
- (maphash #'(lambda (k v)
- (note-assumed-types component k v))
- *free-functions*)
+ (maphash (lambda (k v)
+ (note-assumed-types component k v))
+ *free-funs*)
+
+ (ir1-merge-casts component)
+
(values))