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.
60 ;;; 62 bits should give
61 ;;; one hundred forty-six million one hundred thirty-five thousand five hundred twenty years of runtime
62 ;;; It's dangerous to run SBCL for that long without updating.
63 ;;; And it'll be a fixnum on 64-bit targets.
64 ;;; The result from querying get-internal-run-time with multiple cores
65 ;;; running full tilt will exhaust this faster, but it's still plenty enough.
66 (sb!xc
:deftype internal-time
() '(unsigned-byte 62))
67 (sb!xc
:deftype internal-seconds
()
69 #.
(- 62 (floor (log sb
!xc
:internal-time-units-per-second
2)))))
71 (sb!xc
:deftype bignum-element-type
() `(unsigned-byte ,sb
!vm
:n-word-bits
))
72 (sb!xc
:deftype bignum-type
() 'bignum
)
73 ;;; FIXME: see also DEFCONSTANT MAXIMUM-BIGNUM-LENGTH in
74 ;;; src/code/bignum.lisp. -- CSR, 2004-07-19
75 (sb!xc
:deftype bignum-index
()
76 '(mod #.
(1- (ash 1 (- sb
!vm
:n-word-bits sb
!vm
:n-widetag-bits
)))))
77 (sb!xc
:deftype bignum-length
()
78 '(unsigned-byte #.
(- sb
!vm
:n-word-bits sb
!vm
:n-widetag-bits
)))
80 ;;; an index into an integer
81 (sb!xc
:deftype bit-index
()
82 `(integer 0 #.
(* (1- (ash 1 (- sb
!vm
:n-word-bits sb
!vm
:n-widetag-bits
)))
86 ;;;; hooks into the type system
88 (sb!xc
:deftype unboxed-array
(&optional dims
)
89 (collect ((types (list 'or
)))
90 (dolist (type *specialized-array-element-types
*)
91 (when (subtypep type
'(or integer character float
(complex float
)))
92 (types `(array ,type
,dims
))))
95 (sb!xc
:deftype simple-unboxed-array
(&optional dims
)
96 (collect ((types (list 'or
)))
97 (dolist (type *specialized-array-element-types
*)
98 (when (subtypep type
'(or integer character float
(complex float
)))
99 (types `(simple-array ,type
,dims
))))
102 (sb!xc
:deftype complex-vector
(&optional element-type length
)
103 `(and (vector ,element-type
,length
) (not simple-array
)))
105 ;;; Return the symbol that describes the format of FLOAT.
106 (declaim (ftype (function (float) symbol
) float-format-name
))
107 (defun float-format-name (x)
109 (single-float 'single-float
)
110 (double-float 'double-float
)
111 #!+long-float
(long-float 'long-float
)))
113 (declaim (ftype (sfunction (ctype) ctype
) %upgraded-array-element-type
))
114 (defun %upgraded-array-element-type
(eltype)
115 (if (or (eq eltype
*wild-type
*)
116 ;; This is slightly dubious, but not as dubious as
117 ;; assuming that the upgraded-element-type should be
118 ;; equal to T, given the way that the AREF
119 ;; DERIVE-TYPE optimizer works. -- CSR, 2002-08-19
120 (contains-unknown-type-p eltype
))
123 (literal-ctype-vector *parsed-specialized-array-element-types
*)
125 (when (csubtypep eltype stype
)
128 (defun sb!xc
:upgraded-array-element-type
(spec &optional environment
)
130 "Return the element type that will actually be used to implement an array
131 with the specifier :ELEMENT-TYPE Spec."
132 (declare (type lexenv-designator environment
) (ignore environment
))
133 (declare (explicit-check))
134 (let ((type (type-or-nil-if-unknown spec
)))
136 ;; What about a FUNCTION-TYPE - would (FUNCTION (UNKNOWN) UNKNOWN)
137 ;; upgrade to T? Well, it's still ok to say it's an error.
138 (error "Undefined type: ~S" spec
))
140 (type-specifier (%upgraded-array-element-type type
))))))
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 (type lexenv-designator environment
) (ignore environment
))
147 (declare (explicit-check))
148 (let ((type (type-or-nil-if-unknown spec
)))
150 ((eq type
*empty-type
*) nil
)
151 ((not type
) (error "Undefined type: ~S" spec
))
153 (let ((ctype (specifier-type `(complex ,spec
))))
155 ((eq ctype
*empty-type
*) '(eql 0))
156 ((csubtypep ctype
(specifier-type '(complex single-float
)))
158 ((csubtypep ctype
(specifier-type '(complex double-float
)))
161 ((csubtypep ctype
(specifier-type '(complex long-float
)))
163 ((csubtypep ctype
(specifier-type '(complex rational
)))
167 ;;; Return the most specific integer type that can be quickly checked that
168 ;;; includes the given type.
169 (defun containing-integer-type (subtype)
170 (dolist (type `(fixnum
171 (signed-byte ,sb
!vm
:n-word-bits
)
172 (unsigned-byte ,sb
!vm
:n-word-bits
)
174 (error "~S isn't an integer type?" subtype
))
175 (when (csubtypep subtype
(specifier-type type
))
178 ;; Given a union type INPUT, see if it fully covers an ARRAY-* type,
179 ;; and unite into that when possible, taking care to handle more
180 ;; than one dimensionality/complexity of array, and non-array types.
181 ;; If FOR-TYPEP is true, then:
182 ;; - The input and result are lists of the component types.
183 ;; - We allow "almost coverings" of ARRAY-* to produce an answer
184 ;; that results in a quicker test.
185 ;; e.g. unboxed-array = (and array (not (array t)))
186 ;; Otherwise, if not FOR-TYPEP, the input/result are CTYPES,
187 ;; and we don't introduce negations into the union.
189 ;; Note that in FOR-TYPEP usage, this function should get a chance to see
190 ;; the whole union before WIDETAGS-FROM-UNION-TYPE has removed any types that
191 ;; are testable by their widetag. Otherwise (TYPEP X '(UNBOXED-ARRAY 1))
192 ;; becomes suboptimal. WIDETAGS-FROM-UNION-TYPE knows that strings/bit-vectors,
193 ;; either simple or hairy, all have distinguishing widetags, so if it sees
194 ;; them, reducing to (OR (%OTHER-POINTER-SUBTYPE-P ...) <more-array-types>),
195 ;; the other array-types will not comprise an "almost covering" of ARRAY-*
196 ;; and this code will not do what you want.
197 ;; Additionally, as part of the contract, we don't create a type-difference
198 ;; for a union all of whose types are testable by widetags.
199 ;; e.g. it would be suboptimal to rewrite
200 ;; (SIMPLE-UNBOXED-ARRAY (*)) -> (AND (SIMPLE-ARRAY * (*)) (NOT (ARRAY T)))
201 ;; because it always better to use %OTHER-POINTER-SUBTYPE-P in that case.
203 (defun simplify-array-unions (input &optional for-typep
)
204 (let* ((array-props sb
!vm
:*specialized-array-element-type-properties
*)
205 (types (if (listp input
) input
(union-type-types input
)))
206 (full-mask (1- (ash 1 (length array-props
))))
208 ;; KLUDGE: counting the input types is a fine preliminary check
209 ;; to avoid extra work, but importantly it (magically) bypasses all
210 ;; this logic during cold-init when CTYPE slots of all SAETPs are nil.
211 ;; SBCL sources mostly don't contain type expressions that benefit
212 ;; from this transform.
213 ;; If, in the not-for-typep case, there aren't at least as many
214 ;; array types as SAETPs, there can't be a covering.
215 ;; In the for-typep case, if there aren't at least half as many,
216 ;; then it couldn't be rewritten as negation.
217 ;; Uber-KLUDGE: using (length types) isn't enough to make the
218 ;; not-for-typep case make it all the way through cold-init.
220 (< (length types
) (floor (length array-props
) 2))
221 (< (count-if #'array-type-p types
) (length array-props
)))
222 (return-from simplify-array-unions input
))
223 (flet ((bucket-match-p (a b
)
224 (and (eq (array-type-complexp a
) (array-type-complexp b
))
225 (equal (array-type-dimensions a
) (array-type-dimensions b
))))
227 (and (array-type-p type
)
228 (neq (array-type-specialized-element-type type
) *wild-type
*)
229 (position (array-type-specialized-element-type type
) array-props
230 :key
#'sb
!vm
:saetp-ctype
:test
#'type
=)))
232 (make-array-type (array-type-dimensions type
)
233 :element-type
*wild-type
*
234 :complexp
(array-type-complexp type
))))
235 ;; Bucket the array types by <dimensions,complexp> where each bucket
236 ;; tracks which SAETPs were seen.
237 ;; Search actual element types by TYPE=, not upgraded types, so that the
238 ;; transform into (ARRAY *) is not lossy. However, if uniting does occur
239 ;; and the resultant OR still contains any array type that upgrades to T,
240 ;; we might want to do yet another reduction because:
241 ;; (SPECIFIER-TYPE '(OR (VECTOR *) (VECTOR BAD))) => #<ARRAY-TYPE VECTOR>
243 (binding* ((bit (saetp-index type
) :exit-if-null
)
244 (bucket (assoc type buckets
:test
#'bucket-match-p
)))
246 (push (setq bucket
(cons type full-mask
)) buckets
))
247 ;; Each _missing_ type is represented by a '1' bit so that
248 ;; a final mask of 0 indicates an exhaustive partitioning.
249 ;; (SETF LOGBITP) would work for us, but CLHS doesn't require it.
250 (setf (cdr bucket
) (logandc2 (cdr bucket
) (ash 1 bit
)))))
253 ;; Maybe compute the complement with respect to (ARRAY *)
254 ;; but never express unions of simple-rank-1 as a type-difference,
255 ;; because widetag testing of those is better.
256 (dolist (type types
(nreverse output
))
258 (and (saetp-index type
)
259 (or (array-type-complexp type
)
260 (not (equal (array-type-dimensions type
) '(*))))
261 (assoc type buckets
:test
#'bucket-match-p
)))
265 (< (logcount (cdr bucket
))
266 (floor (length array-props
) 2)))
268 (dotimes (i (length array-props
))
269 (when (logbitp i
(cdr bucket
)) ; exclude it
270 (push (sb!vm
:saetp-specifier
271 (svref array-props i
)) exclude
)))
272 (setf (cdr bucket
) -
1) ; mark as generated
274 `(and ,(type-specifier (wild type
))
275 ,@(mapcar (lambda (x) `(not (array ,x
)))
277 ((not (eql (cdr bucket
) -
1))
278 ;; noncanonical input is a bug,
279 ;; so assert that bucket is not full.
280 (aver (not (eql (cdr bucket
) 0)))
283 (push disjunct output
)))))
284 ((rassoc 0 buckets
) ; at least one full bucket
285 ;; For each input type subsumed by a full bucket,
286 ;; insert the wild array type for that bucket.
287 (dolist (type types
(apply #'type-union
(nreverse output
)))
288 (let* ((bucket (and (saetp-index type
)
289 (assoc type buckets
:test
#'bucket-match-p
)))
290 (disjunct (cond ((eql (cdr bucket
) 0) ; bucket is full
291 (setf (cdr bucket
) -
1) ; mark as generated
293 ((not (eql (cdr bucket
) -
1))
296 (push disjunct output
)))))
297 (t input
))))) ; no change
299 ;; Given TYPES which is a list of types from a union type, decompose into
300 ;; two unions, one being an OR over types representable as widetags
301 ;; with other-pointer-lowtag, and the other being the difference
302 ;; between the input TYPES and the widetags.
303 ;; This is architecture-independent, but unfortunately the needed VOP can't
304 ;; be defined using DEFINE-TYPE-VOPS, so return (VALUES NIL TYPES) for
305 ;; unsupported backends which can't generate an arbitrary call to %TEST-HEADERS.
306 (defun widetags-from-union-type (types)
307 (setq types
(simplify-array-unions types t
))
308 ;; This seems preferable to a reader-conditional in generic code.
309 ;; There is a unit test that the supported architectures don't generate
310 ;; excessively large code, so hopefully it'll not get broken.
311 (let ((info (info :function
:info
'%other-pointer-subtype-p
)))
312 (unless (and info
(sb!c
::fun-info-templates info
))
313 (return-from widetags-from-union-type
(values nil types
))))
314 (let (widetags remainder
)
318 ((and (array-type-p x
)
319 (equal (array-type-dimensions x
) '(*))
320 (type= (array-type-specialized-element-type x
)
321 (array-type-element-type x
)))
322 (if (eq (array-type-specialized-element-type x
) *wild-type
*)
323 ;; could be done, but probably no merit to implementing
324 ;; maybe/definitely-complex wild-type.
325 (unless (array-type-complexp x
)
326 (map 'list
#'sb
!vm
::saetp-typecode
327 sb
!vm
:*specialized-array-element-type-properties
*))
330 (array-type-element-type x
)
331 sb
!vm
:*specialized-array-element-type-properties
*
332 :key
#'sb
!vm
:saetp-ctype
:test
#'type
=)))
333 (cond ((not (array-type-complexp x
))
334 (sb!vm
:saetp-typecode saetp
))
335 ((sb!vm
:saetp-complex-typecode saetp
)
336 (list* (sb!vm
:saetp-complex-typecode saetp
)
337 (when (eq (array-type-complexp x
) :maybe
)
338 (list (sb!vm
:saetp-typecode saetp
)))))))))
340 (case (classoid-name x
)
341 (symbol sb
!vm
:symbol-header-widetag
) ; plus a hack for nil
342 (system-area-pointer sb
!vm
:sap-widetag
))))))
343 (cond ((not adjunct
) (push x remainder
))
344 ((listp adjunct
) (setq widetags
(nconc adjunct widetags
)))
345 (t (push adjunct widetags
)))))
346 (let ((remainder (nreverse remainder
)))
347 (when (member sb
!vm
:symbol-header-widetag widetags
)
348 ;; If symbol is the only widetag-testable type, it's better
349 ;; to just use symbolp. e.g. (OR SYMBOL CHARACTER) should not
350 ;; become (OR (%OTHER-POINTER-SUBTYPE-P ...)
351 (when (null (rest widetags
))
352 (return-from widetags-from-union-type
(values nil types
)))
353 ;; Manipulate 'remainder' to include NULL since NIL's lowtag
354 ;; isn't other-pointer.
355 (let ((null-type (specifier-type 'null
)))
356 (unless (member null-type remainder
:test
#'csubtypep
)
357 (push null-type remainder
))))
358 (values widetags remainder
))))