@@ -13,6 +13,11 @@ pub(crate) fn f16_to_f32(fx: &mut FunctionCx<'_, '_, '_>, value: Value) -> Value
13
13
fx. lib_call ( "__extendhfsf2" , vec ! [ arg_ty] , vec ! [ AbiParam :: new( types:: F32 ) ] , & [ value] ) [ 0 ]
14
14
}
15
15
16
+ fn f16_to_f64 ( fx : & mut FunctionCx < ' _ , ' _ , ' _ > , value : Value ) -> Value {
17
+ let ret = f16_to_f32 ( fx, value) ;
18
+ fx. bcx . ins ( ) . fpromote ( types:: F64 , ret)
19
+ }
20
+
16
21
pub ( crate ) fn f32_to_f16 ( fx : & mut FunctionCx < ' _ , ' _ , ' _ > , value : Value ) -> Value {
17
22
let ret_ty = if fx. tcx . sess . target . vendor == "apple" && fx. tcx . sess . target . arch == "x86_64" {
18
23
types:: I16
@@ -28,6 +33,21 @@ pub(crate) fn f32_to_f16(fx: &mut FunctionCx<'_, '_, '_>, value: Value) -> Value
28
33
if ret_ty == types:: I16 { fx. bcx . ins ( ) . bitcast ( types:: F16 , MemFlags :: new ( ) , ret) } else { ret }
29
34
}
30
35
36
+ fn f64_to_f16 ( fx : & mut FunctionCx < ' _ , ' _ , ' _ > , value : Value ) -> Value {
37
+ let ret_ty = if fx. tcx . sess . target . vendor == "apple" && fx. tcx . sess . target . arch == "x86_64" {
38
+ types:: I16
39
+ } else {
40
+ types:: F16
41
+ } ;
42
+ let ret = fx. lib_call (
43
+ "__truncdfhf2" ,
44
+ vec ! [ AbiParam :: new( types:: F64 ) ] ,
45
+ vec ! [ AbiParam :: new( ret_ty) ] ,
46
+ & [ value] ,
47
+ ) [ 0 ] ;
48
+ if ret_ty == types:: I16 { fx. bcx . ins ( ) . bitcast ( types:: F16 , MemFlags :: new ( ) , ret) } else { ret }
49
+ }
50
+
31
51
pub ( crate ) fn fcmp ( fx : & mut FunctionCx < ' _ , ' _ , ' _ > , cc : FloatCC , lhs : Value , rhs : Value ) -> Value {
32
52
let ty = fx. bcx . func . dfg . value_type ( lhs) ;
33
53
match ty {
@@ -97,6 +117,109 @@ pub(crate) fn neg_f128(fx: &mut FunctionCx<'_, '_, '_>, value: Value) -> Value {
97
117
fx. bcx . ins ( ) . bitcast ( types:: F128 , MemFlags :: new ( ) , bits)
98
118
}
99
119
120
+ pub ( crate ) fn codegen_cast (
121
+ fx : & mut FunctionCx < ' _ , ' _ , ' _ > ,
122
+ from : Value ,
123
+ from_signed : bool ,
124
+ to_ty : Type ,
125
+ to_signed : bool ,
126
+ ) -> Value {
127
+ let from_ty = fx. bcx . func . dfg . value_type ( from) ;
128
+ if from_ty. is_float ( ) && to_ty. is_float ( ) {
129
+ let name = match ( from_ty, to_ty) {
130
+ ( types:: F16 , types:: F32 ) => return f16_to_f32 ( fx, from) ,
131
+ ( types:: F16 , types:: F64 ) => return f16_to_f64 ( fx, from) ,
132
+ ( types:: F16 , types:: F128 ) => "__extendhftf2" ,
133
+ ( types:: F32 , types:: F128 ) => "__extendsftf2" ,
134
+ ( types:: F64 , types:: F128 ) => "__extenddftf2" ,
135
+ ( types:: F128 , types:: F64 ) => "__trunctfdf2" ,
136
+ ( types:: F128 , types:: F32 ) => "__trunctfsf2" ,
137
+ ( types:: F128 , types:: F16 ) => "__trunctfhf2" ,
138
+ ( types:: F64 , types:: F16 ) => return f64_to_f16 ( fx, from) ,
139
+ ( types:: F32 , types:: F16 ) => return f32_to_f16 ( fx, from) ,
140
+ _ => unreachable ! ( "{from_ty:?} -> {to_ty:?}" ) ,
141
+ } ;
142
+ fx. lib_call ( name, vec ! [ AbiParam :: new( from_ty) ] , vec ! [ AbiParam :: new( to_ty) ] , & [ from] ) [ 0 ]
143
+ } else if from_ty. is_int ( ) && to_ty == types:: F16 {
144
+ let res = clif_int_or_float_cast ( fx, from, from_signed, types:: F32 , false ) ;
145
+ f32_to_f16 ( fx, res)
146
+ } else if from_ty == types:: F16 && to_ty. is_int ( ) {
147
+ let from = f16_to_f32 ( fx, from) ;
148
+ clif_int_or_float_cast ( fx, from, false , to_ty, to_signed)
149
+ } else if from_ty. is_int ( ) && to_ty == types:: F128 {
150
+ let ( from, from_ty) = if from_ty. bits ( ) < 32 {
151
+ ( clif_int_or_float_cast ( fx, from, from_signed, types:: I32 , from_signed) , types:: I32 )
152
+ } else {
153
+ ( from, from_ty)
154
+ } ;
155
+ let name = format ! (
156
+ "__float{sign}{size}itf" ,
157
+ sign = if from_signed { "" } else { "un" } ,
158
+ size = match from_ty {
159
+ types:: I32 => 's' ,
160
+ types:: I64 => 'd' ,
161
+ types:: I128 => 't' ,
162
+ _ => unreachable!( "{from_ty:?}" ) ,
163
+ } ,
164
+ ) ;
165
+ fx. lib_call (
166
+ & name,
167
+ vec ! [ lib_call_arg_param( fx. tcx, from_ty, from_signed) ] ,
168
+ vec ! [ AbiParam :: new( to_ty) ] ,
169
+ & [ from] ,
170
+ ) [ 0 ]
171
+ } else if from_ty == types:: F128 && to_ty. is_int ( ) {
172
+ let ret_ty = if to_ty. bits ( ) < 32 { types:: I32 } else { to_ty } ;
173
+ let name = format ! (
174
+ "__fix{sign}tf{size}i" ,
175
+ sign = if from_signed { "" } else { "un" } ,
176
+ size = match ret_ty {
177
+ types:: I32 => 's' ,
178
+ types:: I64 => 'd' ,
179
+ types:: I128 => 't' ,
180
+ _ => unreachable!( "{from_ty:?}" ) ,
181
+ } ,
182
+ ) ;
183
+ let ret =
184
+ fx. lib_call ( & name, vec ! [ AbiParam :: new( from_ty) ] , vec ! [ AbiParam :: new( to_ty) ] , & [ from] )
185
+ [ 0 ] ;
186
+ let val = if ret_ty == to_ty {
187
+ ret
188
+ } else {
189
+ let ( min, max) = match ( to_ty, to_signed) {
190
+ ( types:: I8 , false ) => ( 0 , i64:: from ( u8:: MAX ) ) ,
191
+ ( types:: I16 , false ) => ( 0 , i64:: from ( u16:: MAX ) ) ,
192
+ ( types:: I8 , true ) => ( i64:: from ( i8:: MIN as u32 ) , i64:: from ( i8:: MAX as u32 ) ) ,
193
+ ( types:: I16 , true ) => ( i64:: from ( i16:: MIN as u32 ) , i64:: from ( i16:: MAX as u32 ) ) ,
194
+ _ => unreachable ! ( "{to_ty:?}" ) ,
195
+ } ;
196
+ let min_val = fx. bcx . ins ( ) . iconst ( types:: I32 , min) ;
197
+ let max_val = fx. bcx . ins ( ) . iconst ( types:: I32 , max) ;
198
+
199
+ let val = if to_signed {
200
+ let has_underflow = fx. bcx . ins ( ) . icmp_imm ( IntCC :: SignedLessThan , ret, min) ;
201
+ let has_overflow = fx. bcx . ins ( ) . icmp_imm ( IntCC :: SignedGreaterThan , ret, max) ;
202
+ let bottom_capped = fx. bcx . ins ( ) . select ( has_underflow, min_val, ret) ;
203
+ fx. bcx . ins ( ) . select ( has_overflow, max_val, bottom_capped)
204
+ } else {
205
+ let has_overflow = fx. bcx . ins ( ) . icmp_imm ( IntCC :: UnsignedGreaterThan , ret, max) ;
206
+ fx. bcx . ins ( ) . select ( has_overflow, max_val, ret)
207
+ } ;
208
+ fx. bcx . ins ( ) . ireduce ( to_ty, val)
209
+ } ;
210
+
211
+ if let Some ( false ) = fx. tcx . sess . opts . unstable_opts . saturating_float_casts {
212
+ return val;
213
+ }
214
+
215
+ let is_not_nan = fcmp ( fx, FloatCC :: Equal , from, from) ;
216
+ let zero = type_zero_value ( & mut fx. bcx , to_ty) ;
217
+ fx. bcx . ins ( ) . select ( is_not_nan, val, zero)
218
+ } else {
219
+ unreachable ! ( "{from_ty:?} -> {to_ty:?}" ) ;
220
+ }
221
+ }
222
+
100
223
pub ( crate ) fn fmin_f128 ( fx : & mut FunctionCx < ' _ , ' _ , ' _ > , a : Value , b : Value ) -> Value {
101
224
fx. lib_call (
102
225
"fminimumf128" ,
0 commit comments