5 ;;;; Test generation utilities.
7 (eval-when (:compile-toplevel :execute)
8 (defparameter *immediate-types*
9 (list unbound-marker-widetag base-char-widetag))
11 (defparameter *fun-header-widetags*
12 (list funcallable-instance-header-widetag
13 simple-fun-header-widetag
14 closure-fun-header-widetag
15 closure-header-widetag))
17 (defun canonicalize-headers (headers)
21 (delta (- other-immediate-1-lowtag other-immediate-0-lowtag)))
23 (results (if (= start prev)
26 (dolist (header (sort headers #'<))
30 ((= header (+ prev delta))
40 (macrolet ((test-type (value temp target not-p &rest type-codes)
41 ;; Determine what interesting combinations we need to test for.
42 (let* ((type-codes (mapcar #'eval type-codes))
43 (fixnump (and (member even-fixnum-lowtag type-codes)
44 (member odd-fixnum-lowtag type-codes)
46 (lowtags (remove lowtag-limit type-codes :test #'<))
47 (extended (remove lowtag-limit type-codes :test #'>))
48 (immediates (intersection extended *immediate-types* :test #'eql))
49 (headers (set-difference extended *immediate-types* :test #'eql))
50 (function-p (if (intersection headers *fun-header-widetags*)
51 (if (subsetp headers *fun-header-widetags*)
53 (error "Can't test for mix of function subtypes ~
54 and normal header types."))
57 (error "Must supply at least on type for test-type."))
60 (when (remove-if #'(lambda (x)
61 (or (= x even-fixnum-lowtag)
62 (= x odd-fixnum-lowtag)))
64 (error "Can't mix fixnum testing with other lowtags."))
66 (error "Can't mix fixnum testing with function subtype testing."))
68 (error "Can't mix fixnum testing with other immediates."))
70 `(%test-fixnum-and-headers ,value ,temp ,target ,not-p
71 ',(canonicalize-headers headers))
72 `(%test-fixnum ,value ,temp ,target ,not-p)))
75 (error "Can't mix testing of immediates with testing of headers."))
77 (error "Can't mix testing of immediates with testing of lowtags."))
78 (when (cdr immediates)
79 (error "Can't test multiple immediates at the same time."))
80 `(%test-immediate ,value ,temp ,target ,not-p ,(car immediates)))
83 (error "Can't test multiple lowtags at the same time."))
85 `(%test-lowtag-and-headers
86 ,value ,temp ,target ,not-p ,(car lowtags)
87 ,function-p ',(canonicalize-headers headers))
88 `(%test-lowtag ,value ,temp ,target ,not-p ,(car lowtags))))
90 `(%test-headers ,value ,temp ,target ,not-p ,function-p
91 ',(canonicalize-headers headers)))
93 (error "Nothing to test?"))))))
95 (defun %test-fixnum (value temp target not-p)
97 (inst and temp value 3)
99 (inst bne temp zero-tn target)
100 (inst beq temp zero-tn target))
103 (defun %test-fixnum-and-headers (value temp target not-p headers)
104 (let ((drop-through (gen-label)))
106 (inst and temp value 3)
107 (inst beq temp zero-tn (if not-p drop-through target)))
108 (%test-headers value temp target not-p nil headers drop-through)))
110 (defun %test-immediate (value temp target not-p immediate)
112 (inst and temp value 255)
113 (inst xor temp immediate)
115 (inst bne temp zero-tn target)
116 (inst beq temp zero-tn target))
119 (defun %test-lowtag (value temp target not-p lowtag &optional skip-nop)
121 (inst and temp value lowtag-mask)
122 (inst xor temp lowtag)
124 (inst bne temp zero-tn target)
125 (inst beq temp zero-tn target))
129 (defun %test-lowtag-and-headers (value temp target not-p lowtag
131 (let ((drop-through (gen-label)))
132 (%test-lowtag value temp (if not-p drop-through target) nil lowtag t)
133 (%test-headers value temp target not-p function-p headers drop-through)))
135 (defun %test-headers (value temp target not-p function-p headers
136 &optional (drop-through (gen-label)))
137 (let ((lowtag (if function-p fun-pointer-lowtag other-pointer-lowtag)))
139 (when-true when-false)
140 ;; WHEN-TRUE and WHEN-FALSE are the labels to branch to when
141 ;; we know it's true and when we know it's false respectively.
143 (values drop-through target)
144 (values target drop-through))
146 (%test-lowtag value temp when-false t lowtag)
147 (load-type temp value (- lowtag))
150 (do ((remaining headers (cdr remaining)))
152 (let ((header (car remaining))
153 (last (null (cdr remaining))))
156 (inst subu temp (- header delta))
160 (inst bne temp zero-tn target)
161 (inst beq temp zero-tn target))
162 (inst beq temp zero-tn when-true)))
164 (let ((start (car header))
166 (unless (= start bignum-widetag)
167 (inst subu temp (- start delta))
169 (inst bltz temp when-false))
170 (inst subu temp (- end delta))
174 (inst bgtz temp target)
175 (inst blez temp target))
176 (inst blez temp when-true))))))))
178 (emit-label drop-through)))))
182 ;;;; Type checking and testing:
184 (define-vop (check-type)
185 (:args (value :target result :scs (any-reg descriptor-reg)))
186 (:results (result :scs (any-reg descriptor-reg)))
187 (:temporary (:scs (non-descriptor-reg) :to (:result 0)) temp)
189 (:save-p :compute-only))
191 (define-vop (type-predicate)
192 (:args (value :scs (any-reg descriptor-reg)))
193 (:temporary (:scs (non-descriptor-reg)) temp)
196 (:policy :fast-safe))
198 (eval-when (:compile-toplevel :execute)
199 (defun cost-to-test-types (type-codes)
200 (+ (* 2 (length type-codes))
201 (if (> (apply #'max type-codes) lowtag-limit) 7 2))))
203 (defmacro def-type-vops (pred-name check-name ptype error-code
205 (let ((cost (cost-to-test-types (mapcar #'eval type-codes))))
208 `((define-vop (,pred-name type-predicate)
209 (:translate ,pred-name)
211 (test-type value temp target not-p ,@type-codes)))))
213 `((define-vop (,check-name check-type)
216 (generate-error-code vop ,error-code value)))
217 (test-type value temp err-lab t ,@type-codes)
218 (move result value))))))
220 `((primitive-type-vop ,check-name (:check) ,ptype))))))
222 (def-type-vops fixnump check-fixnum fixnum object-not-fixnum-error
223 even-fixnum-lowtag odd-fixnum-lowtag)
225 (def-type-vops functionp check-fun function
226 object-not-fun-error fun-pointer-lowtag)
228 (def-type-vops listp check-list list object-not-list-error
231 (def-type-vops %instancep check-instance instance object-not-instance-error
232 instance-pointer-lowtag)
234 (def-type-vops bignump check-bignum bignum
235 object-not-bignum-error bignum-widetag)
237 (def-type-vops ratiop check-ratio ratio
238 object-not-ratio-error ratio-widetag)
240 (def-type-vops complexp check-complex complex object-not-complex-error
241 complex-widetag complex-single-float-widetag complex-double-float-widetag)
243 (def-type-vops complex-rational-p check-complex-rational nil
244 object-not-complex-rational-error complex-widetag)
246 (def-type-vops complex-float-p check-complex-float nil
247 object-not-complex-float-error
248 complex-single-float-widetag complex-double-float-widetag)
250 (def-type-vops complex-single-float-p check-complex-single-float
251 complex-single-float object-not-complex-single-float-error
252 complex-single-float-widetag)
254 (def-type-vops complex-double-float-p check-complex-double-float
255 complex-double-float object-not-complex-double-float-error
256 complex-double-float-widetag)
258 (def-type-vops single-float-p check-single-float single-float
259 object-not-single-float-error single-float-widetag)
261 (def-type-vops double-float-p check-double-float double-float
262 object-not-double-float-error double-float-widetag)
264 (def-type-vops simple-string-p check-simple-string simple-string
265 object-not-simple-string-error simple-string-widetag)
267 (def-type-vops simple-bit-vector-p check-simple-bit-vector simple-bit-vector
268 object-not-simple-bit-vector-error simple-bit-vector-widetag)
270 (def-type-vops simple-vector-p check-simple-vector simple-vector
271 object-not-simple-vector-error simple-vector-widetag)
273 (def-type-vops simple-array-unsigned-byte-2-p
274 check-simple-array-unsigned-byte-2
275 simple-array-unsigned-byte-2
276 object-not-simple-array-unsigned-byte-2-error
277 simple-array-unsigned-byte-2-widetag)
279 (def-type-vops simple-array-unsigned-byte-4-p
280 check-simple-array-unsigned-byte-4
281 simple-array-unsigned-byte-4
282 object-not-simple-array-unsigned-byte-4-error
283 simple-array-unsigned-byte-4-widetag)
285 (def-type-vops simple-array-unsigned-byte-8-p
286 check-simple-array-unsigned-byte-8
287 simple-array-unsigned-byte-8
288 object-not-simple-array-unsigned-byte-8-error
289 simple-array-unsigned-byte-8-widetag)
291 (def-type-vops simple-array-unsigned-byte-16-p
292 check-simple-array-unsigned-byte-16
293 simple-array-unsigned-byte-16
294 object-not-simple-array-unsigned-byte-16-error
295 simple-array-unsigned-byte-16-widetag)
297 (def-type-vops simple-array-unsigned-byte-32-p
298 check-simple-array-unsigned-byte-32
299 simple-array-unsigned-byte-32
300 object-not-simple-array-unsigned-byte-32-error
301 simple-array-unsigned-byte-32-widetag)
303 (def-type-vops simple-array-signed-byte-8-p
304 check-simple-array-signed-byte-8
305 simple-array-signed-byte-8
306 object-not-simple-array-signed-byte-8-error
307 simple-array-signed-byte-8-widetag)
309 (def-type-vops simple-array-signed-byte-16-p
310 check-simple-array-signed-byte-16
311 simple-array-signed-byte-16
312 object-not-simple-array-signed-byte-16-error
313 simple-array-signed-byte-16-widetag)
315 (def-type-vops simple-array-signed-byte-30-p
316 check-simple-array-signed-byte-30
317 simple-array-signed-byte-30
318 object-not-simple-array-signed-byte-30-error
319 simple-array-signed-byte-30-widetag)
321 (def-type-vops simple-array-signed-byte-32-p
322 check-simple-array-signed-byte-32
323 simple-array-signed-byte-32
324 object-not-simple-array-signed-byte-32-error
325 simple-array-signed-byte-32-widetag)
327 (def-type-vops simple-array-single-float-p check-simple-array-single-float
328 simple-array-single-float object-not-simple-array-single-float-error
329 simple-array-single-float-widetag)
331 (def-type-vops simple-array-double-float-p check-simple-array-double-float
332 simple-array-double-float object-not-simple-array-double-float-error
333 simple-array-double-float-widetag)
335 (def-type-vops simple-array-complex-single-float-p
336 check-simple-array-complex-single-float
337 simple-array-complex-single-float
338 object-not-simple-array-complex-single-float-error
339 simple-array-complex-single-float-widetag)
341 (def-type-vops simple-array-complex-double-float-p
342 check-simple-array-complex-double-float
343 simple-array-complex-double-float
344 object-not-simple-array-complex-double-float-error
345 simple-array-complex-double-float-widetag)
347 (def-type-vops base-char-p check-base-char base-char
348 object-not-base-char-error base-char-widetag)
350 (def-type-vops system-area-pointer-p check-system-area-pointer
351 system-area-pointer object-not-sap-error sap-widetag)
353 (def-type-vops weak-pointer-p check-weak-pointer weak-pointer
354 object-not-weak-pointer-error weak-pointer-widetag)
356 (def-type-vops code-component-p nil nil nil
359 (def-type-vops lra-p nil nil nil
360 return-pc-header-widetag)
362 (def-type-vops fdefn-p nil nil nil
365 (def-type-vops funcallable-instance-p nil nil nil
366 funcallable-instance-header-widetag)
368 (def-type-vops array-header-p nil nil nil
369 simple-array-widetag complex-string-widetag complex-bit-vector-widetag
370 complex-vector-widetag complex-array-widetag)
372 (def-type-vops stringp check-string nil object-not-string-error
373 simple-string-widetag complex-string-widetag)
375 (def-type-vops bit-vector-p check-bit-vector nil object-not-bit-vector-error
376 simple-bit-vector-widetag complex-bit-vector-widetag)
378 (def-type-vops vectorp check-vector nil object-not-vector-error
379 simple-string-widetag simple-bit-vector-widetag simple-vector-widetag
380 simple-array-unsigned-byte-2-widetag simple-array-unsigned-byte-4-widetag
381 simple-array-unsigned-byte-8-widetag simple-array-unsigned-byte-16-widetag
382 simple-array-unsigned-byte-32-widetag
383 simple-array-signed-byte-8-widetag simple-array-signed-byte-16-widetag
384 simple-array-signed-byte-30-widetag simple-array-signed-byte-32-widetag
385 simple-array-single-float-widetag simple-array-double-float-widetag
386 simple-array-complex-single-float-widetag
387 simple-array-complex-double-float-widetag
388 complex-string-widetag complex-bit-vector-widetag complex-vector-widetag)
390 (def-type-vops complex-vector-p check-complex-vector nil object-not-complex-vector-error
391 complex-vector-widetag)
393 (def-type-vops simple-array-p check-simple-array nil object-not-simple-array-error
394 simple-array-widetag simple-string-widetag simple-bit-vector-widetag
395 simple-vector-widetag simple-array-unsigned-byte-2-widetag
396 simple-array-unsigned-byte-4-widetag simple-array-unsigned-byte-8-widetag
397 simple-array-unsigned-byte-16-widetag simple-array-unsigned-byte-32-widetag
398 simple-array-signed-byte-8-widetag simple-array-signed-byte-16-widetag
399 simple-array-signed-byte-30-widetag simple-array-signed-byte-32-widetag
400 simple-array-single-float-widetag simple-array-double-float-widetag
401 simple-array-complex-single-float-widetag
402 simple-array-complex-double-float-widetag)
404 (def-type-vops arrayp check-array nil object-not-array-error
405 simple-array-widetag simple-string-widetag simple-bit-vector-widetag
406 simple-vector-widetag simple-array-unsigned-byte-2-widetag
407 simple-array-unsigned-byte-4-widetag simple-array-unsigned-byte-8-widetag
408 simple-array-unsigned-byte-16-widetag simple-array-unsigned-byte-32-widetag
409 simple-array-signed-byte-8-widetag simple-array-signed-byte-16-widetag
410 simple-array-signed-byte-30-widetag simple-array-signed-byte-32-widetag
411 simple-array-single-float-widetag simple-array-double-float-widetag
412 simple-array-complex-single-float-widetag
413 simple-array-complex-double-float-widetag
414 complex-string-widetag complex-bit-vector-widetag complex-vector-widetag
415 complex-array-widetag)
417 (def-type-vops numberp check-number nil object-not-number-error
418 even-fixnum-lowtag odd-fixnum-lowtag bignum-widetag ratio-widetag
419 single-float-widetag double-float-widetag complex-widetag
420 complex-single-float-widetag complex-double-float-widetag)
422 (def-type-vops rationalp check-rational nil object-not-rational-error
423 even-fixnum-lowtag odd-fixnum-lowtag ratio-widetag bignum-widetag)
425 (def-type-vops integerp check-integer nil object-not-integer-error
426 even-fixnum-lowtag odd-fixnum-lowtag bignum-widetag)
428 (def-type-vops floatp check-float nil object-not-float-error
429 single-float-widetag double-float-widetag)
431 (def-type-vops realp check-real nil object-not-real-error
432 even-fixnum-lowtag odd-fixnum-lowtag ratio-widetag bignum-widetag
433 single-float-widetag double-float-widetag)
436 ;;;; Other integer ranges.
438 ;;; A (signed-byte 32) can be represented with either fixnum or a bignum with
439 ;;; exactly one digit.
441 (defun signed-byte-32-test (value temp not-p target not-target)
445 (values not-target target)
446 (values target not-target))
448 (inst and temp value 3)
449 (inst beq temp zero-tn yep)
450 (inst and temp value lowtag-mask)
451 (inst xor temp other-pointer-lowtag)
452 (inst bne temp zero-tn nope)
454 (loadw temp value 0 other-pointer-lowtag)
455 (inst xor temp (+ (ash 1 n-widetag-bits) bignum-widetag))
457 (inst bne temp zero-tn target)
458 (inst beq temp zero-tn target))
462 (define-vop (signed-byte-32-p type-predicate)
463 (:translate signed-byte-32-p)
465 (signed-byte-32-test value temp not-p target not-target)
468 (define-vop (check-signed-byte-32 check-type)
470 (let ((loose (generate-error-code vop object-not-signed-byte-32-error
472 (signed-byte-32-test value temp t loose okay))
474 (move result value)))
476 ;;; An (unsigned-byte 32) can be represented with either a positive fixnum, a
477 ;;; bignum with exactly one positive digit, or a bignum with exactly two digits
478 ;;; and the second digit all zeros.
480 (defun unsigned-byte-32-test (value temp not-p target not-target)
481 (multiple-value-bind (yep nope)
483 (values not-target target)
484 (values target not-target))
487 (inst and temp value 3)
488 (inst beq temp zero-tn fixnum)
489 (inst move temp value)
491 ;; If not, is it an other pointer?
492 (inst and temp value lowtag-mask)
493 (inst xor temp other-pointer-lowtag)
494 (inst bne temp zero-tn nope)
497 (loadw temp value 0 other-pointer-lowtag)
499 (inst xor temp (+ (ash 1 n-widetag-bits) bignum-widetag))
500 (inst beq temp zero-tn single-word)
501 ;; If it's other than two, we can't be an (unsigned-byte 32)
502 (inst xor temp (logxor (+ (ash 1 n-widetag-bits) bignum-widetag)
503 (+ (ash 2 n-widetag-bits) bignum-widetag)))
504 (inst bne temp zero-tn nope)
505 ;; Get the second digit.
506 (loadw temp value (1+ bignum-digits-offset) other-pointer-lowtag)
507 ;; All zeros, its an (unsigned-byte 32).
508 (inst beq temp zero-tn yep)
513 ;; Get the single digit.
514 (loadw temp value bignum-digits-offset other-pointer-lowtag)
516 ;; positive implies (unsigned-byte 32).
519 (inst bltz temp target)
520 (inst bgez temp target))
524 (define-vop (unsigned-byte-32-p type-predicate)
525 (:translate unsigned-byte-32-p)
527 (unsigned-byte-32-test value temp not-p target not-target)
530 (define-vop (check-unsigned-byte-32 check-type)
532 (let ((loose (generate-error-code vop object-not-unsigned-byte-32-error
534 (unsigned-byte-32-test value temp t loose okay))
536 (move result value)))
540 ;;;; List/symbol types:
542 ;;; symbolp (or symbol (eq nil))
543 ;;; consp (and list (not (eq nil)))
545 (define-vop (symbolp type-predicate)
548 (inst beq value null-tn (if not-p drop-thru target))
549 (test-type value temp target not-p symbol-header-widetag)
552 (define-vop (check-symbol check-type)
554 (inst beq value null-tn drop-thru)
555 (let ((error (generate-error-code vop object-not-symbol-error value)))
556 (test-type value temp error t symbol-header-widetag))
558 (move result value)))
560 (define-vop (consp type-predicate)
563 (inst beq value null-tn (if not-p target drop-thru))
564 (test-type value temp target not-p list-pointer-lowtag)
567 (define-vop (check-cons check-type)
569 (let ((error (generate-error-code vop object-not-cons-error value)))
570 (inst beq value null-tn error)
571 (test-type value temp error t list-pointer-lowtag))
572 (move result value)))