File tree 2 files changed +14
-8
lines changed
src/librustc_middle/mir/interpret
2 files changed +14
-8
lines changed Original file line number Diff line number Diff line change @@ -598,3 +598,12 @@ pub fn truncate(value: u128, size: Size) -> u128 {
598
598
// Truncate (shift left to drop out leftover values, shift right to fill with zeroes).
599
599
( value << shift) >> shift
600
600
}
601
+
602
+ /// Computes the unsigned absolute value without wrapping or panicking.
603
+ #[ inline]
604
+ pub fn uabs ( value : i64 ) -> u64 {
605
+ // The only tricky part here is if value == i64::MIN. In that case,
606
+ // wrapping_abs() returns i64::MIN == -2^63. Casting this value to a u64
607
+ // gives 2^63, the correct value.
608
+ value. wrapping_abs ( ) as u64
609
+ }
Original file line number Diff line number Diff line change 1
- use super :: { AllocId , InterpResult } ;
1
+ use super :: { uabs , AllocId , InterpResult } ;
2
2
3
3
use rustc_macros:: HashStable ;
4
4
use rustc_target:: abi:: { HasDataLayout , Size } ;
@@ -48,15 +48,12 @@ pub trait PointerArithmetic: HasDataLayout {
48
48
49
49
#[ inline]
50
50
fn overflowing_signed_offset ( & self , val : u64 , i : i64 ) -> ( u64 , bool ) {
51
- if i < 0 {
52
- // Trickery to ensure that `i64::MIN` works fine: compute `n = -i`.
53
- // This formula only works for true negative values; it overflows for zero!
54
- let n = u64 :: MAX - ( i as u64 ) + 1 ;
51
+ let n = uabs ( i ) ;
52
+ if i >= 0 {
53
+ self . overflowing_offset ( val , n )
54
+ } else {
55
55
let res = val. overflowing_sub ( n) ;
56
56
self . truncate_to_ptr ( res)
57
- } else {
58
- // `i >= 0`, so the cast is safe.
59
- self . overflowing_offset ( val, i as u64 )
60
57
}
61
58
}
62
59
You can’t perform that action at this time.
0 commit comments