@@ -20,45 +20,48 @@ pub trait PointerArithmetic: layout::HasDataLayout {
2020 self . data_layout ( ) . pointer_size
2121 }
2222
23- //// Trunace the given value to the pointer size; also return whether there was an overflow
23+ /// Helper function: truncate given value-"overflowed flag" pair to pointer size and
24+ /// update "overflowed flag" if there was an overflow.
25+ /// This should be called by all the other methods before returning!
2426 #[ inline]
25- fn truncate_to_ptr ( & self , val : u128 ) -> ( u64 , bool ) {
27+ fn truncate_to_ptr ( & self , ( val, over) : ( u64 , bool ) ) -> ( u64 , bool ) {
28+ let val = val as u128 ;
2629 let max_ptr_plus_1 = 1u128 << self . pointer_size ( ) . bits ( ) ;
27- ( ( val % max_ptr_plus_1) as u64 , val >= max_ptr_plus_1)
28- }
29-
30- #[ inline]
31- fn offset < ' tcx > ( & self , val : u64 , i : u64 ) -> EvalResult < ' tcx , u64 > {
32- let ( res, over) = self . overflowing_offset ( val, i) ;
33- if over { err ! ( Overflow ( mir:: BinOp :: Add ) ) } else { Ok ( res) }
30+ ( ( val % max_ptr_plus_1) as u64 , over || val >= max_ptr_plus_1)
3431 }
3532
3633 #[ inline]
3734 fn overflowing_offset ( & self , val : u64 , i : u64 ) -> ( u64 , bool ) {
38- let ( res, over1) = val. overflowing_add ( i) ;
39- let ( res, over2) = self . truncate_to_ptr ( u128:: from ( res) ) ;
40- ( res, over1 || over2)
41- }
42-
43- #[ inline]
44- fn signed_offset < ' tcx > ( & self , val : u64 , i : i64 ) -> EvalResult < ' tcx , u64 > {
45- let ( res, over) = self . overflowing_signed_offset ( val, i128:: from ( i) ) ;
46- if over { err ! ( Overflow ( mir:: BinOp :: Add ) ) } else { Ok ( res) }
35+ let res = val. overflowing_add ( i) ;
36+ self . truncate_to_ptr ( res)
4737 }
4838
4939 // Overflow checking only works properly on the range from -u64 to +u64.
5040 #[ inline]
5141 fn overflowing_signed_offset ( & self , val : u64 , i : i128 ) -> ( u64 , bool ) {
5242 // FIXME: is it possible to over/underflow here?
5343 if i < 0 {
54- // trickery to ensure that i64::min_value() works fine
55- // this formula only works for true negative values, it panics for zero!
44+ // Trickery to ensure that i64::min_value() works fine: compute n = -i.
45+ // This formula only works for true negative values, it overflows for zero!
5646 let n = u64:: max_value ( ) - ( i as u64 ) + 1 ;
57- val. overflowing_sub ( n)
47+ let res = val. overflowing_sub ( n) ;
48+ self . truncate_to_ptr ( res)
5849 } else {
5950 self . overflowing_offset ( val, i as u64 )
6051 }
6152 }
53+
54+ #[ inline]
55+ fn offset < ' tcx > ( & self , val : u64 , i : u64 ) -> EvalResult < ' tcx , u64 > {
56+ let ( res, over) = self . overflowing_offset ( val, i) ;
57+ if over { err ! ( Overflow ( mir:: BinOp :: Add ) ) } else { Ok ( res) }
58+ }
59+
60+ #[ inline]
61+ fn signed_offset < ' tcx > ( & self , val : u64 , i : i64 ) -> EvalResult < ' tcx , u64 > {
62+ let ( res, over) = self . overflowing_signed_offset ( val, i128:: from ( i) ) ;
63+ if over { err ! ( Overflow ( mir:: BinOp :: Add ) ) } else { Ok ( res) }
64+ }
6265}
6366
6467impl < T : layout:: HasDataLayout > PointerArithmetic for T { }
0 commit comments