Add MAKE-DUMMY-FDEFN function.
[sbcl.git] / src / compiler / early-globaldb.lisp
bloba27a1a43759cd144f032725dc8581ec6dcd2cc1f
1 ;;;; This file contains stuff that was split out from 'globaldb.lisp'
2 ;;;; to satisfy build-order constraints.
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.
13 ;;; Given the presence of docstrings and source locations,
14 ;;; this logic arguably belongs to the runtime kernel, not the compiler,
15 ;;; but such nuance isn't hugely important.
16 (in-package "SB!C")
18 ;;; Similar to FUNCTION, but the result type is "exactly" specified:
19 ;;; if it is an object type, then the function returns exactly one
20 ;;; value, if it is a short form of VALUES, then this short form
21 ;;; specifies the exact number of values.
22 (def!type sfunction (args &optional result)
23 (let ((result (cond ((eq result '*) '*)
24 ((or (atom result)
25 (not (eq (car result) 'values)))
26 `(values ,result &optional))
27 ((intersection (cdr result) sb!xc:lambda-list-keywords)
28 result)
29 (t `(values ,@(cdr result) &optional)))))
30 `(function ,args ,result)))
32 (declaim (ftype (sfunction (t t t) (values t t)) info)
33 (ftype (sfunction (t t t) t) clear-info)
34 (ftype (sfunction (t t t t) t) (setf info)))
36 ;;; (:FUNCTION :TYPE) information is extracted through a wrapper.
37 ;;; The globaldb representation is not necessarily literally a CTYPE.
38 #-sb-xc-host
39 (declaim (ftype (sfunction (t) (values ctype boolean)) proclaimed-ftype))
41 ;;; At run time, we represent the type of a piece of INFO in the globaldb
42 ;;; by a small integer between 1 and 63. [0 is reserved for internal use.]
43 ;;; CLISP, and maybe others, need EVAL-WHEN because without it, the constant
44 ;;; is not seen by the "#." expression a few lines down.
45 (eval-when (:compile-toplevel :load-toplevel :execute)
46 (defconstant info-number-bits 6))
47 (def!type info-number () `(unsigned-byte ,info-number-bits))
49 ;;; A map from info-number to its META-INFO object.
50 ;;; The reverse mapping is obtained by reading the META-INFO.
51 (declaim (type (simple-vector #.(ash 1 info-number-bits)) *info-types*))
52 (!defglobal *info-types*
53 ;; Must be dumped as a literal for cold-load.
54 #.(make-array (ash 1 info-number-bits) :initial-element nil))
56 (defstruct (meta-info
57 (:constructor
58 !make-meta-info (number category kind type-spec
59 type-checker validate-function default))
60 (:copier nil))
61 ;; a number that uniquely identifies this object
62 (number nil :type info-number :read-only t)
63 ;; 2-part key to this piece of metainfo
64 (category nil :type keyword :read-only t)
65 (kind nil :type keyword :read-only t)
66 ;; a type specifier which info of this type must satisfy
67 (type-spec nil :type t :read-only t)
68 ;; Two functions called by (SETF INFO) before calling SET-INFO-VALUE.
69 ;; 1. A function that type-checks its argument and returns it,
70 ;; or signals an error.
71 ;; Some Lisps trip over their shoelaces trying to assert that
72 ;; a function is (function (t) t). Our code is fine though.
73 (type-checker nil :type #+sb-xc-host function #-sb-xc-host (sfunction (t) t)
74 :read-only t)
75 ;; 2. a function of two arguments, a name and new-value, which performs
76 ;; any other checks and/or side-effects including signaling an error.
77 (validate-function nil :type (or function null) :read-only t)
78 ;; If FUNCTIONP, then a function called when there is no information of
79 ;; this type. If not FUNCTIONP, then any object serving as a default.
80 (default nil :read-only t))
82 (declaim (freeze-type meta-info))
84 (defconstant +info-metainfo-type-num+ 0)
86 ;; Refer to info-vector.lisp for the meaning of this constant.
87 (defconstant +no-auxilliary-key+ 0)
89 ;; Return the globaldb info for SYMBOL. With respect to the state diagram
90 ;; presented at the definition of SYMBOL-PLIST, if the object in SYMBOL's
91 ;; info slot is LISTP, it is in state 1 or 3. Either way, take the CDR.
92 ;; Otherwise, it is in state 2 so return the value as-is.
93 ;; In terms of this function being named "-vector", implying always a vector,
94 ;; it is understood that NIL is a proxy for +NIL-PACKED-INFOS+, a vector.
96 #-sb-xc-host
97 (progn
98 #!-symbol-info-vops (declaim (inline symbol-info-vector))
99 (defun symbol-info-vector (symbol)
100 (let ((info-holder (symbol-info symbol)))
101 (truly-the (or null simple-vector)
102 (if (listp info-holder) (cdr info-holder) info-holder)))))
104 ;;; SYMBOL-INFO is a primitive object accessor defined in 'objdef.lisp'
105 ;;; But in the host Lisp, there is no such thing as a symbol-info slot.
106 ;;; Instead, symbol-info is kept in the host symbol's plist.
107 #+sb-xc-host
108 (defmacro symbol-info-vector (symbol) `(get ,symbol :sb-xc-globaldb-info))
110 ;; Perform the equivalent of (GET-INFO-VALUE KIND +INFO-METAINFO-TYPE-NUM+)
111 ;; but skipping the defaulting logic.
112 ;; Return zero or more META-INFOs that match on KIND, which is usually
113 ;; - though not always - a unique identifier for the (:TYPE :KIND) pair.
114 ;; Note that bypassing of defaults is critical for bootstrapping,
115 ;; since INFO is used to retrieve its own META-INFO at system-build time.
116 (defmacro !get-meta-infos (kind)
117 `(let* ((info-vector (symbol-info-vector ,kind))
118 (index (if info-vector
119 (packed-info-value-index info-vector +no-auxilliary-key+
120 +info-metainfo-type-num+))))
121 (if index (svref info-vector index))))
123 ;; (UNSIGNED-BYTE 16) is an arbitrarily generous limit on the number of
124 ;; cells in an info-vector. Most vectors have a fewer than a handful of things,
125 ;; and performance would need to be re-thought if more than about a dozen
126 ;; cells were in use. (It would want to become hash-based probably)
127 (declaim (ftype (function (simple-vector (or (eql 0) symbol) info-number)
128 (or null (unsigned-byte 16)))
129 packed-info-value-index))
131 ;; Return the META-INFO object for CATEGORY and KIND, signaling an error
132 ;; if not found and ERRORP is non-nil. Note that the two-level logical hierarchy
133 ;; of CATEGORY + KIND is physically grouped by KIND first, then CATEGORY.
134 ;; e.g. Searching for (:SETF :EXPANDER) searches for :EXPANDER and finds
135 ;; (#<:CAS :EXPANDER, 44> #<:SETF :EXPANDER, 43> #<:TYPE :EXPANDER, 25>)
136 ;; from which one is picked. This is slightly faster than searching first by
137 ;; CATEGORY, because in the case of :FUNCTION there would be ~11 things to sift
138 ;; through, whereas typically no more than 3 or 4 items have the same KIND.
140 (defun meta-info (category kind &optional (errorp t))
141 (or (let ((metadata (!get-meta-infos kind)))
142 (cond ((listp metadata) ; conveniently handles NIL
143 (dolist (info metadata nil) ; FIND is slower :-(
144 (when (eq (meta-info-category (truly-the meta-info info))
145 category)
146 (return info))))
147 ((eq (meta-info-category (truly-the meta-info metadata)) category)
148 metadata)))
149 ;; !GET-META-INFOS enforces that KIND is a symbol, therefore
150 ;; if a metaobject was found, CATEGORY was necessarily a symbol too.
151 ;; Otherwise, if the caller wants no error to be signaled on missing info,
152 ;; we must nevertheless enforce that CATEGORY was actually a symbol.
153 (if errorp
154 (error "(~S ~S) is not a defined info type." category kind)
155 (progn (the symbol category) nil)))) ; THE is for type-safety
157 ;;; Compiler macros for INFO functions.
159 ;;; These are defined ASAP so that when building the cross-compiler, all calls
160 ;;; occurring after compilation of "globaldb" (for known constant meta-info)
161 ;;; are transformed; and when executing the cross-compiler, *all* inlineable
162 ;;; calls for known constant meta-info are transformed;
163 ;;; and when running target code, calls with legal constants for the first two
164 ;;; arguments are transformed.
165 (macrolet ((def (name lambda-list form)
166 (assert (and (member 'category lambda-list)
167 (member 'kind lambda-list)))
168 `(define-compiler-macro ,name ,(append '(&whole .whole.) lambda-list)
169 (if (and (keywordp category) (keywordp kind))
170 ;; In the target Lisp, it's a STYLE-WARNING if this macro
171 ;; defers to a full call to #'INFO.
172 ;; If the cross-compilation host, if any info-type is
173 ;; defined, then it's an error not to find the meta-info.
174 ;; If no info-types are defined, silently defer.
175 (let ((meta-info
176 (and #+sb-xc-host (find-if #'identity *info-types*)
177 (meta-info category kind #-sb-xc-host nil))))
178 (if meta-info
179 ,form
180 (progn
181 #-sb-xc-host
182 (style-warn "(~S ~S) is not a defined info type."
183 category kind)
184 .whole.)))
185 .whole.))))
187 (def info (category kind name)
188 `(truly-the (values ,(meta-info-type-spec meta-info) boolean)
189 (get-info-value ,name ,(meta-info-number meta-info))))
191 (def (setf info) (new-value category kind name)
192 (let* (#+sb-xc-host (sb!xc:*gensym-counter* sb!xc:*gensym-counter*)
193 (tin (meta-info-number meta-info)) ; info-type id number
194 (type-spec (meta-info-type-spec meta-info))
195 (new (make-symbol "NEW"))
196 (check
197 (when (meta-info-validate-function meta-info)
198 ;; is (or ... null), but non-null at macroexpansion time
199 ;; implies non-null at runtime.
200 `(truly-the function
201 (meta-info-validate-function
202 (truly-the meta-info (svref *info-types* ,tin)))))))
203 `(let ((,new ,new-value))
204 ;; enforce type-correctness regardless of enclosing policy
205 (let ((,new (locally (declare (optimize (safety 3)))
206 (the ,type-spec ,new))))
207 ,@(when check
208 `((funcall ,check ,name ,new)))
209 (set-info-value ,name ,tin ,new)))))
211 (def clear-info (category kind name)
212 `(clear-info-values ,name '(,(meta-info-number meta-info)))))
214 ;; interface to %ATOMIC-SET-INFO-VALUE
215 ;; GET-INFO-VALUE-INITIALIZING is a restricted case of this,
216 ;; and perhaps could be implemented as such.
217 ;; Atomic update will be important for making the fasloader threadsafe
218 ;; using a predominantly lock-free design, and other nice things.
219 (defmacro atomic-set-info-value (category kind name lambda)
220 (with-unique-names (info-number proc)
221 `(let ((,info-number
222 ,(if (and (keywordp category) (keywordp kind))
223 (meta-info-number (meta-info category kind))
224 `(meta-info-number (meta-info ,category ,kind)))))
225 ,(if (and (listp lambda) (eq (car lambda) 'lambda))
226 ;; rewrite as FLET because the compiler is unable to dxify
227 ;; (DX-LET ((x (LAMBDA <whatever>))) (F x))
228 (destructuring-bind (lambda-list . body) (cdr lambda)
229 `(dx-flet ((,proc ,lambda-list ,@body))
230 (%atomic-set-info-value ,name ,info-number #',proc)))
231 `(%atomic-set-info-value ,name ,info-number ,lambda)))))
233 ;; Perform the approximate equivalent operations of retrieving
234 ;; (INFO :CATEGORY :KIND NAME), but if no info is found, invoke CREATION-FORM
235 ;; to produce an object that becomes the value for that piece of info, storing
236 ;; and returning it. The entire sequence behaves atomically but with a proviso:
237 ;; the creation form's result may be discarded, and another object returned
238 ;; instead (presumably) from another thread's execution of the creation form.
239 ;; If constructing the object has either non-trivial cost, or deleterious
240 ;; side-effects from making and discarding its result, do NOT use this macro.
241 ;; A mutex-guarded table would probably be more appropriate in such cases.
243 (defmacro get-info-value-initializing (category kind name creation-form)
244 (let ((proc (make-symbol "THUNK")))
245 `(dx-flet ((,proc () ,creation-form))
246 (%get-info-value-initializing
247 ,(if (and (keywordp category) (keywordp kind))
248 (meta-info-number (meta-info category kind))
249 `(meta-info-number (meta-info ,category ,kind)))
250 ,name #',proc))))
252 ;;;; boolean attribute utilities
253 ;;;;
254 ;;;; We need to maintain various sets of boolean attributes for known
255 ;;;; functions and VOPs. To save space and allow for quick set
256 ;;;; operations, we represent the attributes as bits in a fixnum.
258 (deftype attributes () 'fixnum)
260 ;;; Given a list of attribute names and an alist that translates them
261 ;;; to masks, return the OR of the masks.
262 (defun encode-attribute-mask (names universe)
263 (loop for name in names
264 for pos = (position name universe)
265 sum (if pos (ash 1 pos) (error "unknown attribute name: ~S" name))))
267 (defun decode-attribute-mask (bits universe)
268 (loop for name across universe
269 for mask = 1 then (ash mask 1)
270 when (logtest mask bits) collect name))
272 ;;; Define a new class of boolean attributes, with the attributes
273 ;;; having the specified ATTRIBUTE-NAMES. NAME is the name of the
274 ;;; class, which is used to generate some macros to manipulate sets of
275 ;;; the attributes:
277 ;;; NAME-attributep attributes attribute-name*
278 ;;; Return true if one of the named attributes is present, false
279 ;;; otherwise. When set with SETF, updates the place Attributes
280 ;;; setting or clearing the specified attributes.
282 ;;; NAME-attributes attribute-name*
283 ;;; Return a set of the named attributes.
284 (defmacro !def-boolean-attribute (name &rest attribute-names)
285 (let ((vector (coerce attribute-names 'vector))
286 (constructor (symbolicate name "-ATTRIBUTES"))
287 (test-name (symbolicate name "-ATTRIBUTEP")))
288 `(progn
289 (defmacro ,constructor (&rest attribute-names)
290 "Automagically generated boolean attribute creation function.
291 See !DEF-BOOLEAN-ATTRIBUTE."
292 (encode-attribute-mask attribute-names ,vector))
293 (defun ,(symbolicate "DECODE-" name "-ATTRIBUTES") (attributes)
294 (decode-attribute-mask attributes ,vector))
295 (defmacro ,test-name (attributes &rest attribute-names)
296 "Automagically generated boolean attribute test function.
297 See !DEF-BOOLEAN-ATTRIBUTE."
298 `(logtest (the attributes ,attributes)
299 (,',constructor ,@attribute-names)))
300 (define-setf-expander ,test-name (place &rest attributes
301 &environment env)
302 "Automagically generated boolean attribute setter. See
303 !DEF-BOOLEAN-ATTRIBUTE."
304 (multiple-value-bind (temps values stores setter getter)
305 (#+sb-xc-host get-setf-expansion
306 #-sb-xc-host sb!xc:get-setf-expansion place env)
307 (when (cdr stores)
308 (error "multiple store variables for ~S" place))
309 (let ((newval (sb!xc:gensym))
310 (n-place (sb!xc:gensym))
311 (mask (encode-attribute-mask attributes ,vector)))
312 (values `(,@temps ,n-place)
313 `(,@values ,getter)
314 `(,newval)
315 `(let ((,(first stores)
316 (if ,newval
317 (logior ,n-place ,mask)
318 (logandc2 ,n-place ,mask))))
319 ,setter
320 ,newval)
321 `(,',test-name ,n-place ,@attributes))))))))
323 ;;; And now for some gratuitous pseudo-abstraction...
325 ;;; ATTRIBUTES-UNION
326 ;;; Return the union of all the sets of boolean attributes which are its
327 ;;; arguments.
328 ;;; ATTRIBUTES-INTERSECTION
329 ;;; Return the intersection of all the sets of boolean attributes which
330 ;;; are its arguments.
331 ;;; ATTRIBUTES=
332 ;;; True if the attributes present in ATTR1 are identical to
333 ;;; those in ATTR2.
334 (defmacro attributes-union (&rest attributes)
335 `(the attributes
336 (logior ,@(mapcar (lambda (x) `(the attributes ,x)) attributes))))
337 (defmacro attributes-intersection (&rest attributes)
338 `(the attributes
339 (logand ,@(mapcar (lambda (x) `(the attributes ,x)) attributes))))
340 (declaim (ftype (function (attributes attributes) boolean) attributes=))
341 #!-sb-fluid (declaim (inline attributes=))
342 (defun attributes= (attr1 attr2)
343 (eql attr1 attr2))