Refactor const saturating intrinsics emulation and add unstable feature attribute #58030
This commit is contained in:
parent
d7efc76b7e
commit
17998961d4
3 changed files with 29 additions and 39 deletions
|
@ -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 {
|
||||||
|
|
|
@ -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])?;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue