about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbjorn3 <bjorn3@users.noreply.github.com>2019-08-20 10:40:08 +0200
committerbjorn3 <bjorn3@users.noreply.github.com>2019-08-20 10:40:08 +0200
commit3fcd54088c71cf64d723fe928f3da188f6d9952e (patch)
tree6727ffc549176f3c4a21e1cf5174875857ed4dc5
parentf99d31dbfedd10ed3bb66bea1184065bd841f44c (diff)
downloadrust-3fcd54088c71cf64d723fe928f3da188f6d9952e.tar.gz
rust-3fcd54088c71cf64d723fe928f3da188f6d9952e.zip
Implement saturating_{add,sub} intrinsics
-rw-r--r--example/std_example.rs5
-rw-r--r--src/intrinsics.rs22
2 files changed, 21 insertions, 6 deletions
diff --git a/example/std_example.rs b/example/std_example.rs
index f16ff592d4c..26289818896 100644
--- a/example/std_example.rs
+++ b/example/std_example.rs
@@ -38,6 +38,11 @@ fn main() {
     assert_eq!(2.3f32.copysign(-1.0), -2.3f32);
     println!("{}", 2.3f32.powf(2.0));
 
+    assert_eq!(-128i8, (-128i8).saturating_sub(1));
+    assert_eq!(127i8, 127i8.saturating_sub(-128));
+    assert_eq!(-128i8, (-128i8).saturating_add(-128));
+    assert_eq!(127i8, 127i8.saturating_add(1));
+
     assert_eq!(0b0000000000000000000000000010000010000000000000000000000000000000_0000000000100000000000000000000000001000000000000100000000000000u128.leading_zeros(), 26);
     assert_eq!(0b0000000000000000000000000010000000000000000000000000000000000000_0000000000000000000000000000000000001000000000000000000010000000u128.trailing_zeros(), 7);
 
diff --git a/src/intrinsics.rs b/src/intrinsics.rs
index e09dc25f4ab..2cec9c57143 100644
--- a/src/intrinsics.rs
+++ b/src/intrinsics.rs
@@ -487,8 +487,8 @@ pub fn codegen_intrinsic_call<'tcx>(
             );
             ret.write_cvalue(fx, res);
         };
-        _ if intrinsic.starts_with("saturating_"), <T> (c x, c y) {
-            assert_eq!(x.layout().ty, y.layout().ty);
+        _ if intrinsic.starts_with("saturating_"), <T> (c lhs, c rhs) {
+            assert_eq!(lhs.layout().ty, rhs.layout().ty);
             let bin_op = match intrinsic {
                 "saturating_add" => BinOp::Add,
                 "saturating_sub" => BinOp::Sub,
@@ -500,8 +500,8 @@ pub fn codegen_intrinsic_call<'tcx>(
             let checked_res = crate::num::trans_checked_int_binop(
                 fx,
                 bin_op,
-                x,
-                y,
+                lhs,
+                rhs,
             );
 
             let (val, has_overflow) = checked_res.load_scalar_pair(fx);
@@ -517,8 +517,18 @@ pub fn codegen_intrinsic_call<'tcx>(
             let val = match (intrinsic, signed) {
                 ("saturating_add", false) => codegen_select(&mut fx.bcx, has_overflow, max, val),
                 ("saturating_sub", false) => codegen_select(&mut fx.bcx, has_overflow, min, val),
-                ("saturating_add", true) => unimplemented!(),
-                ("saturating_sub", true) => unimplemented!(),
+                ("saturating_add", true) => {
+                    let rhs = rhs.load_scalar(fx);
+                    let rhs_ge_zero = fx.bcx.ins().icmp_imm(IntCC::SignedGreaterThanOrEqual, rhs, 0);
+                    let sat_val = codegen_select(&mut fx.bcx, rhs_ge_zero, max, min);
+                    codegen_select(&mut fx.bcx, has_overflow, sat_val, val)
+                }
+                ("saturating_sub", true) => {
+                    let rhs = rhs.load_scalar(fx);
+                    let rhs_ge_zero = fx.bcx.ins().icmp_imm(IntCC::SignedGreaterThanOrEqual, rhs, 0);
+                    let sat_val = codegen_select(&mut fx.bcx, rhs_ge_zero, min, max);
+                    codegen_select(&mut fx.bcx, has_overflow, sat_val, val)
+                }
                 _ => unreachable!(),
             };