0.8.4.2:
[sbcl.git] / src / compiler / ir1final.lisp
1 ;;;; This file implements the IR1 finalize phase, which checks for
2 ;;;; various semantic errors.
3
4 ;;;; This software is part of the SBCL system. See the README file for
5 ;;;; more information.
6 ;;;;
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.
12
13 (in-package "SB!C")
14
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 (fun-info-p (combination-kind node))))
24     (let ((*compiler-error-context* node))
25       (dolist (failure failures)
26         (let ((what (cdr failure))
27               (note (transform-note (car failure))))
28           (cond
29            ((consp what)
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)
35             (collect ((messages))
36               (flet ((give-grief (string &rest stuff)
37                        (messages string)
38                        (messages stuff)))
39                 (valid-fun-use node what
40                                :unwinnage-fun #'give-grief
41                                :lossage-fun #'give-grief))
42               (compiler-notify "~@<unable to ~
43                                 ~2I~_~A ~
44                                 ~I~_due to type uncertainty: ~
45                                 ~2I~_~{~?~^~@:_~}~:>"
46                              note (messages))))
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
52            ))))))
53
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)
70           (when global-p
71             (remhash source-name *free-funs*))
72           (ecase where
73             (:assumed
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))
80             (:declared
81              (let ((declared-ftype (info :function :type source-name)))
82                (unless (defined-ftype-matches-declared-ftype-p
83                          defined-ftype declared-ftype)
84                  (compiler-style-warn
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)))))
89             (:defined
90              (setf (info :function :type source-name) defined-ftype)))
91           (when (fasl-output-p *compile-object*)
92             (if (member source-name *fun-names-in-this-file* :test #'equal)
93                 (compiler-warn "~@<Duplicate definition for ~S found in ~
94                                 one static unit (usually a file).~@:>"
95                                source-name)
96                 (push source-name *fun-names-in-this-file*)))))))
97   (values))
98
99 ;;; Find all calls in COMPONENT to assumed functions and update the
100 ;;; assumed type information. This is delayed until now so that we
101 ;;; have the best possible information about the actual argument
102 ;;; types.
103 (defun note-assumed-types (component name var)
104   (when (and (eq (leaf-where-from var) :assumed)
105              (not (and (defined-fun-p var)
106                        (eq (defined-fun-inlinep var) :notinline)))
107              (eq (info :function :where-from name) :assumed)
108              (eq (info :function :kind name) :function))
109     (let ((atype (info :function :assumed-type name)))
110       (dolist (ref (leaf-refs var))
111         (let ((dest (node-dest ref)))
112           (when (and (eq (node-component ref) component)
113                      (combination-p dest)
114                      (eq (lvar-uses (basic-combination-fun dest)) ref))
115             (setq atype (note-fun-use dest atype)))))
116       (setf (info :function :assumed-type name) atype))))
117
118 ;;; Merge CASTs with preceding/following nodes.
119 (defun ir1-merge-casts (component)
120   (do-blocks-backwards (block component)
121     (do-nodes-backwards (node lvar block)
122       (let ((dest (when lvar (lvar-dest lvar))))
123         (cond ((and (cast-p dest)
124                     (not (cast-type-check dest))
125                     (immediately-used-p lvar node))
126                (derive-node-type node (cast-asserted-type dest)))
127               ((and (cast-p node)
128                     (eq (cast-type-check node) :external))
129                (aver (basic-combination-p dest))
130                (delete-filter node lvar (cast-value node))))))))
131
132 ;;; Do miscellaneous things that we want to do once all optimization
133 ;;; has been done:
134 ;;;  -- Record the derived result type before the back-end trashes the
135 ;;;     flow graph.
136 ;;;  -- Note definition of any entry points.
137 ;;;  -- Note any failed optimizations.
138 (defun ir1-finalize (component)
139   (declare (type component component))
140   (dolist (fun (component-lambdas component))
141     (case (functional-kind fun)
142       (:external
143        (finalize-xep-definition fun))
144       ((nil)
145        (setf (leaf-type fun) (definition-type fun)))))
146
147   (maphash #'note-failed-optimization
148            (component-failed-optimizations component))
149
150   (maphash (lambda (k v)
151              (note-assumed-types component k v))
152            *free-funs*)
153
154   (ir1-merge-casts component)
155
156   (values))