1 ;;;; This file contains implementation-dependent parts of the type
2 ;;;; support code. This is stuff which deals with the mapping from
3 ;;;; types defined in Common Lisp to types actually supported by an
6 ;;;; This software is part of the SBCL system. See the README file for
9 ;;;; This software is derived from the CMU CL system, which was
10 ;;;; written at Carnegie Mellon University and released into the
11 ;;;; public domain. The software is in the public domain and is
12 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
13 ;;;; files for more information.
15 (in-package "SB!KERNEL")
17 ;;;; implementation-dependent DEFTYPEs
19 ;;; Make DOUBLE-FLOAT a synonym for LONG-FLOAT, SINGLE-FLOAT for
20 ;;; SHORT-FLOAT. This is done by way of an "expander", not a "translator".
21 ;;; !PRECOMPUTE-TYPES will turn their :TYPE :KIND into :PRIMITIVE
22 ;;; in the target image so that they become not redefinable.
23 (sb!xc
:deftype long-float
(&optional low high
) `(double-float ,low
,high
))
24 (sb!xc
:deftype short-float
(&optional low high
) `(single-float ,low
,high
))
26 ;;; worst-case values for float attributes
27 (sb!xc
:deftype float-exponent
()
28 #!-long-float
'double-float-exponent
29 #!+long-float
'long-float-exponent
)
30 (sb!xc
:deftype float-digits
()
31 #!-long-float
`(integer 0 ,sb
!vm
:double-float-digits
)
32 #!+long-float
`(integer 0 ,sb
!vm
:long-float-digits
))
33 (sb!xc
:deftype float-radix
() '(integer 2 2))
34 (sb!xc
:deftype float-int-exponent
()
35 #!-long-float
'double-float-int-exponent
36 #!+long-float
'long-float-int-exponent
)
39 (sb!xc
:deftype boole-code
() '(unsigned-byte 4))
41 ;;; a byte specifier (as generated by BYTE)
42 (sb!xc
:deftype byte-specifier
() 'cons
)
44 ;;; result of CHAR-INT
45 (sb!xc
:deftype char-int
() 'char-code
)
47 ;;; PATHNAME pieces, as returned by the PATHNAME-xxx functions
48 (sb!xc
:deftype pathname-host
() '(or sb
!impl
::host null
))
49 (sb!xc
:deftype pathname-device
()
50 '(or simple-string
(member nil
:unspecific
:unc
)))
51 (sb!xc
:deftype pathname-directory
() 'list
)
52 (sb!xc
:deftype pathname-name
()
53 '(or simple-string sb
!impl
::pattern
(member nil
:unspecific
:wild
)))
54 (sb!xc
:deftype pathname-type
()
55 '(or simple-string sb
!impl
::pattern
(member nil
:unspecific
:wild
)))
56 (sb!xc
:deftype pathname-version
()
57 '(or integer
(member nil
:newest
:wild
:unspecific
)))
59 ;;; internal time format. (Note: not a FIXNUM, ouch..)
60 (sb!xc
:deftype internal-time
() 'unsigned-byte
)
62 (sb!xc
:deftype bignum-element-type
() `(unsigned-byte ,sb
!vm
:n-word-bits
))
63 (sb!xc
:deftype bignum-type
() 'bignum
)
64 ;;; FIXME: see also DEFCONSTANT MAXIMUM-BIGNUM-LENGTH in
65 ;;; src/code/bignum.lisp. -- CSR, 2004-07-19
66 (sb!xc
:deftype bignum-index
()
67 '(mod #.
(1- (ash 1 (- sb
!vm
:n-word-bits sb
!vm
:n-widetag-bits
)))))
68 (sb!xc
:deftype bignum-length
()
69 '(unsigned-byte #.
(- sb
!vm
:n-word-bits sb
!vm
:n-widetag-bits
)))
71 ;;; an index into an integer
72 (sb!xc
:deftype bit-index
()
73 `(integer 0 #.
(* (1- (ash 1 (- sb
!vm
:n-word-bits sb
!vm
:n-widetag-bits
)))
77 ;;;; hooks into the type system
79 (sb!xc
:deftype unboxed-array
(&optional dims
)
80 (collect ((types (list 'or
)))
81 (dolist (type *specialized-array-element-types
*)
82 (when (subtypep type
'(or integer character float
(complex float
)))
83 (types `(array ,type
,dims
))))
86 (sb!xc
:deftype simple-unboxed-array
(&optional dims
)
87 (collect ((types (list 'or
)))
88 (dolist (type *specialized-array-element-types
*)
89 (when (subtypep type
'(or integer character float
(complex float
)))
90 (types `(simple-array ,type
,dims
))))
93 (sb!xc
:deftype complex-vector
(&optional element-type length
)
94 `(and (vector ,element-type
,length
) (not simple-array
)))
96 ;;; Return the symbol that describes the format of FLOAT.
97 (declaim (ftype (function (float) symbol
) float-format-name
))
98 (defun float-format-name (x)
100 (single-float 'single-float
)
101 (double-float 'double-float
)
102 #!+long-float
(long-float 'long-float
)))
104 (declaim (ftype (sfunction (ctype) ctype
) %upgraded-array-element-type
))
105 (defun %upgraded-array-element-type
(eltype)
106 (if (or (eq eltype
*wild-type
*)
107 ;; This is slightly dubious, but not as dubious as
108 ;; assuming that the upgraded-element-type should be
109 ;; equal to T, given the way that the AREF
110 ;; DERIVE-TYPE optimizer works. -- CSR, 2002-08-19
111 (contains-unknown-type-p eltype
))
113 (dolist (stype-name *specialized-array-element-types
*
115 ;; FIXME: Mightn't it be better to have
116 ;; *SPECIALIZED-ARRAY-ELEMENT-TYPES* be stored as precalculated
117 ;; SPECIFIER-TYPE results, instead of having to calculate
118 ;; them on the fly this way? (Call the new array
119 ;; *SPECIALIZED-ARRAY-ELEMENT-SPECIFIER-TYPES* or something..)
120 (let ((stype (specifier-type stype-name
)))
121 (aver (not (unknown-type-p stype
)))
122 (when (csubtypep eltype stype
)
125 (defun sb!xc
:upgraded-array-element-type
(spec &optional environment
)
127 "Return the element type that will actually be used to implement an array
128 with the specifier :ELEMENT-TYPE Spec."
129 (declare (ignore environment
))
131 ;; Can't rely on SPECIFIER-TYPE to signal PARSE-UNKNOWN-TYPE in
132 ;; the case of (AND KNOWN UNKNOWN), since the result of the
133 ;; outter call to SPECIFIER-TYPE can be cached by the code that
134 ;; doesn't catch PARSE-UNKNOWN-TYPE signal.
135 (let ((type (specifier-type spec
)))
136 (if (contains-unknown-type-p type
)
137 (error "Undefined type: ~S" spec
)
138 (type-specifier (%upgraded-array-element-type type
))))
139 (parse-unknown-type (c)
140 (error "Undefined type: ~S" (parse-unknown-type-specifier c
)))))
142 (defun sb!xc
:upgraded-complex-part-type
(spec &optional environment
)
144 "Return the element type of the most specialized COMPLEX number type that
145 can hold parts of type SPEC."
146 (declare (ignore environment
))
147 (let ((type (specifier-type spec
)))
149 ((eq type
*empty-type
*) nil
)
150 ((unknown-type-p type
) (error "undefined type: ~S" spec
))
152 (let ((ctype (specifier-type `(complex ,spec
))))
154 ((eq ctype
*empty-type
*) '(eql 0))
155 ((csubtypep ctype
(specifier-type '(complex single-float
)))
157 ((csubtypep ctype
(specifier-type '(complex double-float
)))
160 ((csubtypep ctype
(specifier-type '(complex long-float
)))
162 ((csubtypep ctype
(specifier-type '(complex rational
)))
166 ;;; Return the most specific integer type that can be quickly checked that
167 ;;; includes the given type.
168 (defun containing-integer-type (subtype)
169 (dolist (type `(fixnum
170 (signed-byte ,sb
!vm
:n-word-bits
)
171 (unsigned-byte ,sb
!vm
:n-word-bits
)
173 (error "~S isn't an integer type?" subtype
))
174 (when (csubtypep subtype
(specifier-type type
))
177 ;;; If TYPE has a CHECK-xxx template, but doesn't have a corresponding
178 ;;; PRIMITIVE-TYPE, then return the template's name. Otherwise, return NIL.
179 (defun hairy-type-check-template-name (type)
180 (declare (type ctype type
))
183 (if (type= type
(specifier-type 'cons
))
187 (if (type= type
(specifier-type 'symbol
))
191 (cond ((type= type
(specifier-type 'fixnum
))
193 #!+#.
(cl:if
(cl:= 32 sb
!vm
:n-word-bits
) '(and) '(or))
194 ((type= type
(specifier-type '(signed-byte 32)))
195 'sb
!c
:check-signed-byte-32
)
196 #!+#.
(cl:if
(cl:= 32 sb
!vm
:n-word-bits
) '(and) '(or))
197 ((type= type
(specifier-type '(unsigned-byte 32)))
198 'sb
!c
:check-unsigned-byte-32
)
199 #!+#.
(cl:if
(cl:= 64 sb
!vm
:n-word-bits
) '(and) '(or))
200 ((type= type
(specifier-type '(signed-byte 64)))
201 'sb
!c
:check-signed-byte-64
)
202 #!+#.
(cl:if
(cl:= 64 sb
!vm
:n-word-bits
) '(and) '(or))
203 ((type= type
(specifier-type '(unsigned-byte 64)))
204 'sb
!c
:check-unsigned-byte-64
)
211 ;; Given a union type INPUT, see if it fully covers an ARRAY-* type,
212 ;; and unite into that when possible, taking care to handle more
213 ;; than one dimensionality/complexity of array, and non-array types.
214 ;; If FOR-TYPEP is true, then:
215 ;; - The input and result are lists of the component types.
216 ;; - We allow "almost coverings" of ARRAY-* to produce an answer
217 ;; that results in a quicker test.
218 ;; e.g. unboxed-array = (and array (not (array t)))
219 ;; Otherwise, if not FOR-TYPEP, the input/result are CTYPES,
220 ;; and we don't introduce negations into the union.
222 ;; Note that in FOR-TYPEP usage, this function should get a chance to see
223 ;; the whole union before WIDETAGS-FROM-UNION-TYPE has removed any types that
224 ;; are testable by their widetag. Otherwise (TYPEP X '(UNBOXED-ARRAY 1))
225 ;; becomes suboptimal. WIDETAGS-FROM-UNION-TYPE knows that strings/bit-vectors,
226 ;; either simple or hairy, all have distinguishing widetags, so if it sees
227 ;; them, reducing to (OR (%OTHER-POINTER-SUBTYPE-P ...) <more-array-types>),
228 ;; the other array-types will not comprise an "almost covering" of ARRAY-*
229 ;; and this code will not do what you want.
230 ;; Additionally, as part of the contract, we don't create a type-difference
231 ;; for a union all of whose types are testable by widetags.
232 ;; e.g. it would be suboptimal to rewrite
233 ;; (SIMPLE-UNBOXED-ARRAY (*)) -> (AND (SIMPLE-ARRAY * (*)) (NOT (ARRAY T)))
234 ;; because it always better to use %OTHER-POINTER-SUBTYPE-P in that case.
236 (defun simplify-array-unions (input &optional for-typep
)
237 (let* ((array-props sb
!vm
:*specialized-array-element-type-properties
*)
238 (types (if (listp input
) input
(union-type-types input
)))
239 (full-mask (1- (ash 1 (length array-props
))))
241 ;; KLUDGE: counting the input types is a fine preliminary check
242 ;; to avoid extra work, but importantly it (magically) bypasses all
243 ;; this logic during cold-init when CTYPE slots of all SAETPs are nil.
244 ;; SBCL sources mostly don't contain type expressions that benefit
245 ;; from this transform.
246 ;; If, in the not-for-typep case, there aren't at least as many
247 ;; array types as SAETPs, there can't be a covering.
248 ;; In the for-typep case, if there aren't at least half as many,
249 ;; then it couldn't be rewritten as negation.
250 ;; Uber-KLUDGE: using (length types) isn't enough to make the
251 ;; not-for-typep case make it all the way through cold-init.
253 (< (length types
) (floor (length array-props
) 2))
254 (< (count-if #'array-type-p types
) (length array-props
)))
255 (return-from simplify-array-unions input
))
256 (flet ((bucket-match-p (a b
)
257 (and (eq (array-type-complexp a
) (array-type-complexp b
))
258 (equal (array-type-dimensions a
) (array-type-dimensions b
))))
260 (and (array-type-p type
)
261 (neq (array-type-specialized-element-type type
) *wild-type
*)
262 (position (array-type-specialized-element-type type
) array-props
263 :key
#'sb
!vm
:saetp-ctype
:test
#'type
=)))
265 (make-array-type (array-type-dimensions type
)
266 :element-type
*wild-type
*
267 :complexp
(array-type-complexp type
))))
268 ;; Bucket the array types by <dimensions,complexp> where each bucket
269 ;; tracks which SAETPs were seen.
270 ;; Search actual element types by TYPE=, not upgraded types, so that the
271 ;; transform into (ARRAY *) is not lossy. However, if uniting does occur
272 ;; and the resultant OR still contains any array type that upgrades to T,
273 ;; we might want to do yet another reduction because:
274 ;; (SPECIFIER-TYPE '(OR (VECTOR *) (VECTOR BAD))) => #<ARRAY-TYPE VECTOR>
276 (binding* ((bit (saetp-index type
) :exit-if-null
)
277 (bucket (assoc type buckets
:test
#'bucket-match-p
)))
279 (push (setq bucket
(cons type full-mask
)) buckets
))
280 ;; Each _missing_ type is represented by a '1' bit so that
281 ;; a final mask of 0 indicates an exhaustive partitioning.
282 ;; (SETF LOGBITP) would work for us, but CLHS doesn't require it.
283 (setf (cdr bucket
) (logandc2 (cdr bucket
) (ash 1 bit
)))))
286 ;; Maybe compute the complement with respect to (ARRAY *)
287 ;; but never express unions of simple-rank-1 as a type-difference,
288 ;; because widetag testing of those is better.
289 (dolist (type types
(nreverse output
))
291 (and (saetp-index type
)
292 (or (array-type-complexp type
)
293 (not (equal (array-type-dimensions type
) '(*))))
294 (assoc type buckets
:test
#'bucket-match-p
)))
298 (< (logcount (cdr bucket
))
299 (floor (length array-props
) 2)))
301 (dotimes (i (length array-props
))
302 (when (logbitp i
(cdr bucket
)) ; exclude it
303 (push (sb!vm
:saetp-specifier
304 (svref array-props i
)) exclude
)))
305 (setf (cdr bucket
) -
1) ; mark as generated
307 `(and ,(type-specifier (wild type
))
308 ,@(mapcar (lambda (x) `(not (array ,x
)))
310 ((not (eql (cdr bucket
) -
1))
311 ;; noncanonical input is a bug,
312 ;; so assert that bucket is not full.
313 (aver (not (eql (cdr bucket
) 0)))
316 (push disjunct output
)))))
317 ((rassoc 0 buckets
) ; at least one full bucket
318 ;; For each input type subsumed by a full bucket,
319 ;; insert the wild array type for that bucket.
320 (dolist (type types
(apply #'type-union
(nreverse output
)))
321 (let* ((bucket (and (saetp-index type
)
322 (assoc type buckets
:test
#'bucket-match-p
)))
323 (disjunct (cond ((eql (cdr bucket
) 0) ; bucket is full
324 (setf (cdr bucket
) -
1) ; mark as generated
326 ((not (eql (cdr bucket
) -
1))
329 (push disjunct output
)))))
330 (t input
))))) ; no change
332 ;; Given TYPES which is a list of types from a union type, decompose into
333 ;; two unions, one being an OR over types representable as widetags
334 ;; with other-pointer-lowtag, and the other being the difference
335 ;; between the input TYPES and the widetags.
336 ;; This is architecture-independent, but unfortunately the needed VOP can't
337 ;; be defined using DEFINE-TYPE-VOPS, so return (VALUES NIL TYPES) for
338 ;; unsupported backends which can't generate an arbitrary call to %TEST-HEADERS.
339 (defun widetags-from-union-type (types)
340 (setq types
(simplify-array-unions types t
))
341 ;; This seems preferable to a reader-conditional in generic code.
342 ;; There is a unit test that the supported architectures don't generate
343 ;; excessively large code, so hopefully it'll not get broken.
344 (let ((info (info :function
:info
'%other-pointer-subtype-p
)))
345 (unless (and info
(sb!c
::fun-info-templates info
))
346 (return-from widetags-from-union-type
(values nil types
))))
347 (let (widetags remainder
)
351 ((and (array-type-p x
)
352 (equal (array-type-dimensions x
) '(*))
353 (type= (array-type-specialized-element-type x
)
354 (array-type-element-type x
)))
355 (if (eq (array-type-specialized-element-type x
) *wild-type
*)
356 ;; could be done, but probably no merit to implementing
357 ;; maybe/definitely-complex wild-type.
358 (unless (array-type-complexp x
)
359 (map 'list
#'sb
!vm
::saetp-typecode
360 sb
!vm
:*specialized-array-element-type-properties
*))
363 (array-type-element-type x
)
364 sb
!vm
:*specialized-array-element-type-properties
*
365 :key
#'sb
!vm
:saetp-ctype
:test
#'type
=)))
366 (cond ((not (array-type-complexp x
))
367 (sb!vm
:saetp-typecode saetp
))
368 ((sb!vm
:saetp-complex-typecode saetp
)
369 (list* (sb!vm
:saetp-complex-typecode saetp
)
370 (when (eq (array-type-complexp x
) :maybe
)
371 (list (sb!vm
:saetp-typecode saetp
)))))))))
373 (case (classoid-name x
)
374 (symbol sb
!vm
:symbol-header-widetag
) ; plus a hack for nil
375 (system-area-pointer sb
!vm
:sap-widetag
))))))
376 (cond ((not adjunct
) (push x remainder
))
377 ((listp adjunct
) (setq widetags
(nconc adjunct widetags
)))
378 (t (push adjunct widetags
)))))
379 (let ((remainder (nreverse remainder
)))
380 (when (member sb
!vm
:symbol-header-widetag widetags
)
381 ;; If symbol is the only widetag-testable type, it's better
382 ;; to just use symbolp. e.g. (OR SYMBOL CHARACTER) should not
383 ;; become (OR (%OTHER-POINTER-SUBTYPE-P ...)
384 (when (null (rest widetags
))
385 (return-from widetags-from-union-type
(values nil types
)))
386 ;; Manipulate 'remainder' to include NULL since NIL's lowtag
387 ;; isn't other-pointer.
388 (let ((null-type (specifier-type 'null
)))
389 (unless (member null-type remainder
:test
#'csubtypep
)
390 (push null-type remainder
))))
391 (values widetags remainder
))))