+ ;; Large resulting bounds are easy to generate but are not
+ ;; particularly useful, so an open outer bound is returned for a
+ ;; shift greater than 64 - the largest word size of any of the ports.
+ ;; Large negative shifts are also problematic as the ASH
+ ;; implementation only accepts shifts greater than
+ ;; MOST-NEGATIVE-FIXNUM. These issues are handled by two local
+ ;; functions:
+ ;; ASH-OUTER: Perform the shift when within an acceptable range,
+ ;; otherwise return an open bound.
+ ;; ASH-INNER: Perform the shift when within range, limited to a
+ ;; maximum of 64, otherwise returns the inner limit.
+ ;;
+ ;; FIXME: The magic number 64 should be given a mnemonic name as a
+ ;; symbolic constant -- perhaps +MAX-REGISTER-SIZE+. And perhaps is
+ ;; should become an architecture-specific SB!VM:+MAX-REGISTER-SIZE+
+ ;; instead of trying to have a single magic number which covers
+ ;; all possible ports.
+ (flet ((ash-outer (n s)
+ (when (and (fixnump s)
+ (<= s 64)
+ (> s sb!vm:*target-most-negative-fixnum*))
+ (ash n s)))
+ (ash-inner (n s)
+ (if (and (fixnump s)
+ (> s sb!vm:*target-most-negative-fixnum*))
+ (ash n (min s 64))
+ (if (minusp n) -1 0))))
+ (or (let ((n-type (continuation-type n)))
+ (when (numeric-type-p n-type)
+ (let ((n-low (numeric-type-low n-type))
+ (n-high (numeric-type-high n-type)))
+ (if (constant-continuation-p shift)
+ (let ((shift (continuation-value shift)))
+ (make-numeric-type :class 'integer
+ :complexp :real
+ :low (when n-low (ash n-low shift))
+ :high (when n-high (ash n-high shift))))
+ (let ((s-type (continuation-type shift)))
+ (when (numeric-type-p s-type)
+ (let* ((s-low (numeric-type-low s-type))
+ (s-high (numeric-type-high s-type))
+ (low-slot (when n-low
+ (if (minusp n-low)
+ (ash-outer n-low s-high)
+ (ash-inner n-low s-low))))
+ (high-slot (when n-high
+ (if (minusp n-high)
+ (ash-inner n-high s-low)
+ (ash-outer n-high s-high)))))
+ (make-numeric-type :class 'integer
+ :complexp :real
+ :low low-slot
+ :high high-slot))))))))
+ *universal-type*))