1
Fork 0

Refactor const saturating intrinsics emulation and add unstable feature attribute #58030

This commit is contained in:
Patrick McCarter 2019-02-07 13:12:17 -05:00
parent d7efc76b7e
commit 17998961d4
3 changed files with 29 additions and 39 deletions

View file

@ -909,6 +909,7 @@ $EndFeature, "
```"), ```"),
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_saturating_int_methods")]
#[inline] #[inline]
#[cfg(not(stage0))] #[cfg(not(stage0))]
pub const fn saturating_add(self, rhs: Self) -> Self { pub const fn saturating_add(self, rhs: Self) -> Self {
@ -957,6 +958,7 @@ assert_eq!(", stringify!($SelfT), "::min_value().saturating_sub(100), ", stringi
$EndFeature, " $EndFeature, "
```"), ```"),
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_saturating_int_methods")]
#[inline] #[inline]
#[cfg(not(stage0))] #[cfg(not(stage0))]
pub const fn saturating_sub(self, rhs: Self) -> Self { pub const fn saturating_sub(self, rhs: Self) -> Self {

View file

@ -122,55 +122,41 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
self.binop_with_overflow(bin_op, lhs, rhs, dest)?; self.binop_with_overflow(bin_op, lhs, rhs, dest)?;
} }
} }
"saturating_add" => { "saturating_add" | "saturating_sub" => {
let l = self.read_immediate(args[0])?; let l = self.read_immediate(args[0])?;
let r = self.read_immediate(args[1])?; let r = self.read_immediate(args[1])?;
let (val, overflowed) = self.binary_op_imm(BinOp::Add, l, r)?; let is_add = intrinsic_name == "saturating_add";
if overflowed { let (val, overflowed) = self.binary_op_imm(if is_add {
let first_term: u128 = l.to_scalar()?.to_bits(l.layout.size)?; BinOp::Add
let num_bits = l.layout.size.bits();
let val = if l.layout.abi.is_signed() {
// For signed addition the saturated value depends on the
// sign of either term
if first_term & (1 << (num_bits-1)) == 0 { // signed term is positive
Scalar::from_uint((1u128 << (num_bits - 1)) - 1,
Size::from_bits(num_bits))
} else { // signed term is negative
Scalar::from_uint(1u128 << (num_bits - 1), Size::from_bits(num_bits))
}
} else {
Scalar::from_uint(u128::max_value() >> (128 - num_bits),
Size::from_bits(num_bits))
};
self.write_scalar(val, dest)?;
} else { } else {
self.write_scalar(val, dest)?; BinOp::Sub
} }, l, r)?;
} let val = if overflowed {
"saturating_sub" => { // For signed ints the saturated value depends on the
let l = self.read_immediate(args[0])?; // sign of the first term
let r = self.read_immediate(args[1])?;
let (val, overflowed) = self.binary_op_imm(BinOp::Sub, l, r)?;
if overflowed {
let first_term: u128 = l.to_scalar()?.to_bits(l.layout.size)?; let first_term: u128 = l.to_scalar()?.to_bits(l.layout.size)?;
let num_bits = l.layout.size.bits(); let num_bits = l.layout.size.bits();
let val = if l.layout.abi.is_signed() { if l.layout.abi.is_signed() {
if first_term & (1 << (num_bits-1)) == 0 { // first term is positive if first_term & (1 << (num_bits-1)) == 0 { // first term is positive
// so overflow is positive Scalar::from_uint((1u128 << (num_bits - 1)) - 1, // max positive
Scalar::from_uint((1u128 << (num_bits - 1)) - 1,
Size::from_bits(num_bits)) Size::from_bits(num_bits))
} else { } else { // first term is negative
// if first term negative, overflow must be negative // max negative
Scalar::from_uint(1u128 << (num_bits - 1), Size::from_bits(num_bits)) Scalar::from_uint(1u128 << (num_bits - 1), Size::from_bits(num_bits))
} }
} else { } else { // unsigned
// unsigned underflow saturates to 0 if is_add {
Scalar::from_uint(0u128, Size::from_bits(num_bits)) // max unsigned
}; Scalar::from_uint(u128::max_value() >> (128 - num_bits),
self.write_scalar(val, dest)?; Size::from_bits(num_bits))
} else { // underflow to 0
Scalar::from_uint(0u128, Size::from_bits(num_bits))
}
}
} else { } else {
self.write_scalar(val, dest)?; val
} };
self.write_scalar(val, dest)?;
} }
"unchecked_shl" | "unchecked_shr" => { "unchecked_shl" | "unchecked_shr" => {
let l = self.read_immediate(args[0])?; let l = self.read_immediate(args[0])?;

View file

@ -1,3 +1,5 @@
#![feature(const_saturating_int_methods)]
const INT_U32_NO: u32 = (42 as u32).saturating_add(2); const INT_U32_NO: u32 = (42 as u32).saturating_add(2);
const INT_U32: u32 = u32::max_value().saturating_add(1); const INT_U32: u32 = u32::max_value().saturating_add(1);
const INT_U128: u128 = u128::max_value().saturating_add(1); const INT_U128: u128 = u128::max_value().saturating_add(1);