From 17998961d4d08d08be3cee5e09ca62b75b832f1a Mon Sep 17 00:00:00 2001
From: Patrick McCarter
Date: Thu, 7 Feb 2019 13:12:17 -0500
Subject: [PATCH] Refactor const saturating intrinsics emulation and add
unstable feature attribute #58030
---
src/libcore/num/mod.rs | 2 +
src/librustc_mir/interpret/intrinsics.rs | 64 ++++++++-----------
.../run-pass/const-int-saturating-arith.rs | 2 +
3 files changed, 29 insertions(+), 39 deletions(-)
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index 104b124bad4..d4fade76138 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -909,6 +909,7 @@ $EndFeature, "
```"),
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_const_unstable(feature = "const_saturating_int_methods")]
#[inline]
#[cfg(not(stage0))]
pub const fn saturating_add(self, rhs: Self) -> Self {
@@ -957,6 +958,7 @@ assert_eq!(", stringify!($SelfT), "::min_value().saturating_sub(100), ", stringi
$EndFeature, "
```"),
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_const_unstable(feature = "const_saturating_int_methods")]
#[inline]
#[cfg(not(stage0))]
pub const fn saturating_sub(self, rhs: Self) -> Self {
diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs
index 5ec18d133c6..e8dc22b8a59 100644
--- a/src/librustc_mir/interpret/intrinsics.rs
+++ b/src/librustc_mir/interpret/intrinsics.rs
@@ -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)?;
}
}
- "saturating_add" => {
+ "saturating_add" | "saturating_sub" => {
let l = self.read_immediate(args[0])?;
let r = self.read_immediate(args[1])?;
- let (val, overflowed) = self.binary_op_imm(BinOp::Add, l, r)?;
- if overflowed {
- let first_term: u128 = l.to_scalar()?.to_bits(l.layout.size)?;
- 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)?;
+ let is_add = intrinsic_name == "saturating_add";
+ let (val, overflowed) = self.binary_op_imm(if is_add {
+ BinOp::Add
} else {
- self.write_scalar(val, dest)?;
- }
- }
- "saturating_sub" => {
- let l = self.read_immediate(args[0])?;
- let r = self.read_immediate(args[1])?;
- let (val, overflowed) = self.binary_op_imm(BinOp::Sub, l, r)?;
- if overflowed {
+ BinOp::Sub
+ }, l, r)?;
+ let val = if overflowed {
+ // For signed ints the saturated value depends on the
+ // sign of the first term
let first_term: u128 = l.to_scalar()?.to_bits(l.layout.size)?;
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
- // so overflow is positive
- Scalar::from_uint((1u128 << (num_bits - 1)) - 1,
+ Scalar::from_uint((1u128 << (num_bits - 1)) - 1, // max positive
Size::from_bits(num_bits))
- } else {
- // if first term negative, overflow must be negative
+ } else { // first term is negative
+ // max negative
Scalar::from_uint(1u128 << (num_bits - 1), Size::from_bits(num_bits))
}
- } else {
- // unsigned underflow saturates to 0
- Scalar::from_uint(0u128, Size::from_bits(num_bits))
- };
- self.write_scalar(val, dest)?;
+ } else { // unsigned
+ if is_add {
+ // max unsigned
+ Scalar::from_uint(u128::max_value() >> (128 - num_bits),
+ Size::from_bits(num_bits))
+ } else { // underflow to 0
+ Scalar::from_uint(0u128, Size::from_bits(num_bits))
+ }
+ }
} else {
- self.write_scalar(val, dest)?;
- }
+ val
+ };
+ self.write_scalar(val, dest)?;
}
"unchecked_shl" | "unchecked_shr" => {
let l = self.read_immediate(args[0])?;
diff --git a/src/test/run-pass/const-int-saturating-arith.rs b/src/test/run-pass/const-int-saturating-arith.rs
index 92372e073cf..4f586a276f0 100644
--- a/src/test/run-pass/const-int-saturating-arith.rs
+++ b/src/test/run-pass/const-int-saturating-arith.rs
@@ -1,3 +1,5 @@
+#![feature(const_saturating_int_methods)]
+
const INT_U32_NO: u32 = (42 as u32).saturating_add(2);
const INT_U32: u32 = u32::max_value().saturating_add(1);
const INT_U128: u128 = u128::max_value().saturating_add(1);