use crate::prelude::*;
pub(crate) fn clif_intcast(
- fx: &mut FunctionCx<'_, '_, impl Backend>,
+ fx: &mut FunctionCx<'_, '_, '_>,
val: Value,
to: Type,
signed: bool,
(_, _) 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)
}
// 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,
},
);
- let from_rust_ty = if from_signed {
- fx.tcx.types.i128
- } else {
- fx.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.tcx.types.f32,
};
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);
}
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
_ => unreachable!(),
};
- 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);
- }
+ 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)
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.unstable_opts.saturating_float_casts {
+ return val;
}
+
+ let is_not_nan = fx.bcx.ins().fcmp(FloatCC::Equal, from, from);
+ 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
match (from_ty, to_ty) {