diff options
Diffstat (limited to 'compiler/rustc_codegen_cranelift/src/cast.rs')
| -rw-r--r-- | compiler/rustc_codegen_cranelift/src/cast.rs | 29 |
1 files changed, 21 insertions, 8 deletions
diff --git a/compiler/rustc_codegen_cranelift/src/cast.rs b/compiler/rustc_codegen_cranelift/src/cast.rs index e7e6afeb865..e19070774c6 100644 --- a/compiler/rustc_codegen_cranelift/src/cast.rs +++ b/compiler/rustc_codegen_cranelift/src/cast.rs @@ -84,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 @@ -109,13 +109,9 @@ pub(crate) fn clif_int_or_float_cast( let to_rust_ty = if to_signed { fx.tcx.types.i128 } else { fx.tcx.types.u128 }; - return fx - .easy_call(&name, &[CValue::by_val(from, fx.layout_of(from_rust_ty))], to_rust_ty) - .load_scalar(fx); - } - - // 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) @@ -146,6 +142,23 @@ pub(crate) fn clif_int_or_float_cast( fx.bcx.ins().fcvt_to_sint_sat(to_ty, from) } else { 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 |
