about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPatrick McCarter <p.mccarter@gmail.com>2019-02-07 13:12:17 -0500
committerPatrick McCarter <p.mccarter@gmail.com>2019-02-07 13:12:17 -0500
commit17998961d4d08d08be3cee5e09ca62b75b832f1a (patch)
tree196ccb52f86f59c4934e77d5a36b488132a6fbe3
parentd7efc76b7ef8c60aefd603dd4773b2fa039bab80 (diff)
downloadrust-17998961d4d08d08be3cee5e09ca62b75b832f1a.tar.gz
rust-17998961d4d08d08be3cee5e09ca62b75b832f1a.zip
Refactor const saturating intrinsics emulation and add unstable feature attribute #58030
-rw-r--r--src/libcore/num/mod.rs2
-rw-r--r--src/librustc_mir/interpret/intrinsics.rs64
-rw-r--r--src/test/run-pass/const-int-saturating-arith.rs2
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);