]> git.lizzy.rs Git - rust.git/blob - src/cast.rs
Use anonymous lifetimes where possible
[rust.git] / src / cast.rs
1 use crate::prelude::*;
2
3 pub fn clif_intcast(
4     fx: &mut FunctionCx<'_, '_, impl Backend>,
5     val: Value,
6     to: Type,
7     signed: bool,
8 ) -> Value {
9     let from = fx.bcx.func.dfg.value_type(val);
10     match (from, to) {
11         // equal
12         (_, _) if from == to => val,
13
14         // extend
15         (_, types::I128) => {
16             let wider = if from == types::I64 {
17                 val
18             } else if signed {
19                 fx.bcx.ins().sextend(types::I64, val)
20             } else {
21                 fx.bcx.ins().uextend(types::I64, val)
22             };
23             let zero = fx.bcx.ins().iconst(types::I64, 0);
24             fx.bcx.ins().iconcat(wider, zero)
25         }
26         (_, _) if to.wider_or_equal(from) => {
27             if signed {
28                 fx.bcx.ins().sextend(to, val)
29             } else {
30                 fx.bcx.ins().uextend(to, val)
31             }
32         }
33
34         // reduce
35         (types::I128, _) => {
36             let (lsb, _msb) = fx.bcx.ins().isplit(val);
37             if to == types::I64 {
38                 lsb
39             } else {
40                 fx.bcx.ins().ireduce(to, lsb)
41             }
42         }
43         (_, _) => {
44             fx.bcx.ins().ireduce(to, val)
45         }
46     }
47 }
48
49 pub fn clif_int_or_float_cast(
50     fx: &mut FunctionCx<'_, '_, impl Backend>,
51     from: Value,
52     from_signed: bool,
53     to_ty: Type,
54     to_signed: bool,
55 ) -> Value {
56     let from_ty = fx.bcx.func.dfg.value_type(from);
57
58     if from_ty.is_int() && to_ty.is_int() {
59         // int-like -> int-like
60         clif_intcast(
61             fx,
62             from,
63             to_ty,
64             from_signed, // FIXME is this correct?
65         )
66     } else if from_ty.is_int() && to_ty.is_float() {
67         // int-like -> float
68         if from_signed {
69             fx.bcx.ins().fcvt_from_sint(to_ty, from)
70         } else {
71             fx.bcx.ins().fcvt_from_uint(to_ty, from)
72         }
73     } else if from_ty.is_float() && to_ty.is_int() {
74         // float -> int-like
75         if to_ty == types::I8 || to_ty == types::I16 {
76             // FIXME implement fcvt_to_*int_sat.i8/i16
77             let val = if to_signed {
78                 fx.bcx.ins().fcvt_to_sint_sat(types::I32, from)
79             } else {
80                 fx.bcx.ins().fcvt_to_uint_sat(types::I32, from)
81             };
82             let (min, max) = type_min_max_value(to_ty, to_signed);
83             let min_val = fx.bcx.ins().iconst(types::I32, min);
84             let max_val = fx.bcx.ins().iconst(types::I32, max);
85
86             let val = if to_signed {
87                 let has_underflow = fx.bcx.ins().icmp_imm(
88                     IntCC::SignedLessThan,
89                     val,
90                     min,
91                 );
92                 let has_overflow = fx.bcx.ins().icmp_imm(
93                     IntCC::SignedGreaterThan,
94                     val,
95                     max,
96                 );
97                 let bottom_capped = fx.bcx.ins().select(has_underflow, min_val, val);
98                 fx.bcx.ins().select(has_overflow, max_val, bottom_capped)
99             } else {
100                 let has_overflow = fx.bcx.ins().icmp_imm(
101                     IntCC::UnsignedGreaterThan,
102                     val,
103                     max,
104                 );
105                 fx.bcx.ins().select(has_overflow, max_val, val)
106             };
107             fx.bcx.ins().ireduce(to_ty, val)
108         } else {
109             if to_signed {
110                 fx.bcx.ins().fcvt_to_sint_sat(to_ty, from)
111             } else {
112                 fx.bcx.ins().fcvt_to_uint_sat(to_ty, from)
113             }
114         }
115     } else if from_ty.is_float() && to_ty.is_float() {
116         // float -> float
117         match (from_ty, to_ty) {
118             (types::F32, types::F64) => {
119                 fx.bcx.ins().fpromote(types::F64, from)
120             }
121             (types::F64, types::F32) => {
122                 fx.bcx.ins().fdemote(types::F32, from)
123             }
124             _ => from,
125         }
126     } else {
127         unreachable!("cast value from {:?} to {:?}", from_ty, to_ty);
128     }
129 }