fixed the bahavior of fxaithmetic-shift{-left,-right,} when the
shift amount is not in range and when the result overflows.
This commit is contained in:
		
							parent
							
								
									b1c9fda05c
								
							
						
					
					
						commit
						c0233db219
					
				
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							| 
						 | 
					@ -27,7 +27,9 @@
 | 
				
			||||||
          fxarithmetic-shift-left fxarithmetic-shift-right fxarithmetic-shift
 | 
					          fxarithmetic-shift-left fxarithmetic-shift-right fxarithmetic-shift
 | 
				
			||||||
          fxmin fxmax
 | 
					          fxmin fxmax
 | 
				
			||||||
          error@fx+ error@fx* error@fx- error@fxadd1 error@fxsub1
 | 
					          error@fx+ error@fx* error@fx- error@fxadd1 error@fxsub1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          error@fxarithmetic-shift-left
 | 
					          error@fxarithmetic-shift-left
 | 
				
			||||||
 | 
					          error@fxarithmetic-shift-right
 | 
				
			||||||
          )
 | 
					          )
 | 
				
			||||||
  (import 
 | 
					  (import 
 | 
				
			||||||
    (ikarus system $fx)
 | 
					    (ikarus system $fx)
 | 
				
			||||||
| 
						 | 
					@ -47,6 +49,14 @@
 | 
				
			||||||
            fxmin fxmax
 | 
					            fxmin fxmax
 | 
				
			||||||
            fixnum->string))
 | 
					            fixnum->string))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  (define (die/overflow who . args)
 | 
				
			||||||
 | 
					    (raise
 | 
				
			||||||
 | 
					      (condition
 | 
				
			||||||
 | 
					        (make-implementation-restriction-violation)
 | 
				
			||||||
 | 
					        (make-who-condition who)
 | 
				
			||||||
 | 
					        (make-message-condition "overflow")
 | 
				
			||||||
 | 
					        (make-irritants-condition args))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  (define fxzero?
 | 
					  (define fxzero?
 | 
				
			||||||
    (lambda (x)
 | 
					    (lambda (x)
 | 
				
			||||||
      (cond
 | 
					      (cond
 | 
				
			||||||
| 
						 | 
					@ -67,27 +77,24 @@
 | 
				
			||||||
        (die 'fxnot "not a fixnum" x))
 | 
					        (die 'fxnot "not a fixnum" x))
 | 
				
			||||||
      ($fxlognot x)))
 | 
					      ($fxlognot x)))
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  (define (make-fx-error who msg)
 | 
					  (define (make-fx-error who)
 | 
				
			||||||
    (case-lambda
 | 
					    (case-lambda
 | 
				
			||||||
      [(x y)
 | 
					      [(x y)
 | 
				
			||||||
       (if (fixnum? x)
 | 
					       (if (fixnum? x)
 | 
				
			||||||
           (if (fixnum? y) 
 | 
					           (if (fixnum? y) 
 | 
				
			||||||
               (die who msg x y)
 | 
					               (die/overflow who x y)
 | 
				
			||||||
               (die who "not a fixnum" y))
 | 
					               (die who "not a fixnum" y))
 | 
				
			||||||
           (die who "not a fixnum" x))]
 | 
					           (die who "not a fixnum" x))]
 | 
				
			||||||
      [(x) 
 | 
					      [(x) 
 | 
				
			||||||
       (if (fixnum? x)
 | 
					       (if (fixnum? x)
 | 
				
			||||||
           (die who msg x)
 | 
					           (die/overflow who x)
 | 
				
			||||||
           (die who "not a fixnum" x))]))
 | 
					           (die who "not a fixnum" x))]))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  (define error@fx+ 
 | 
					  (define error@fx+    (make-fx-error 'fx+))
 | 
				
			||||||
    (make-fx-error 'fx+ "overflow during addition"))
 | 
					  (define error@fx-    (make-fx-error 'fx-))
 | 
				
			||||||
  
 | 
					  (define error@fx*    (make-fx-error 'fx*))
 | 
				
			||||||
  (define error@fx- 
 | 
					  (define error@fxadd1 (make-fx-error 'fxadd1))
 | 
				
			||||||
    (make-fx-error 'fx- "overflow during subtraction"))
 | 
					  (define error@fxsub1 (make-fx-error 'fxsub1))
 | 
				
			||||||
 | 
					 | 
				
			||||||
  (define error@fx*
 | 
					 | 
				
			||||||
    (make-fx-error 'fx* "overflow during multiplication"))
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  (define (fx+ x y) (sys:fx+ x y))
 | 
					  (define (fx+ x y) (sys:fx+ x y))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -98,12 +105,6 @@
 | 
				
			||||||
      [(x y) (sys:fx- x y)]
 | 
					      [(x y) (sys:fx- x y)]
 | 
				
			||||||
      [(x)   (sys:fx- x)]))
 | 
					      [(x)   (sys:fx- x)]))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  (define error@fxadd1 
 | 
					 | 
				
			||||||
    (make-fx-error 'fxadd1 "overflow during addition"))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  (define error@fxsub1 
 | 
					 | 
				
			||||||
    (make-fx-error 'fxsub1 "overflow during subtraction"))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  (define fxadd1
 | 
					  (define fxadd1
 | 
				
			||||||
    (lambda (n)
 | 
					    (lambda (n)
 | 
				
			||||||
      (import (ikarus))
 | 
					      (import (ikarus))
 | 
				
			||||||
| 
						 | 
					@ -173,7 +174,7 @@
 | 
				
			||||||
        (die 'fxquotient "zero dividend" y))
 | 
					        (die 'fxquotient "zero dividend" y))
 | 
				
			||||||
      (if (eq? y -1)
 | 
					      (if (eq? y -1)
 | 
				
			||||||
          (if (eq? x (least-fixnum))
 | 
					          (if (eq? x (least-fixnum))
 | 
				
			||||||
              (die 'fxquotient "overflow" x y)
 | 
					              (die/overflow 'fxquotient x y)
 | 
				
			||||||
              ($fx- 0 x))
 | 
					              ($fx- 0 x))
 | 
				
			||||||
          ($fxquotient x y))))
 | 
					          ($fxquotient x y))))
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
| 
						 | 
					@ -255,13 +256,8 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  (define fxarithmetic-shift-right
 | 
					  (define fxarithmetic-shift-right
 | 
				
			||||||
    (lambda (x y) 
 | 
					    (lambda (x y) 
 | 
				
			||||||
      (unless (fixnum? x)
 | 
					      (import (ikarus))
 | 
				
			||||||
        (die 'fxarithmetic-shift-right "not a fixnum" x))
 | 
					      (fxarithmetic-shift-right x y)))
 | 
				
			||||||
      (unless (fixnum? y)
 | 
					 | 
				
			||||||
        (die 'fxarithmetic-shift-right "not a fixnum" y))
 | 
					 | 
				
			||||||
      (unless ($fx>= y 0)
 | 
					 | 
				
			||||||
        (die 'fxarithmetic-shift-right "negative shift not allowed" y))
 | 
					 | 
				
			||||||
      ($fxsra x y)))
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  (define fxsll
 | 
					  (define fxsll
 | 
				
			||||||
    (lambda (x y) 
 | 
					    (lambda (x y) 
 | 
				
			||||||
| 
						 | 
					@ -273,17 +269,23 @@
 | 
				
			||||||
        (die 'fxsll "negative shift not allowed" y))
 | 
					        (die 'fxsll "negative shift not allowed" y))
 | 
				
			||||||
      ($fxsll x y))) 
 | 
					      ($fxsll x y))) 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  (define (error@fxarithmetic-shift-left x y)
 | 
					
 | 
				
			||||||
 | 
					  (define (error@fxarithmetic-shift who x y)
 | 
				
			||||||
    (unless (fixnum? x)
 | 
					    (unless (fixnum? x)
 | 
				
			||||||
      (die 'fxarithmetic-shift-left "not a fixnum" x))
 | 
					      (die who "not a fixnum" x))
 | 
				
			||||||
    (unless (fixnum? y)
 | 
					    (unless (fixnum? y)
 | 
				
			||||||
      (die 'fxarithmetic-shift-left "not a fixnum" y))
 | 
					      (die who "not a fixnum" y))
 | 
				
			||||||
    (unless ($fx>= y 0)
 | 
					    (unless ($fx>= y 0)
 | 
				
			||||||
      (die 'fxarithmetic-shift-left "negative shift not allowed" y))
 | 
					      (die who "negative shift not allowed" y))
 | 
				
			||||||
    (unless ($fx< y (fixnum-width))
 | 
					    (unless ($fx< y (fixnum-width))
 | 
				
			||||||
      (die 'fxarithmetic-shift-left 
 | 
					      (die who "shift is not less than fixnum-width" y))
 | 
				
			||||||
        "shift is not less than fixnum-width" y))
 | 
					    (die/overflow who x y))
 | 
				
			||||||
    (die 'fxarithmetic-shift-left "overflow" x y))
 | 
					 
 | 
				
			||||||
 | 
					  (define (error@fxarithmetic-shift-left x y)
 | 
				
			||||||
 | 
					    (error@fxarithmetic-shift 'arithmetic-shift-left x y))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  (define (error@fxarithmetic-shift-right x y)
 | 
				
			||||||
 | 
					    (error@fxarithmetic-shift 'arithmetic-shift-right x y))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  (define fxarithmetic-shift-left
 | 
					  (define fxarithmetic-shift-left
 | 
				
			||||||
    (lambda (x y)
 | 
					    (lambda (x y)
 | 
				
			||||||
| 
						 | 
					@ -292,15 +294,20 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  (define fxarithmetic-shift
 | 
					  (define fxarithmetic-shift
 | 
				
			||||||
    (lambda (x y) 
 | 
					    (lambda (x y) 
 | 
				
			||||||
      (unless (fixnum? x)
 | 
					      (import (ikarus))
 | 
				
			||||||
        (die 'fxarithmetic-shift "not a fixnum" x))
 | 
					      (define (err str x) (die 'fxarithmetic-shift str x))
 | 
				
			||||||
      (unless (fixnum? y)
 | 
					      (unless (fixnum? x) (err "not a fixnum" x))
 | 
				
			||||||
        (die 'fxarithmetic-shift "not a fixnum" y))
 | 
					      (unless (fixnum? y) (err "not a fixnum" y))
 | 
				
			||||||
      (if ($fx>= y 0)
 | 
					      (if ($fx>= y 0)
 | 
				
			||||||
          ($fxsll x y)
 | 
					          (if ($fx< y (fixnum-width))
 | 
				
			||||||
          (if ($fx< x -100) ;;; arbitrary number < (fixnum-width)
 | 
					              (let ([r ($fxsll x y)])
 | 
				
			||||||
              ($fxsra x 32)
 | 
					                (if ($fx= x ($fxsra r y))
 | 
				
			||||||
              ($fxsra x ($fx- 0 y))))))
 | 
					                    r
 | 
				
			||||||
 | 
					                    (die/overflow 'fxarithmetic-shift x y)))
 | 
				
			||||||
 | 
					              (err "invalid shift amount" y))
 | 
				
			||||||
 | 
					          (if ($fx> y (- (fixnum-width)))
 | 
				
			||||||
 | 
					              ($fxsra x ($fx- 0 y))
 | 
				
			||||||
 | 
					              (err "invalid shift amount" y)))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  (define (fxpositive? x)
 | 
					  (define (fxpositive? x)
 | 
				
			||||||
    (if (fixnum? x)
 | 
					    (if (fixnum? x)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1 +1 @@
 | 
				
			||||||
1845
 | 
					1846
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -617,6 +617,7 @@
 | 
				
			||||||
    [make-traced-macro                           i]
 | 
					    [make-traced-macro                           i]
 | 
				
			||||||
    [error@fx+                                   ]
 | 
					    [error@fx+                                   ]
 | 
				
			||||||
    [error@fxarithmetic-shift-left               ]
 | 
					    [error@fxarithmetic-shift-left               ]
 | 
				
			||||||
 | 
					    [error@fxarithmetic-shift-right              ]
 | 
				
			||||||
    [error@fx*                                   ]
 | 
					    [error@fx*                                   ]
 | 
				
			||||||
    [error@fx-                                   ]
 | 
					    [error@fx-                                   ]
 | 
				
			||||||
    [error@add1                                  ]
 | 
					    [error@add1                                  ]
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1592,6 +1592,33 @@
 | 
				
			||||||
            x2)))])])
 | 
					            x2)))])])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(define-primop fxarithmetic-shift-right safe
 | 
				
			||||||
 | 
					  [(V x n) 
 | 
				
			||||||
 | 
					   (struct-case n 
 | 
				
			||||||
 | 
					     [(constant i)
 | 
				
			||||||
 | 
					      (cond
 | 
				
			||||||
 | 
					        [(and (fx? i)
 | 
				
			||||||
 | 
					              (>= i 0)
 | 
				
			||||||
 | 
					              (< i (- (* wordsize 8) fx-shift)))
 | 
				
			||||||
 | 
					         (prm 'sll
 | 
				
			||||||
 | 
					              (prm 'sra (T x) (K (+ i fx-shift)))
 | 
				
			||||||
 | 
					              (K fx-shift))]
 | 
				
			||||||
 | 
					        [else
 | 
				
			||||||
 | 
					         (interrupt)])]
 | 
				
			||||||
 | 
					     [else 
 | 
				
			||||||
 | 
					      (with-tmp ([x (T x)] [n (T n)])
 | 
				
			||||||
 | 
					        (assert-fixnums x (list n))
 | 
				
			||||||
 | 
					        (with-tmp ([n (prm 'sra n (K fx-shift))])
 | 
				
			||||||
 | 
					          (interrupt-when 
 | 
				
			||||||
 | 
					            (prm '< n (K 0)))
 | 
				
			||||||
 | 
					          (interrupt-when 
 | 
				
			||||||
 | 
					            (prm '>= n (K (- (* wordsize 8) fx-shift))))
 | 
				
			||||||
 | 
					          (prm 'sll 
 | 
				
			||||||
 | 
					               (prm 'sra x n)
 | 
				
			||||||
 | 
					               (K fx-shift))))])])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(define (log2 n) 
 | 
					(define (log2 n) 
 | 
				
			||||||
  (let f ([n n] [i 0])
 | 
					  (let f ([n n] [i 0])
 | 
				
			||||||
    (cond
 | 
					    (cond
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -212,14 +212,15 @@
 | 
				
			||||||
  (module (cogen-primop cogen-debug-primop)
 | 
					  (module (cogen-primop cogen-debug-primop)
 | 
				
			||||||
    (define (primop-interrupt-handler x)
 | 
					    (define (primop-interrupt-handler x)
 | 
				
			||||||
      (case x
 | 
					      (case x
 | 
				
			||||||
        [(fx+)                     'error@fx+]
 | 
					        [(fx+)                      'error@fx+]
 | 
				
			||||||
        [(fx-)                     'error@fx-]
 | 
					        [(fx-)                      'error@fx-]
 | 
				
			||||||
        [(fx*)                     'error@fx*]
 | 
					        [(fx*)                      'error@fx*]
 | 
				
			||||||
        [(add1)                    'error@add1]
 | 
					        [(add1)                     'error@add1]
 | 
				
			||||||
        [(sub1)                    'error@sub1]
 | 
					        [(sub1)                     'error@sub1]
 | 
				
			||||||
        [(fxadd1)                  'error@fxadd1]
 | 
					        [(fxadd1)                   'error@fxadd1]
 | 
				
			||||||
        [(fxsub1)                  'error@fxsub1]
 | 
					        [(fxsub1)                   'error@fxsub1]
 | 
				
			||||||
        [(fxarithmetic-shift-left) 'error@fxarithmetic-shift-left]
 | 
					        [(fxarithmetic-shift-left)  'error@fxarithmetic-shift-left]
 | 
				
			||||||
 | 
					        [(fxarithmetic-shift-right) 'error@fxarithmetic-shift-right]
 | 
				
			||||||
        [else                      x]))
 | 
					        [else                      x]))
 | 
				
			||||||
    (define (make-interrupt-call op args)
 | 
					    (define (make-interrupt-call op args)
 | 
				
			||||||
      (make-funcall 
 | 
					      (make-funcall 
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue