1 ;;;; This file implements the IR1 finalize phase, which checks for
2 ;;;; various semantic errors.
4 ;;;; This software is part of the SBCL system. See the README file for
7 ;;;; This software is derived from the CMU CL system, which was
8 ;;;; written at Carnegie Mellon University and released into the
9 ;;;; public domain. The software is in the public domain and is
10 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
11 ;;;; files for more information.
15 ;;; Give the user grief about optimizations that we weren't able to
16 ;;; do. It is assumed that the user wants to hear about this, or there
17 ;;; wouldn't be any entries in the table. If the node has been deleted
18 ;;; or is no longer a known call, then do nothing; some other
19 ;;; optimization must have gotten to it.
20 (defun note-failed-optimization (node failures
)
21 (declare (type combination node
) (list failures
))
22 (unless (or (node-deleted node
)
23 (not (eq :known
(combination-kind node
))))
24 (let ((*compiler-error-context
* node
))
25 (dolist (failure failures
)
26 (let ((what (cdr failure
))
27 (note (transform-note (car failure
))))
30 (compiler-notify "~@<unable to ~2I~_~A ~I~_because: ~2I~_~?~:>"
31 note
(first what
) (rest what
)))
32 ((valid-fun-use node what
33 :argument-test
#'types-equal-or-intersect
34 :result-test
#'values-types-equal-or-intersect
)
36 (flet ((give-grief (string &rest stuff
)
39 (valid-fun-use node what
40 :unwinnage-fun
#'give-grief
41 :lossage-fun
#'give-grief
))
42 (compiler-notify "~@<unable to ~
44 ~I~_due to type uncertainty: ~
47 ;; As best I can guess, it's OK to fall off the end here
48 ;; because if it's not a VALID-FUNCTION-USE, the user
49 ;; doesn't want to hear about it. The things I caught when
50 ;; I put ERROR "internal error: unexpected FAILURE=~S" here
51 ;; didn't look like things we need to report. -- WHN 2001-02-07
54 ;;; For each named function with an XEP, note the definition of that
55 ;;; name, and add derived type information to the INFO environment. We
56 ;;; also delete the FUNCTIONAL from *FREE-FUNS* to eliminate the
57 ;;; possibility that new references might be converted to it.
58 (defun finalize-xep-definition (fun)
59 (let* ((leaf (functional-entry-fun fun
))
60 (defined-ftype (definition-type leaf
)))
61 (setf (leaf-type leaf
) defined-ftype
)
62 (when (and (leaf-has-source-name-p leaf
)
63 (eq (leaf-source-name leaf
) (functional-debug-name leaf
)))
64 (let ((source-name (leaf-source-name leaf
)))
65 (let* ((where (info :function
:where-from source-name
))
66 (*compiler-error-context
* (lambda-bind (main-entry leaf
)))
67 (global-def (gethash source-name
*free-funs
*))
68 (global-p (defined-fun-p global-def
)))
69 (note-name-defined source-name
:function
)
71 (remhash source-name
*free-funs
*))
74 (let ((approx-type (info :function
:assumed-type source-name
)))
75 (when (and approx-type
(fun-type-p defined-ftype
))
76 (valid-approximate-type approx-type defined-ftype
))
77 (setf (info :function
:type source-name
) defined-ftype
)
78 (setf (info :function
:assumed-type source-name
) nil
))
79 (setf (info :function
:where-from source-name
) :defined
))
81 (let ((declared-ftype (info :function
:type source-name
)))
82 (unless (defined-ftype-matches-declared-ftype-p
83 defined-ftype declared-ftype
)
85 "~@<The previously declared FTYPE~2I ~_~S~I ~_~
86 conflicts with the definition type ~2I~_~S~:>"
87 (type-specifier declared-ftype
)
88 (type-specifier defined-ftype
)))))
90 (setf (info :function
:type source-name
) defined-ftype
)))))))
93 ;;; Find all calls in COMPONENT to assumed functions and update the
94 ;;; assumed type information. This is delayed until now so that we
95 ;;; have the best possible information about the actual argument
97 (defun note-assumed-types (component name var
)
98 (when (and (eq (leaf-where-from var
) :assumed
)
99 (not (and (defined-fun-p var
)
100 (eq (defined-fun-inlinep var
) :notinline
)))
101 (eq (info :function
:where-from name
) :assumed
)
102 (eq (info :function
:kind name
) :function
))
103 (let ((atype (info :function
:assumed-type name
)))
104 (dolist (ref (leaf-refs var
))
105 (let ((dest (node-dest ref
)))
106 (when (and (eq (node-component ref
) component
)
108 (eq (lvar-uses (basic-combination-fun dest
)) ref
))
109 (setq atype
(note-fun-use dest atype
)))))
110 (setf (info :function
:assumed-type name
) atype
))))
112 ;;; Merge CASTs with preceding/following nodes.
113 (defun ir1-merge-casts (component)
114 (do-blocks-backwards (block component
)
115 (do-nodes-backwards (node lvar block
)
116 (let ((dest (when lvar
(lvar-dest lvar
))))
117 (cond ((and (cast-p dest
)
118 (not (cast-type-check dest
))
119 (immediately-used-p lvar node
))
120 (let ((dtype (node-derived-type node
))
121 (atype (node-derived-type dest
)))
122 (when (values-types-equal-or-intersect
124 ;; FIXME: We do not perform pathwise CAST->type-error
125 ;; conversion, and type errors can later cause
126 ;; backend failures. On the other hand, this version
127 ;; produces less efficient code.
129 ;; This is sorta DERIVE-NODE-TYPE, but does not try
130 ;; to optimize the node.
131 (setf (node-derived-type node
)
132 (values-type-intersection dtype atype
)))))
134 (eq (cast-type-check node
) :external
))
135 (aver (basic-combination-p dest
))
136 (delete-filter node lvar
(cast-value node
))))))))
138 ;;; Do miscellaneous things that we want to do once all optimization
140 ;;; -- Record the derived result type before the back-end trashes the
142 ;;; -- Note definition of any entry points.
143 ;;; -- Note any failed optimizations.
144 (defun ir1-finalize (component)
145 (declare (type component component
))
146 (dolist (fun (component-lambdas component
))
147 (case (functional-kind fun
)
149 (finalize-xep-definition fun
))
151 (setf (leaf-type fun
) (definition-type fun
)))))
153 (maphash #'note-failed-optimization
154 (component-failed-optimizations component
))
156 (maphash (lambda (k v
)
157 (note-assumed-types component k v
))
160 (ir1-merge-casts component
)