]> git.lizzy.rs Git - rust.git/commitdiff
Fix saturated_* intrinsics for 128bit ints
authorbjorn3 <bjorn3@users.noreply.github.com>
Fri, 17 Apr 2020 12:14:18 +0000 (14:14 +0200)
committerbjorn3 <bjorn3@users.noreply.github.com>
Fri, 17 Apr 2020 12:14:24 +0000 (14:14 +0200)
Fixes #968

src/cast.rs
src/common.rs
src/intrinsics/mod.rs

index 08dc68b08d7ef796a4f561a73c66a2f809e72cae..395a270efd9dce90c53dba9c1746bbd84ea812b0 100644 (file)
@@ -159,7 +159,13 @@ pub(crate) fn clif_int_or_float_cast(
             } else {
                 fx.bcx.ins().fcvt_to_uint_sat(types::I32, from)
             };
-            let (min, max) = type_min_max_value(to_ty, to_signed);
+            let (min, max) = match (to_ty, to_signed) {
+                (types::I8, false) => (0, u8::MAX as i64),
+                (types::I16, false) => (0, u16::MAX as i64),
+                (types::I8, true) => (i8::MIN as i64, i8::MAX as i64),
+                (types::I16, true) => (i16::MIN as i64, i16::MAX as i64),
+                _ => unreachable!(),
+            };
             let min_val = fx.bcx.ins().iconst(types::I32, min);
             let max_val = fx.bcx.ins().iconst(types::I32, max);
 
index ed368bf96ecc49b0f11869a4768b870d474cf9c4..e24eb9f0553eb75b40031f0ee9836472f7864288 100644 (file)
@@ -215,8 +215,33 @@ pub(crate) fn resolve_value_imm(func: &Function, val: Value) -> Option<u128> {
     }
 }
 
-pub(crate) fn type_min_max_value(ty: Type, signed: bool) -> (i64, i64) {
+pub(crate) fn type_min_max_value(bcx: &mut FunctionBuilder<'_>, ty: Type, signed: bool) -> (Value, Value) {
     assert!(ty.is_int());
+
+    if ty == types::I128 {
+        if signed {
+            let min = i128::MIN as u128;
+            let min_lsb = bcx.ins().iconst(types::I64, min as u64 as i64);
+            let min_msb = bcx.ins().iconst(types::I64, (min >> 64) as u64 as i64);
+            let min = bcx.ins().iconcat(min_lsb, min_msb);
+
+            let max = i128::MIN as u128;
+            let max_lsb = bcx.ins().iconst(types::I64, max as u64 as i64);
+            let max_msb = bcx.ins().iconst(types::I64, (max >> 64) as u64 as i64);
+            let max = bcx.ins().iconcat(max_lsb, max_msb);
+
+            return (min, max);
+        } else {
+            let min_half = bcx.ins().iconst(types::I64, 0);
+            let min = bcx.ins().iconcat(min_half, min_half);
+
+            let max_half = bcx.ins().iconst(types::I64, u64::MAX as i64);
+            let max = bcx.ins().iconcat(max_half, max_half);
+
+            return (min, max);
+        }
+    }
+
     let min = match (ty, signed) {
         (types::I8, false) | (types::I16, false) | (types::I32, false) | (types::I64, false) => {
             0i64
@@ -225,7 +250,6 @@ pub(crate) fn type_min_max_value(ty: Type, signed: bool) -> (i64, i64) {
         (types::I16, true) => i16::MIN as i64,
         (types::I32, true) => i32::MIN as i64,
         (types::I64, true) => i64::MIN,
-        (types::I128, _) => unimplemented!(),
         _ => unreachable!(),
     };
 
@@ -238,10 +262,11 @@ pub(crate) fn type_min_max_value(ty: Type, signed: bool) -> (i64, i64) {
         (types::I16, true) => i16::MAX as i64,
         (types::I32, true) => i32::MAX as i64,
         (types::I64, true) => i64::MAX,
-        (types::I128, _) => unimplemented!(),
         _ => unreachable!(),
     };
 
+    let (min, max) = (bcx.ins().iconst(ty, min), bcx.ins().iconst(ty, max));
+
     (min, max)
 }
 
index 12edbfdbe3fcb34622d7a524dc2b10c3806a6bab..8ae4848a7dff46219e78749b95d25936170f79b1 100644 (file)
@@ -583,9 +583,7 @@ pub(crate) fn codegen_intrinsic_call<'tcx>(
             // `select.i8` is not implemented by Cranelift.
             let has_overflow = fx.bcx.ins().uextend(types::I32, has_overflow);
 
-            let (min, max) = type_min_max_value(clif_ty, signed);
-            let min = fx.bcx.ins().iconst(clif_ty, min);
-            let max = fx.bcx.ins().iconst(clif_ty, max);
+            let (min, max) = type_min_max_value(&mut fx.bcx, clif_ty, signed);
 
             let val = match (intrinsic, signed) {
                 ("saturating_add", false) => fx.bcx.ins().select(has_overflow, max, val),