]> git.lizzy.rs Git - rust.git/blobdiff - src/cast.rs
Rustfmt
[rust.git] / src / cast.rs
index 25ce5812f9bd4bcea5d9ccc39afebbc2c2ad2044..e19070774c6e0c246662f55ed06e4cf5a53f17e0 100644 (file)
@@ -1,7 +1,9 @@
+//! Various number casting functions
+
 use crate::prelude::*;
 
 pub(crate) fn clif_intcast(
-    fx: &mut FunctionCx<'_, '_, impl Backend>,
+    fx: &mut FunctionCx<'_, '_, '_>,
     val: Value,
     to: Type,
     signed: bool,
@@ -12,21 +14,6 @@ pub(crate) fn clif_intcast(
         (_, _) if from == to => val,
 
         // extend
-        (_, types::I128) => {
-            let lo = if from == types::I64 {
-                val
-            } else if signed {
-                fx.bcx.ins().sextend(types::I64, val)
-            } else {
-                fx.bcx.ins().uextend(types::I64, val)
-            };
-            let hi = if signed {
-                fx.bcx.ins().sshr_imm(lo, 63)
-            } else {
-                fx.bcx.ins().iconst(types::I64, 0)
-            };
-            fx.bcx.ins().iconcat(lo, hi)
-        }
         (_, _) if to.wider_or_equal(from) => {
             if signed {
                 fx.bcx.ins().sextend(to, val)
@@ -36,20 +23,12 @@ pub(crate) fn clif_intcast(
         }
 
         // reduce
-        (types::I128, _) => {
-            let (lsb, _msb) = fx.bcx.ins().isplit(val);
-            if to == types::I64 {
-                lsb
-            } else {
-                fx.bcx.ins().ireduce(to, lsb)
-            }
-        }
         (_, _) => fx.bcx.ins().ireduce(to, val),
     }
 }
 
 pub(crate) fn clif_int_or_float_cast(
-    fx: &mut FunctionCx<'_, '_, impl Backend>,
+    fx: &mut FunctionCx<'_, '_, '_>,
     from: Value,
     from_signed: bool,
     to_ty: Type,
@@ -85,24 +64,16 @@ pub(crate) fn clif_int_or_float_cast(
                 },
             );
 
-            let from_rust_ty = if from_signed {
-                fx.cx.tcx.types.i128
-            } else {
-                fx.cx.tcx.types.u128
-            };
+            let from_rust_ty = if from_signed { fx.tcx.types.i128 } else { fx.tcx.types.u128 };
 
             let to_rust_ty = match to_ty {
-                types::F32 => fx.cx.tcx.types.f32,
-                types::F64 => fx.cx.tcx.types.f64,
+                types::F32 => fx.tcx.types.f32,
+                types::F64 => fx.tcx.types.f64,
                 _ => unreachable!(),
             };
 
             return fx
-                .easy_call(
-                    &name,
-                    &[CValue::by_val(from, fx.layout_of(from_rust_ty))],
-                    to_rust_ty,
-                )
+                .easy_call(&name, &[CValue::by_val(from, fx.layout_of(from_rust_ty))], to_rust_ty)
                 .load_scalar(fx);
         }
 
@@ -113,7 +84,7 @@ pub(crate) fn clif_int_or_float_cast(
             fx.bcx.ins().fcvt_from_uint(to_ty, from)
         }
     } else if from_ty.is_float() && to_ty.is_int() {
-        if to_ty == types::I128 {
+        let val = if to_ty == types::I128 {
             // _____sssf___
             // __fix   sfti: f32 -> i128
             // __fix   dfti: f64 -> i128
@@ -131,28 +102,16 @@ pub(crate) fn clif_int_or_float_cast(
             );
 
             let from_rust_ty = match from_ty {
-                types::F32 => fx.cx.tcx.types.f32,
-                types::F64 => fx.cx.tcx.types.f64,
+                types::F32 => fx.tcx.types.f32,
+                types::F64 => fx.tcx.types.f64,
                 _ => unreachable!(),
             };
 
-            let to_rust_ty = if to_signed {
-                fx.cx.tcx.types.i128
-            } else {
-                fx.cx.tcx.types.u128
-            };
-
-            return fx
-                .easy_call(
-                    &name,
-                    &[CValue::by_val(from, fx.layout_of(from_rust_ty))],
-                    to_rust_ty,
-                )
-                .load_scalar(fx);
-        }
+            let to_rust_ty = if to_signed { fx.tcx.types.i128 } else { fx.tcx.types.u128 };
 
-        // float -> int-like
-        if to_ty == types::I8 || to_ty == types::I16 {
+            fx.easy_call(&name, &[CValue::by_val(from, fx.layout_of(from_rust_ty))], to_rust_ty)
+                .load_scalar(fx)
+        } else if to_ty == types::I8 || to_ty == types::I16 {
             // FIXME implement fcvt_to_*int_sat.i8/i16
             let val = if to_signed {
                 fx.bcx.ins().fcvt_to_sint_sat(types::I32, from)
@@ -179,12 +138,27 @@ pub(crate) fn clif_int_or_float_cast(
                 fx.bcx.ins().select(has_overflow, max_val, val)
             };
             fx.bcx.ins().ireduce(to_ty, val)
+        } else if to_signed {
+            fx.bcx.ins().fcvt_to_sint_sat(to_ty, from)
         } else {
-            if to_signed {
-                fx.bcx.ins().fcvt_to_sint_sat(to_ty, from)
-            } else {
-                fx.bcx.ins().fcvt_to_uint_sat(to_ty, from)
-            }
+            fx.bcx.ins().fcvt_to_uint_sat(to_ty, from)
+        };
+
+        if let Some(false) = fx.tcx.sess.opts.debugging_opts.saturating_float_casts {
+            return val;
+        }
+
+        let is_not_nan = fx.bcx.ins().fcmp(FloatCC::Equal, from, from);
+        if to_ty == types::I128 {
+            // FIXME(bytecodealliance/wasmtime#3963): select.i128 on fcmp eq miscompiles
+            let (lsb, msb) = fx.bcx.ins().isplit(val);
+            let zero = fx.bcx.ins().iconst(types::I64, 0);
+            let lsb = fx.bcx.ins().select(is_not_nan, lsb, zero);
+            let msb = fx.bcx.ins().select(is_not_nan, msb, zero);
+            fx.bcx.ins().iconcat(lsb, msb)
+        } else {
+            let zero = fx.bcx.ins().iconst(to_ty, 0);
+            fx.bcx.ins().select(is_not_nan, val, zero)
         }
     } else if from_ty.is_float() && to_ty.is_float() {
         // float -> float