@@ -20,45 +20,48 @@ pub trait PointerArithmetic: layout::HasDataLayout {
20
20
self . data_layout ( ) . pointer_size
21
21
}
22
22
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!
24
26
#[ 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 ;
26
29
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)
34
31
}
35
32
36
33
#[ inline]
37
34
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)
47
37
}
48
38
49
39
// Overflow checking only works properly on the range from -u64 to +u64.
50
40
#[ inline]
51
41
fn overflowing_signed_offset ( & self , val : u64 , i : i128 ) -> ( u64 , bool ) {
52
42
// FIXME: is it possible to over/underflow here?
53
43
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!
56
46
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)
58
49
} else {
59
50
self . overflowing_offset ( val, i as u64 )
60
51
}
61
52
}
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
+ }
62
65
}
63
66
64
67
impl < T : layout:: HasDataLayout > PointerArithmetic for T { }
0 commit comments