4 fx: &mut FunctionCx<'_, '_, impl Backend>,
9 let from = fx.bcx.func.dfg.value_type(val);
12 (_, _) if from == to => val,
16 let wider = if from == types::I64 {
19 fx.bcx.ins().sextend(types::I64, val)
21 fx.bcx.ins().uextend(types::I64, val)
23 let zero = fx.bcx.ins().iconst(types::I64, 0);
24 fx.bcx.ins().iconcat(wider, zero)
26 (_, _) if to.wider_or_equal(from) => {
28 fx.bcx.ins().sextend(to, val)
30 fx.bcx.ins().uextend(to, val)
36 let (lsb, _msb) = fx.bcx.ins().isplit(val);
40 fx.bcx.ins().ireduce(to, lsb)
43 (_, _) => fx.bcx.ins().ireduce(to, val),
47 pub fn clif_int_or_float_cast(
48 fx: &mut FunctionCx<'_, '_, impl Backend>,
54 let from_ty = fx.bcx.func.dfg.value_type(from);
56 if from_ty.is_int() && to_ty.is_int() {
57 // int-like -> int-like
62 from_signed, // FIXME is this correct?
64 } else if from_ty.is_int() && to_ty.is_float() {
65 if from_ty == types::I128 {
67 // __float tisf: i128 -> f32
68 // __float tidf: i128 -> f64
69 // __floatuntisf: u128 -> f32
70 // __floatuntidf: u128 -> f64
73 "__float{sign}ti{flt}f",
74 sign = if from_signed { "" } else { "un" },
78 _ => unreachable!("{:?}", to_ty),
82 let from_rust_ty = if from_signed {
88 let to_rust_ty = match to_ty {
89 types::F32 => fx.tcx.types.f32,
90 types::F64 => fx.tcx.types.f64,
97 &[CValue::by_val(from, fx.layout_of(from_rust_ty))],
105 fx.bcx.ins().fcvt_from_sint(to_ty, from)
107 fx.bcx.ins().fcvt_from_uint(to_ty, from)
109 } else if from_ty.is_float() && to_ty.is_int() {
110 if to_ty == types::I128 {
112 // __fix sfti: f32 -> i128
113 // __fix dfti: f64 -> i128
114 // __fixunssfti: f32 -> u128
115 // __fixunsdfti: f64 -> u128
118 "__fix{sign}{flt}fti",
119 sign = if to_signed { "" } else { "uns" },
120 flt = match from_ty {
123 _ => unreachable!("{:?}", to_ty),
127 let from_rust_ty = match from_ty {
128 types::F32 => fx.tcx.types.f32,
129 types::F64 => fx.tcx.types.f64,
133 let to_rust_ty = if to_signed {
142 &[CValue::by_val(from, fx.layout_of(from_rust_ty))],
149 if to_ty == types::I8 || to_ty == types::I16 {
150 // FIXME implement fcvt_to_*int_sat.i8/i16
151 let val = if to_signed {
152 fx.bcx.ins().fcvt_to_sint_sat(types::I32, from)
154 fx.bcx.ins().fcvt_to_uint_sat(types::I32, from)
156 let (min, max) = type_min_max_value(to_ty, to_signed);
157 let min_val = fx.bcx.ins().iconst(types::I32, min);
158 let max_val = fx.bcx.ins().iconst(types::I32, max);
160 let val = if to_signed {
161 let has_underflow = fx.bcx.ins().icmp_imm(IntCC::SignedLessThan, val, min);
162 let has_overflow = fx.bcx.ins().icmp_imm(IntCC::SignedGreaterThan, val, max);
163 let bottom_capped = fx.bcx.ins().select(has_underflow, min_val, val);
164 fx.bcx.ins().select(has_overflow, max_val, bottom_capped)
166 let has_overflow = fx.bcx.ins().icmp_imm(IntCC::UnsignedGreaterThan, val, max);
167 fx.bcx.ins().select(has_overflow, max_val, val)
169 fx.bcx.ins().ireduce(to_ty, val)
172 fx.bcx.ins().fcvt_to_sint_sat(to_ty, from)
174 fx.bcx.ins().fcvt_to_uint_sat(to_ty, from)
177 } else if from_ty.is_float() && to_ty.is_float() {
179 match (from_ty, to_ty) {
180 (types::F32, types::F64) => fx.bcx.ins().fpromote(types::F64, from),
181 (types::F64, types::F32) => fx.bcx.ins().fdemote(types::F32, from),
185 unreachable!("cast value from {:?} to {:?}", from_ty, to_ty);