1 ;;;; type testing and checking VOPs for the PPC VM
3 ;;;; This software is part of the SBCL system. See the README file for
6 ;;;; This software is derived from the CMU CL system, which was
7 ;;;; written at Carnegie Mellon University and released into the
8 ;;;; public domain. The software is in the public domain and is
9 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
10 ;;;; files for more information.
14 (defun %test-fixnum (value target not-p &key temp)
16 ;; FIXME: again, this 3 should be FIXNUM-MASK
17 (inst andi. temp value 3)
18 (inst b? (if not-p :ne :eq) target)))
20 (defun %test-fixnum-and-headers (value target not-p headers &key temp)
21 (let ((drop-through (gen-label)))
23 (inst andi. temp value 3)
24 (inst beq (if not-p drop-through target)))
25 (%test-headers value target not-p nil headers
26 :drop-through drop-through :temp temp)))
28 (defun %test-immediate (value target not-p immediate &key temp)
30 (inst andi. temp value widetag-mask)
31 (inst cmpwi temp immediate)
32 (inst b? (if not-p :ne :eq) target)))
34 (defun %test-lowtag (value target not-p lowtag &key temp)
36 (inst andi. temp value lowtag-mask)
37 (inst cmpwi temp lowtag)
38 (inst b? (if not-p :ne :eq) target)))
40 (defun %test-lowtag-and-headers (value target not-p lowtag function-p headers
42 (let ((drop-through (gen-label)))
43 (%test-lowtag value (if not-p drop-through target) not-p lowtag
45 (%test-headers value target not-p function-p headers
46 :temp temp :drop-through drop-through)))
48 (defun %test-headers (value target not-p function-p headers
49 &key temp (drop-through (gen-label)))
50 (let ((lowtag (if function-p fun-pointer-lowtag other-pointer-lowtag)))
51 (multiple-value-bind (when-true when-false)
53 (values drop-through target)
54 (values target drop-through))
56 (%test-lowtag value when-false t lowtag :temp temp)
57 (load-type temp value (- lowtag))
58 (do ((remaining headers (cdr remaining)))
60 (let ((header (car remaining))
61 (last (null (cdr remaining))))
64 (inst cmpwi temp header)
66 (inst b? (if not-p :ne :eq) target)
67 (inst beq when-true)))
69 (let ((start (car header))
71 (unless (= start bignum-widetag)
72 (inst cmpwi temp start)
73 (inst blt when-false))
76 (inst b? (if not-p :gt :le) target)
77 (inst ble when-true)))))))
78 (emit-label drop-through)))))
80 ;;; Simple type checking and testing:
81 (define-vop (check-type)
82 (:args (value :target result :scs (any-reg descriptor-reg)))
83 (:results (result :scs (any-reg descriptor-reg)))
84 (:temporary (:scs (non-descriptor-reg)) temp)
86 (:save-p :compute-only))
88 (define-vop (type-predicate)
89 (:args (value :scs (any-reg descriptor-reg)))
93 (:temporary (:scs (non-descriptor-reg)) temp))
95 (defun cost-to-test-types (type-codes)
96 (+ (* 2 (length type-codes))
97 (if (> (apply #'max type-codes) lowtag-limit) 7 2)))
99 (defmacro !define-type-vops (pred-name check-name ptype error-code
101 ;; KLUDGE: ideally, the compiler could
102 ;; derive that it can use the sneaky trap
103 ;; twice mechanism itself. However, one
104 ;; thing at a time...
105 &key mask &allow-other-keys)
106 (let ((cost (cost-to-test-types (mapcar #'eval type-codes))))
109 `((define-vop (,pred-name type-predicate)
110 (:translate ,pred-name)
112 (test-type value target not-p (,@type-codes) :temp temp)))))
114 `((define-vop (,check-name check-type)
117 `((inst andi. temp value ,mask)
118 (inst twi 0 value (error-number-or-lose ',error-code))
119 (inst twi :ne temp ,@(if ;; KLUDGE: At
128 (generate-error-code vop ,error-code value)))
129 (test-type value err-lab t (,@type-codes) :temp temp)
130 (move result value))))))))
132 `((primitive-type-vop ,check-name (:check) ,ptype))))))
135 (def-type-vops fixnump nil nil object-not-fixnum-error
136 sb!vm:even-fixnum-lowtag sb!vm:odd-fixnum-lowtag)
137 (define-vop (check-fixnum check-type)
139 (inst andi. temp value 3)
140 (inst twi 0 value (error-number-or-lose 'object-not-fixnum-error))
141 (inst twi :ne temp 0)
142 (move result value)))
143 (primitive-type-vop check-fixnum (:check) fixnum)
144 (def-type-vops functionp nil nil
145 object-not-fun-error sb!vm:fun-pointer-lowtag)
147 (define-vop (check-fun check-type)
149 (inst andi. temp value 7)
150 (inst twi 0 value (error-number-or-lose 'object-not-fun-error))
151 (inst twi :ne temp sb!vm:fun-pointer-lowtag)
152 (move result value)))
153 (primitive-type-vop check-fun (:check) function)
155 (def-type-vops listp nil nil
156 object-not-list-error sb!vm:list-pointer-lowtag)
157 (define-vop (check-list check-type)
159 (inst andi. temp value 7)
160 (inst twi 0 value (error-number-or-lose 'object-not-list-error))
161 (inst twi :ne temp sb!vm:list-pointer-lowtag)
162 (move result value)))
163 (primitive-type-vop check-list (:check) list)
165 (def-type-vops %instancep nil nil
166 object-not-instance-error sb!vm:instance-pointer-lowtag)
167 (define-vop (check-instance check-type)
169 (inst andi. temp value 7)
170 (inst twi 0 value (error-number-or-lose 'object-not-instance-error))
171 (inst twi :ne temp sb!vm:instance-pointer-lowtag)
172 (move result value)))
173 (primitive-type-vop check-instance (:check) instance)
176 (def-type-vops bignump check-bignum bignum
177 object-not-bignum-error sb!vm:bignum-widetag)
179 (def-type-vops ratiop check-ratio ratio
180 object-not-ratio-error sb!vm:ratio-widetag)
182 (def-type-vops complexp check-complex complex
183 object-not-complex-error sb!vm:complex-widetag
184 complex-single-float-widetag complex-double-float-widetag)
186 (def-type-vops complex-rational-p check-complex-rational nil
187 object-not-complex-rational-error complex-widetag)
189 (def-type-vops complex-float-p check-complex-float nil
190 object-not-complex-float-error
191 complex-single-float-widetag complex-double-float-widetag)
193 (def-type-vops complex-single-float-p check-complex-single-float
194 complex-single-float object-not-complex-single-float-error
195 complex-single-float-widetag)
197 (def-type-vops complex-double-float-p check-complex-double-float
198 complex-double-float object-not-complex-double-float-error
199 complex-double-float-widetag)
201 (def-type-vops single-float-p check-single-float single-float
202 object-not-single-float-error sb!vm:single-float-widetag)
204 (def-type-vops double-float-p check-double-float double-float
205 object-not-double-float-error sb!vm:double-float-widetag)
207 (def-type-vops simple-string-p check-simple-string simple-string
208 object-not-simple-string-error sb!vm:simple-string-widetag)
210 (def-type-vops simple-bit-vector-p check-simple-bit-vector simple-bit-vector
211 object-not-simple-bit-vector-error simple-bit-vector-widetag)
213 (def-type-vops simple-vector-p check-simple-vector simple-vector
214 object-not-simple-vector-error sb!vm:simple-vector-widetag)
216 (def-type-vops simple-array-unsigned-byte-2-p
217 check-simple-array-unsigned-byte-2
218 simple-array-unsigned-byte-2
219 object-not-simple-array-unsigned-byte-2-error
220 sb!vm:simple-array-unsigned-byte-2-widetag)
222 (def-type-vops simple-array-unsigned-byte-4-p
223 check-simple-array-unsigned-byte-4
224 simple-array-unsigned-byte-4
225 object-not-simple-array-unsigned-byte-4-error
226 sb!vm:simple-array-unsigned-byte-4-widetag)
228 (def-type-vops simple-array-unsigned-byte-8-p
229 check-simple-array-unsigned-byte-8
230 simple-array-unsigned-byte-8
231 object-not-simple-array-unsigned-byte-8-error
232 sb!vm:simple-array-unsigned-byte-8-widetag)
234 (def-type-vops simple-array-unsigned-byte-16-p
235 check-simple-array-unsigned-byte-16
236 simple-array-unsigned-byte-16
237 object-not-simple-array-unsigned-byte-16-error
238 sb!vm:simple-array-unsigned-byte-16-widetag)
240 (def-type-vops simple-array-unsigned-byte-32-p
241 check-simple-array-unsigned-byte-32
242 simple-array-unsigned-byte-32
243 object-not-simple-array-unsigned-byte-32-error
244 sb!vm:simple-array-unsigned-byte-32-widetag)
246 (def-type-vops simple-array-signed-byte-8-p
247 check-simple-array-signed-byte-8
248 simple-array-signed-byte-8
249 object-not-simple-array-signed-byte-8-error
250 simple-array-signed-byte-8-widetag)
252 (def-type-vops simple-array-signed-byte-16-p
253 check-simple-array-signed-byte-16
254 simple-array-signed-byte-16
255 object-not-simple-array-signed-byte-16-error
256 simple-array-signed-byte-16-widetag)
258 (def-type-vops simple-array-signed-byte-30-p
259 check-simple-array-signed-byte-30
260 simple-array-signed-byte-30
261 object-not-simple-array-signed-byte-30-error
262 simple-array-signed-byte-30-widetag)
264 (def-type-vops simple-array-signed-byte-32-p
265 check-simple-array-signed-byte-32
266 simple-array-signed-byte-32
267 object-not-simple-array-signed-byte-32-error
268 simple-array-signed-byte-32-widetag)
270 (def-type-vops simple-array-single-float-p check-simple-array-single-float
271 simple-array-single-float object-not-simple-array-single-float-error
272 sb!vm:simple-array-single-float-widetag)
274 (def-type-vops simple-array-double-float-p check-simple-array-double-float
275 simple-array-double-float object-not-simple-array-double-float-error
276 sb!vm:simple-array-double-float-widetag)
278 (def-type-vops simple-array-complex-single-float-p
279 check-simple-array-complex-single-float
280 simple-array-complex-single-float
281 object-not-simple-array-complex-single-float-error
282 simple-array-complex-single-float-widetag)
284 (def-type-vops simple-array-complex-double-float-p
285 check-simple-array-complex-double-float
286 simple-array-complex-double-float
287 object-not-simple-array-complex-double-float-error
288 simple-array-complex-double-float-widetag)
290 (def-type-vops base-char-p check-base-char base-char
291 object-not-base-char-error sb!vm:base-char-widetag)
293 (def-type-vops system-area-pointer-p check-system-area-pointer
294 system-area-pointer object-not-sap-error sb!vm:sap-widetag)
296 (def-type-vops weak-pointer-p check-weak-pointer weak-pointer
297 object-not-weak-pointer-error sb!vm:weak-pointer-widetag)
299 (def-type-vops code-component-p nil nil nil
300 sb!vm:code-header-widetag)
302 (def-type-vops lra-p nil nil nil
303 sb!vm:return-pc-header-widetag)
305 (def-type-vops fdefn-p nil nil nil
308 (def-type-vops funcallable-instance-p nil nil nil
309 sb!vm:funcallable-instance-header-widetag)
311 (def-type-vops array-header-p nil nil nil
312 sb!vm:simple-array-widetag sb!vm:complex-string-widetag sb!vm:complex-bit-vector-widetag
313 sb!vm:complex-vector-widetag sb!vm:complex-array-widetag)
315 (def-type-vops nil check-function-or-symbol nil object-not-function-or-symbol-error
316 sb!vm:fun-pointer-lowtag sb!vm:symbol-header-widetag)
318 (def-type-vops stringp check-string nil object-not-string-error
319 sb!vm:simple-string-widetag sb!vm:complex-string-widetag)
321 (def-type-vops complex-vector-p check-complex-vector nil
322 object-not-complex-vector-error complex-vector-widetag)
324 (def-type-vops bit-vector-p check-bit-vector nil object-not-bit-vector-error
325 sb!vm:simple-bit-vector-widetag sb!vm:complex-bit-vector-widetag)
327 (def-type-vops vectorp check-vector nil object-not-vector-error
328 simple-string-widetag simple-bit-vector-widetag simple-vector-widetag
329 simple-array-unsigned-byte-2-widetag simple-array-unsigned-byte-4-widetag
330 simple-array-unsigned-byte-8-widetag simple-array-unsigned-byte-16-widetag
331 simple-array-unsigned-byte-32-widetag
332 simple-array-signed-byte-8-widetag simple-array-signed-byte-16-widetag
333 simple-array-signed-byte-30-widetag simple-array-signed-byte-32-widetag
334 simple-array-single-float-widetag simple-array-double-float-widetag
335 simple-array-complex-single-float-widetag
336 simple-array-complex-double-float-widetag
337 complex-string-widetag complex-bit-vector-widetag complex-vector-widetag)
339 (def-type-vops simple-array-p check-simple-array nil object-not-simple-array-error
340 simple-array-widetag simple-string-widetag simple-bit-vector-widetag
341 simple-vector-widetag simple-array-unsigned-byte-2-widetag
342 simple-array-unsigned-byte-4-widetag simple-array-unsigned-byte-8-widetag
343 simple-array-unsigned-byte-16-widetag simple-array-unsigned-byte-32-widetag
344 simple-array-signed-byte-8-widetag simple-array-signed-byte-16-widetag
345 simple-array-signed-byte-30-widetag simple-array-signed-byte-32-widetag
346 simple-array-single-float-widetag simple-array-double-float-widetag
347 simple-array-complex-single-float-widetag
348 simple-array-complex-double-float-widetag)
350 (def-type-vops arrayp check-array nil object-not-array-error
351 simple-array-widetag simple-string-widetag simple-bit-vector-widetag
352 simple-vector-widetag simple-array-unsigned-byte-2-widetag
353 simple-array-unsigned-byte-4-widetag simple-array-unsigned-byte-8-widetag
354 simple-array-unsigned-byte-16-widetag simple-array-unsigned-byte-32-widetag
355 simple-array-signed-byte-8-widetag simple-array-signed-byte-16-widetag
356 simple-array-signed-byte-30-widetag simple-array-signed-byte-32-widetag
357 simple-array-single-float-widetag simple-array-double-float-widetag
358 simple-array-complex-single-float-widetag
359 simple-array-complex-double-float-widetag
360 complex-string-widetag complex-bit-vector-widetag complex-vector-widetag
361 complex-array-widetag)
363 (def-type-vops numberp check-number nil object-not-number-error
364 even-fixnum-lowtag odd-fixnum-lowtag bignum-widetag ratio-widetag
365 single-float-widetag double-float-widetag complex-widetag
366 complex-single-float-widetag complex-double-float-widetag)
368 (def-type-vops rationalp check-rational nil object-not-rational-error
369 sb!vm:even-fixnum-lowtag sb!vm:odd-fixnum-lowtag sb!vm:ratio-widetag sb!vm:bignum-widetag)
371 (def-type-vops integerp check-integer nil object-not-integer-error
372 sb!vm:even-fixnum-lowtag sb!vm:odd-fixnum-lowtag sb!vm:bignum-widetag)
374 (def-type-vops floatp check-float nil object-not-float-error
375 sb!vm:single-float-widetag sb!vm:double-float-widetag)
377 (def-type-vops realp check-real nil object-not-real-error
378 sb!vm:even-fixnum-lowtag sb!vm:odd-fixnum-lowtag sb!vm:ratio-widetag sb!vm:bignum-widetag
379 sb!vm:single-float-widetag sb!vm:double-float-widetag))
382 ;;;; Other integer ranges.
384 ;;; A (signed-byte 32) can be represented with either fixnum or a bignum with
385 ;;; exactly one digit.
387 (define-vop (signed-byte-32-p type-predicate)
388 (:translate signed-byte-32-p)
390 (let ((not-target (gen-label)))
394 (values not-target target)
395 (values target not-target))
396 (inst andi. temp value #x3)
398 (test-type value nope t (other-pointer-lowtag) :temp temp)
399 (loadw temp value 0 other-pointer-lowtag)
400 (inst cmpwi temp (+ (ash 1 n-widetag-bits)
402 (inst b? (if not-p :ne :eq) target)
403 (emit-label not-target)))))
405 (define-vop (check-signed-byte-32 check-type)
407 (let ((nope (generate-error-code vop object-not-signed-byte-32-error value))
409 (inst andi. temp value #x3)
411 (test-type value nope t (other-pointer-lowtag) :temp temp)
412 (loadw temp value 0 other-pointer-lowtag)
413 (inst cmpwi temp (+ (ash 1 n-widetag-bits) bignum-widetag))
416 (move result value))))
419 ;;; An (unsigned-byte 32) can be represented with either a positive fixnum, a
420 ;;; bignum with exactly one positive digit, or a bignum with exactly two digits
421 ;;; and the second digit all zeros.
423 (define-vop (unsigned-byte-32-p type-predicate)
424 (:translate unsigned-byte-32-p)
426 (let ((not-target (gen-label))
427 (single-word (gen-label))
428 (fixnum (gen-label)))
432 (values not-target target)
433 (values target not-target))
435 (inst andi. temp value #x3)
436 (inst cmpwi :cr1 value 0)
439 ;; If not, is it an other pointer?
440 (test-type value nope t (other-pointer-lowtag) :temp temp)
442 (loadw temp value 0 other-pointer-lowtag)
444 (inst cmpwi temp (+ (ash 1 n-widetag-bits) bignum-widetag))
445 (inst beq single-word)
446 ;; If it's other than two, we can't be an (unsigned-byte 32)
447 (inst cmpwi temp (+ (ash 2 n-widetag-bits) bignum-widetag))
449 ;; Get the second digit.
450 (loadw temp value (1+ bignum-digits-offset) other-pointer-lowtag)
451 ;; All zeros, its an (unsigned-byte 32).
454 ;; Otherwise, it isn't.
457 (emit-label single-word)
458 ;; Get the single digit.
459 (loadw temp value bignum-digits-offset other-pointer-lowtag)
460 (inst cmpwi :cr1 temp 0)
462 ;; positive implies (unsigned-byte 32).
464 (inst b? :cr1 (if not-p :lt :ge) target)
466 (emit-label not-target)))))
468 (define-vop (check-unsigned-byte-32 check-type)
471 (generate-error-code vop object-not-unsigned-byte-32-error value))
474 (single-word (gen-label)))
476 (inst andi. temp value #x3)
477 (inst cmpwi :cr1 value 0)
480 ;; If not, is it an other pointer?
481 (test-type value nope t (other-pointer-lowtag) :temp temp)
482 ;; Get the number of digits.
483 (loadw temp value 0 other-pointer-lowtag)
485 (inst cmpwi temp (+ (ash 1 n-widetag-bits) bignum-widetag))
486 (inst beq single-word)
487 ;; If it's other than two, we can't be an (unsigned-byte 32)
488 (inst cmpwi temp (+ (ash 2 n-widetag-bits) bignum-widetag))
490 ;; Get the second digit.
491 (loadw temp value (1+ bignum-digits-offset) other-pointer-lowtag)
492 ;; All zeros, its an (unsigned-byte 32).
495 ;; Otherwise, it isn't.
498 (emit-label single-word)
499 ;; Get the single digit.
500 (loadw temp value bignum-digits-offset other-pointer-lowtag)
501 ;; positive implies (unsigned-byte 32).
502 (inst cmpwi :cr1 temp 0)
508 (move result value))))
513 ;;;; List/symbol types:
515 ;;; symbolp (or symbol (eq nil))
516 ;;; consp (and list (not (eq nil)))
518 (define-vop (symbolp type-predicate)
521 (let* ((drop-thru (gen-label))
522 (is-symbol-label (if not-p drop-thru target)))
523 (inst cmpw value null-tn)
524 (inst beq is-symbol-label)
525 (test-type value target not-p (symbol-header-widetag) :temp temp)
526 (emit-label drop-thru))))
528 (define-vop (check-symbol check-type)
530 (let ((drop-thru (gen-label))
531 (error (generate-error-code vop object-not-symbol-error value)))
532 (inst cmpw value null-tn)
534 (test-type value error t (symbol-header-widetag) :temp temp)
535 (emit-label drop-thru)
536 (move result value))))
538 (define-vop (consp type-predicate)
541 (let* ((drop-thru (gen-label))
542 (is-not-cons-label (if not-p target drop-thru)))
543 (inst cmpw value null-tn)
544 (inst beq is-not-cons-label)
545 (test-type value target not-p (list-pointer-lowtag) :temp temp)
546 (emit-label drop-thru))))
548 (define-vop (check-cons check-type)
550 (let ((error (generate-error-code vop object-not-cons-error value)))
551 (inst cmpw value null-tn)
553 (test-type value error t (list-pointer-lowtag) :temp temp)
554 (move result value))))