librustc_middle: Add function for computing unsigned abs
This is tricky to get right if we want to avoid panicking or wrapping. Signed-off-by: Joe Richey <joerichey@google.com>
This commit is contained in:
parent
55577b411c
commit
6367b544b7
2 changed files with 14 additions and 8 deletions
|
|
@ -598,3 +598,12 @@ pub fn truncate(value: u128, size: Size) -> u128 {
|
|||
// Truncate (shift left to drop out leftover values, shift right to fill with zeroes).
|
||||
(value << shift) >> shift
|
||||
}
|
||||
|
||||
/// Computes the unsigned absolute value without wrapping or panicking.
|
||||
#[inline]
|
||||
pub fn uabs(value: i64) -> u64 {
|
||||
// The only tricky part here is if value == i64::MIN. In that case,
|
||||
// wrapping_abs() returns i64::MIN == -2^63. Casting this value to a u64
|
||||
// gives 2^63, the correct value.
|
||||
value.wrapping_abs() as u64
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use super::{AllocId, InterpResult};
|
||||
use super::{uabs, AllocId, InterpResult};
|
||||
|
||||
use rustc_macros::HashStable;
|
||||
use rustc_target::abi::{HasDataLayout, Size};
|
||||
|
|
@ -48,15 +48,12 @@ pub trait PointerArithmetic: HasDataLayout {
|
|||
|
||||
#[inline]
|
||||
fn overflowing_signed_offset(&self, val: u64, i: i64) -> (u64, bool) {
|
||||
if i < 0 {
|
||||
// Trickery to ensure that `i64::MIN` works fine: compute `n = -i`.
|
||||
// This formula only works for true negative values; it overflows for zero!
|
||||
let n = u64::MAX - (i as u64) + 1;
|
||||
let n = uabs(i);
|
||||
if i >= 0 {
|
||||
self.overflowing_offset(val, n)
|
||||
} else {
|
||||
let res = val.overflowing_sub(n);
|
||||
self.truncate_to_ptr(res)
|
||||
} else {
|
||||
// `i >= 0`, so the cast is safe.
|
||||
self.overflowing_offset(val, i as u64)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue