0.pre7.25:
[sbcl.git] / src / compiler / srctran.lisp
index adc6132..8631e17 100644 (file)
 ;;; Note that all the integer division functions are available for
 ;;; inline expansion.
 
-;;; FIXME: DEF-FROB instead of FROB
-(macrolet ((frob (fun)
+(macrolet ((deffrob (fun)
             `(def-source-transform ,fun (x &optional (y nil y-p))
                (declare (ignore y))
                (if y-p
                    (values nil t)
                    `(,',fun ,x 1)))))
-  (frob truncate)
-  (frob round)
+  (deffrob truncate)
+  (deffrob round)
   #-sb-xc-host ; (See CROSS-FLOAT-INFINITY-KLUDGE.)
-  (frob floor)
+  (deffrob floor)
   #-sb-xc-host ; (See CROSS-FLOAT-INFINITY-KLUDGE.)
-  (frob ceiling))
+  (deffrob ceiling))
 
 (def-source-transform lognand (x y) `(lognot (logand ,x ,y)))
 (def-source-transform lognor (x y) `(lognot (logior ,x ,y)))
 ;;;; numeric-type has everything we want to know. Reason 2 wins for
 ;;;; now.
 
-#-sb-xc-host ; (See CROSS-FLOAT-INFINITY-KLUDGE.)
-(progn
-
 ;;; The basic interval type. It can handle open and closed intervals.
 ;;; A bound is open if it is a list containing a number, just like
 ;;; Lisp says. NIL means unbounded.
            ((eq y-range '-)
             (interval-neg (interval-mul x (interval-neg y))))
            ((and (eq x-range '+) (eq y-range '+))
-            ;; If we are here, X and Y are both positive
-            (make-interval :low (bound-mul (interval-low x) (interval-low y))
-                           :high (bound-mul (interval-high x) (interval-high y))))
+            ;; If we are here, X and Y are both positive.
+            (make-interval
+             :low (bound-mul (interval-low x) (interval-low y))
+             :high (bound-mul (interval-high x) (interval-high y))))
            (t
             (error "This shouldn't happen!"))))))
 
             ;; sign of the result.
             (interval-neg (interval-div (interval-neg top) bot)))
            ((and (eq top-range '+) (eq bot-range '+))
-            ;; The easy case
-            (make-interval :low (bound-div (interval-low top) (interval-high bot) t)
-                           :high (bound-div (interval-high top) (interval-low bot) nil)))
+            ;; the easy case
+            (make-interval
+             :low (bound-div (interval-low top) (interval-high bot) t)
+             :high (bound-div (interval-high top) (interval-low bot) nil)))
            (t
             (error "This shouldn't happen!"))))))
 
 ;;; Compute the square of an interval.
 (defun interval-sqr (x)
   (declare (type interval x))
-  (interval-func #'(lambda (x) (* x x))
+  (interval-func (lambda (x) (* x x))
                 (interval-abs x)))
-) ; PROGN
 \f
 ;;;; numeric DERIVE-TYPE methods
 
                             :high high))
        (numeric-contagion x y))))
 
-#-sb-xc-host ; (See CROSS-FLOAT-INFINITY-KLUDGE.)
-(progn
-
 ;;; simple utility to flatten a list
 (defun flatten-list (x)
   (labels ((flatten-helper (x r);; 'r' is the stuff to the 'right'.
          (if (rest results)
              (make-canonical-union-type results)
              (first results)))))))
-
-) ; PROGN
 \f
 #+sb-xc-host ; (See CROSS-FLOAT-INFINITY-KLUDGE.)
 (progn
 ;;; and it's hard to avoid that calculation in here.
 #-(and cmu sb-xc-host)
 (progn
-#+sb-xc-host ; (See CROSS-FLOAT-INFINITY-KLUDGE.)
-(defoptimizer (ash derive-type) ((n shift))
-  ;; 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*))
-  (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)))
-                     (if (and s-low s-high (<= s-low 64) (<= s-high 64))
-                         (make-numeric-type :class 'integer
-                                            :complexp :real
-                                            :low (when n-low
-                                                   (min (ash n-low s-high)
-                                                        (ash n-low s-low)))
-                                            :high (when n-high
-                                                    (max (ash n-high s-high)
-                                                         (ash n-high s-low))))
-                         (make-numeric-type :class 'integer
-                                            :complexp :real)))))))))
-      *universal-type*))
 
-#-sb-xc-host ; (See CROSS-FLOAT-INFINITY-KLUDGE.)
 (defun ash-derive-type-aux (n-type shift same-arg)
   (declare (ignore same-arg))
   (flet ((ash-outer (n s)
                                             (ash-outer n-high s-high))))))
        *universal-type*)))
 
-#-sb-xc-host ; (See CROSS-FLOAT-INFINITY-KLUDGE.)
 (defoptimizer (ash derive-type) ((n shift))
   (two-arg-derive-type n shift #'ash-derive-type-aux #'ash))
 ) ; PROGN
                    (values (if hi (,fun hi) nil) (if lo (,fun lo) nil))))))
 
   (defoptimizer (%negate derive-type) ((num))
-    (derive-integer-type num num (frob -)))
+    (derive-integer-type num num (frob -))))
 
-  (defoptimizer (lognot derive-type) ((int))
-    (derive-integer-type int int (frob lognot))))
-
-#-sb-xc-host ; (See CROSS-FLOAT-INFINITY-KLUDGE.)
 (defoptimizer (lognot derive-type) ((int))
   (derive-integer-type int int
                       (lambda (type type2)
 (defoptimizer (random derive-type) ((bound &optional state))
   (one-arg-derive-type bound #'random-derive-type-aux nil))
 \f
-;;;; logical derive-type methods
+;;;; DERIVE-TYPE methods for LOGAND, LOGIOR, and friends
 
 ;;; Return the maximum number of bits an integer of the supplied type
 ;;; can take up, or NIL if it is unbounded. The second (third) value
                (or (null min) (minusp min))))
       (values nil t t)))
 
-#+sb-xc-host ; (See CROSS-FLOAT-INFINITY-KLUDGE.)
-(progn
-
-(defoptimizer (logand derive-type) ((x y))
-  (multiple-value-bind (x-len x-pos x-neg)
-      (integer-type-length (continuation-type x))
-    (declare (ignore x-pos))
-    (multiple-value-bind (y-len y-pos y-neg)
-       (integer-type-length (continuation-type y))
-      (declare (ignore y-pos))
-      (if (not x-neg)
-         ;; X must be positive.
-         (if (not y-neg)
-             ;; The must both be positive.
-             (cond ((or (null x-len) (null y-len))
-                    (specifier-type 'unsigned-byte))
-                   ((or (zerop x-len) (zerop y-len))
-                    (specifier-type '(integer 0 0)))
-                   (t
-                    (specifier-type `(unsigned-byte ,(min x-len y-len)))))
-             ;; X is positive, but Y might be negative.
-             (cond ((null x-len)
-                    (specifier-type 'unsigned-byte))
-                   ((zerop x-len)
-                    (specifier-type '(integer 0 0)))
-                   (t
-                    (specifier-type `(unsigned-byte ,x-len)))))
-         ;; X might be negative.
-         (if (not y-neg)
-             ;; Y must be positive.
-             (cond ((null y-len)
-                    (specifier-type 'unsigned-byte))
-                   ((zerop y-len)
-                    (specifier-type '(integer 0 0)))
-                   (t
-                    (specifier-type
-                     `(unsigned-byte ,y-len))))
-             ;; Either might be negative.
-             (if (and x-len y-len)
-                 ;; The result is bounded.
-                 (specifier-type `(signed-byte ,(1+ (max x-len y-len))))
-                 ;; We can't tell squat about the result.
-                 (specifier-type 'integer)))))))
-
-(defoptimizer (logior derive-type) ((x y))
-  (multiple-value-bind (x-len x-pos x-neg)
-      (integer-type-length (continuation-type x))
-    (multiple-value-bind (y-len y-pos y-neg)
-       (integer-type-length (continuation-type y))
-      (cond
-       ((and (not x-neg) (not y-neg))
-       ;; Both are positive.
-       (specifier-type `(unsigned-byte ,(if (and x-len y-len)
-                                            (max x-len y-len)
-                                            '*))))
-       ((not x-pos)
-       ;; X must be negative.
-       (if (not y-pos)
-           ;; Both are negative. The result is going to be negative and be
-           ;; the same length or shorter than the smaller.
-           (if (and x-len y-len)
-               ;; It's bounded.
-               (specifier-type `(integer ,(ash -1 (min x-len y-len)) -1))
-               ;; It's unbounded.
-               (specifier-type '(integer * -1)))
-           ;; X is negative, but we don't know about Y. The result will be
-           ;; negative, but no more negative than X.
-           (specifier-type
-            `(integer ,(or (numeric-type-low (continuation-type x)) '*)
-                      -1))))
-       (t
-       ;; X might be either positive or negative.
-       (if (not y-pos)
-           ;; But Y is negative. The result will be negative.
-           (specifier-type
-            `(integer ,(or (numeric-type-low (continuation-type y)) '*)
-                      -1))
-           ;; We don't know squat about either. It won't get any bigger.
-           (if (and x-len y-len)
-               ;; Bounded.
-               (specifier-type `(signed-byte ,(1+ (max x-len y-len))))
-               ;; Unbounded.
-               (specifier-type 'integer))))))))
-
-(defoptimizer (logxor derive-type) ((x y))
-  (multiple-value-bind (x-len x-pos x-neg)
-      (integer-type-length (continuation-type x))
-    (multiple-value-bind (y-len y-pos y-neg)
-       (integer-type-length (continuation-type y))
-      (cond
-       ((or (and (not x-neg) (not y-neg))
-           (and (not x-pos) (not y-pos)))
-       ;; Either both are negative or both are positive. The result
-       ;; will be positive, and as long as the longer.
-       (specifier-type `(unsigned-byte ,(if (and x-len y-len)
-                                            (max x-len y-len)
-                                            '*))))
-       ((or (and (not x-pos) (not y-neg))
-           (and (not y-neg) (not y-pos)))
-       ;; Either X is negative and Y is positive of vice-versa. The
-       ;; result will be negative.
-       (specifier-type `(integer ,(if (and x-len y-len)
-                                      (ash -1 (max x-len y-len))
-                                      '*)
-                                 -1)))
-       ;; We can't tell what the sign of the result is going to be.
-       ;; All we know is that we don't create new bits.
-       ((and x-len y-len)
-       (specifier-type `(signed-byte ,(1+ (max x-len y-len)))))
-       (t
-       (specifier-type 'integer))))))
-
-) ; PROGN
-
-#-sb-xc-host ; (See CROSS-FLOAT-INFINITY-KLUDGE.)
-(progn
-
 (defun logand-derive-type-aux (x y &optional same-leaf)
   (declare (ignore same-leaf))
   (multiple-value-bind (x-len x-pos x-neg) (integer-type-length x)
                                             '*)))))
        ((or (and (not x-pos) (not y-neg))
            (and (not y-neg) (not y-pos)))
-       ;; Either X is negative and Y is positive of vice-verca. The
+       ;; Either X is negative and Y is positive of vice-versa. The
        ;; result will be negative.
        (specifier-type `(integer ,(if (and x-len y-len)
                                       (ash -1 (max x-len y-len))
        (t
        (specifier-type 'integer))))))
 
-(macrolet ((frob (logfcn)
+(macrolet ((deffrob (logfcn)
             (let ((fcn-aux (symbolicate logfcn "-DERIVE-TYPE-AUX")))
             `(defoptimizer (,logfcn derive-type) ((x y))
                (two-arg-derive-type x y #',fcn-aux #',logfcn)))))
-  ;; FIXME: DEF-FROB, not just FROB
-  (frob logand)
-  (frob logior)
-  (frob logxor))
+  (deffrob logand)
+  (deffrob logior)
+  (deffrob logxor))
+\f
+;;;; miscellaneous derive-type methods
 
 (defoptimizer (integer-length derive-type) ((x))
   (let ((x-type (continuation-type x)))
     (when (and (numeric-type-p x-type)
                (csubtypep x-type (specifier-type 'integer)))
-      ;; If the X is of type (INTEGER LO HI), then the integer-length
-      ;; of X is (INTEGER (min lo hi) (max lo hi), basically.  Be
+      ;; If the X is of type (INTEGER LO HI), then the INTEGER-LENGTH
+      ;; of X is (INTEGER (MIN lo hi) (MAX lo hi), basically.  Be
       ;; careful about LO or HI being NIL, though.  Also, if 0 is
       ;; contained in X, the lower bound is obviously 0.
       (flet ((null-or-min (a b)
           (when (ctypep 0 x-type)
             (setf min-len 0))
           (specifier-type `(integer ,(or min-len '*) ,(or max-len '*))))))))
-) ; PROGN
-\f
-;;;; miscellaneous derive-type methods
 
 (defoptimizer (code-char derive-type) ((code))
   (specifier-type 'base-char))