/src/compiler/alpha/type-vops.lisp

https://github.com/JonathanSmith/sbcl · Lisp · 276 lines · 217 code · 28 blank · 31 comment · 0 complexity · 9e9f2d07b83b1c48552770344a18daa4 MD5 · raw file

  1. ;;;; type testing and checking VOPs for the Alpha VM
  2. ;;;; This software is part of the SBCL system. See the README file for
  3. ;;;; more information.
  4. ;;;;
  5. ;;;; This software is derived from the CMU CL system, which was
  6. ;;;; written at Carnegie Mellon University and released into the
  7. ;;;; public domain. The software is in the public domain and is
  8. ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
  9. ;;;; files for more information.
  10. (in-package "SB!VM")
  11. (defun %test-fixnum (value target not-p &key temp)
  12. (assemble ()
  13. (inst and value fixnum-tag-mask temp)
  14. (if not-p
  15. (inst bne temp target)
  16. (inst beq temp target))))
  17. (defun %test-fixnum-and-headers (value target not-p headers &key temp)
  18. (let ((drop-through (gen-label)))
  19. (assemble ()
  20. (inst and value fixnum-tag-mask temp)
  21. (inst beq temp (if not-p drop-through target)))
  22. (%test-headers value target not-p nil headers
  23. :drop-through drop-through :temp temp)))
  24. (defun %test-immediate (value target not-p immediate &key temp)
  25. (assemble ()
  26. (inst and value 255 temp)
  27. (inst xor temp immediate temp)
  28. (if not-p
  29. (inst bne temp target)
  30. (inst beq temp target))))
  31. (defun %test-lowtag (value target not-p lowtag &key temp)
  32. (assemble ()
  33. (inst and value lowtag-mask temp)
  34. (inst xor temp lowtag temp)
  35. (if not-p
  36. (inst bne temp target)
  37. (inst beq temp target))))
  38. (defun %test-headers (value target not-p function-p headers
  39. &key (drop-through (gen-label)) temp)
  40. (let ((lowtag (if function-p fun-pointer-lowtag other-pointer-lowtag)))
  41. (multiple-value-bind
  42. (when-true when-false)
  43. ;; WHEN-TRUE and WHEN-FALSE are the labels to branch to when
  44. ;; we know it's true and when we know it's false respectively.
  45. (if not-p
  46. (values drop-through target)
  47. (values target drop-through))
  48. (assemble ()
  49. (%test-lowtag value when-false t lowtag :temp temp)
  50. (load-type temp value (- lowtag))
  51. (let ((delta 0))
  52. (do ((remaining headers (cdr remaining)))
  53. ((null remaining))
  54. (let ((header (car remaining))
  55. (last (null (cdr remaining))))
  56. (cond
  57. ((atom header)
  58. (inst subq temp (- header delta) temp)
  59. (setf delta header)
  60. (if last
  61. (if not-p
  62. (inst bne temp target)
  63. (inst beq temp target))
  64. (inst beq temp when-true)))
  65. (t
  66. (let ((start (car header))
  67. (end (cdr header)))
  68. (unless (= start bignum-widetag)
  69. (inst subq temp (- start delta) temp)
  70. (setf delta start)
  71. (inst blt temp when-false))
  72. (inst subq temp (- end delta) temp)
  73. (setf delta end)
  74. (if last
  75. (if not-p
  76. (inst bgt temp target)
  77. (inst ble temp target))
  78. (inst ble temp when-true))))))))
  79. (emit-label drop-through)))))
  80. ;;;; 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) :to (:result 0)) temp)
  85. (:vop-var vop)
  86. (:save-p :compute-only))
  87. (define-vop (type-predicate)
  88. (:args (value :scs (any-reg descriptor-reg)))
  89. (:temporary (:scs (non-descriptor-reg)) temp)
  90. (:conditional)
  91. (:info target not-p)
  92. (:policy :fast-safe))
  93. (defun cost-to-test-types (type-codes)
  94. (+ (* 2 (length type-codes))
  95. (if (> (apply #'max type-codes) lowtag-limit) 7 2)))
  96. (defmacro !define-type-vops (pred-name check-name ptype error-code
  97. (&rest type-codes)
  98. &key &allow-other-keys)
  99. (let ((cost (cost-to-test-types (mapcar #'eval type-codes))))
  100. `(progn
  101. ,@(when pred-name
  102. `((define-vop (,pred-name type-predicate)
  103. (:translate ,pred-name)
  104. (:generator ,cost
  105. (test-type value target not-p (,@type-codes) :temp temp)))))
  106. ,@(when check-name
  107. `((define-vop (,check-name check-type)
  108. (:generator ,cost
  109. (let ((err-lab
  110. (generate-error-code vop ,error-code value)))
  111. (test-type value err-lab t (,@type-codes) :temp temp)
  112. (move value result))))))
  113. ,@(when ptype
  114. `((primitive-type-vop ,check-name (:check) ,ptype))))))
  115. ;;;; Other integer ranges.
  116. ;;; A (signed-byte 32) can be represented with either fixnum or a bignum with
  117. ;;; exactly one digit.
  118. (defun signed-byte-32-test (value temp temp1 not-p target not-target)
  119. (multiple-value-bind
  120. (yep nope)
  121. (if not-p
  122. (values not-target target)
  123. (values target not-target))
  124. (assemble ()
  125. (inst and value fixnum-tag-mask temp)
  126. (inst beq temp yep)
  127. (inst and value lowtag-mask temp)
  128. (inst xor temp other-pointer-lowtag temp)
  129. (inst bne temp nope)
  130. (loadw temp value 0 other-pointer-lowtag)
  131. (inst li (+ (ash 1 n-widetag-bits) bignum-widetag) temp1)
  132. (inst xor temp temp1 temp)
  133. (if not-p
  134. (inst bne temp target)
  135. (inst beq temp target))))
  136. (values))
  137. (define-vop (signed-byte-32-p type-predicate)
  138. (:translate signed-byte-32-p)
  139. (:temporary (:scs (non-descriptor-reg)) temp1)
  140. (:generator 45
  141. (signed-byte-32-test value temp temp1 not-p target not-target)
  142. NOT-TARGET))
  143. (define-vop (check-signed-byte-32 check-type)
  144. (:temporary (:scs (non-descriptor-reg)) temp1)
  145. (:generator 45
  146. (let ((loose (generate-error-code vop object-not-signed-byte-32-error
  147. value)))
  148. (signed-byte-32-test value temp temp1 t loose okay))
  149. OKAY
  150. (move value result)))
  151. ;;; An (unsigned-byte 32) can be represented with either a positive fixnum, a
  152. ;;; bignum with exactly one positive digit, or a bignum with exactly two digits
  153. ;;; and the second digit all zeros.
  154. (defun unsigned-byte-32-test (value temp temp1 not-p target not-target)
  155. (multiple-value-bind (yep nope)
  156. (if not-p
  157. (values not-target target)
  158. (values target not-target))
  159. (assemble ()
  160. ;; Is it a fixnum?
  161. (inst and value fixnum-tag-mask temp1)
  162. (inst move value temp)
  163. (inst beq temp1 fixnum)
  164. ;; If not, is it an other pointer?
  165. (inst and value lowtag-mask temp)
  166. (inst xor temp other-pointer-lowtag temp)
  167. (inst bne temp nope)
  168. ;; Get the header.
  169. (loadw temp value 0 other-pointer-lowtag)
  170. ;; Is it one?
  171. (inst li (+ (ash 1 n-widetag-bits) bignum-widetag) temp1)
  172. (inst xor temp temp1 temp)
  173. (inst beq temp single-word)
  174. ;; If it's other than two, we can't be an (unsigned-byte 32)
  175. (inst li (logxor (+ (ash 1 n-widetag-bits) bignum-widetag)
  176. (+ (ash 2 n-widetag-bits) bignum-widetag))
  177. temp1)
  178. (inst xor temp temp1 temp)
  179. (inst bne temp nope)
  180. ;; Get the second digit.
  181. (loadw temp value (1+ bignum-digits-offset) other-pointer-lowtag)
  182. ;; All zeros, its an (unsigned-byte 32).
  183. (inst beq temp yep)
  184. (inst br zero-tn nope)
  185. SINGLE-WORD
  186. ;; Get the single digit.
  187. (loadw temp value bignum-digits-offset other-pointer-lowtag)
  188. ;; positive implies (unsigned-byte 32).
  189. FIXNUM
  190. (if not-p
  191. (inst blt temp target)
  192. (inst bge temp target))))
  193. (values))
  194. (define-vop (unsigned-byte-32-p type-predicate)
  195. (:translate unsigned-byte-32-p)
  196. (:temporary (:scs (non-descriptor-reg)) temp1)
  197. (:generator 45
  198. (unsigned-byte-32-test value temp temp1 not-p target not-target)
  199. NOT-TARGET))
  200. (define-vop (check-unsigned-byte-32 check-type)
  201. (:temporary (:scs (non-descriptor-reg)) temp1)
  202. (:generator 45
  203. (let ((loose (generate-error-code vop object-not-unsigned-byte-32-error
  204. value)))
  205. (unsigned-byte-32-test value temp temp1 t loose okay))
  206. OKAY
  207. (move value result)))
  208. ;;;; List/symbol types:
  209. ;;;
  210. ;;; symbolp (or symbol (eq nil))
  211. ;;; consp (and list (not (eq nil)))
  212. (define-vop (symbolp type-predicate)
  213. (:translate symbolp)
  214. (:temporary (:scs (non-descriptor-reg)) temp)
  215. (:generator 12
  216. (inst cmpeq value null-tn temp)
  217. (inst bne temp (if not-p drop-thru target))
  218. (test-type value target not-p (symbol-header-widetag) :temp temp)
  219. DROP-THRU))
  220. (define-vop (check-symbol check-type)
  221. (:temporary (:scs (non-descriptor-reg)) temp)
  222. (:generator 12
  223. (inst cmpeq value null-tn temp)
  224. (inst bne temp drop-thru)
  225. (let ((error (generate-error-code vop object-not-symbol-error value)))
  226. (test-type value error t (symbol-header-widetag) :temp temp))
  227. DROP-THRU
  228. (move value result)))
  229. (define-vop (consp type-predicate)
  230. (:translate consp)
  231. (:temporary (:scs (non-descriptor-reg)) temp)
  232. (:generator 8
  233. (inst cmpeq value null-tn temp)
  234. (inst bne temp (if not-p target drop-thru))
  235. (test-type value target not-p (list-pointer-lowtag) :temp temp)
  236. DROP-THRU))
  237. (define-vop (check-cons check-type)
  238. (:temporary (:scs (non-descriptor-reg)) temp)
  239. (:generator 8
  240. (let ((error (generate-error-code vop object-not-cons-error value)))
  241. (inst cmpeq value null-tn temp)
  242. (inst bne temp error)
  243. (test-type value error t (list-pointer-lowtag) :temp temp))
  244. (move value result)))