]>
Commit | Line | Data |
---|---|---|
e9174d1e SL |
1 | //! Type-checking for the rust-intrinsic and platform-intrinsic |
2 | //! intrinsics that the compiler exposes. | |
3 | ||
1b1a35ee XL |
4 | use crate::errors::{ |
5 | SimdShuffleMissingLength, UnrecognizedAtomicOperation, UnrecognizedIntrinsicFunction, | |
6 | WrongNumberOfTypeArgumentsToInstrinsic, | |
7 | }; | |
9fa01778 | 8 | use crate::require_same_types; |
e9174d1e | 9 | |
dfeec247 XL |
10 | use rustc_errors::struct_span_err; |
11 | use rustc_hir as hir; | |
ba9703b0 XL |
12 | use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; |
13 | use rustc_middle::ty::subst::Subst; | |
fc512014 | 14 | use rustc_middle::ty::{self, TyCtxt}; |
f035d41b | 15 | use rustc_span::symbol::{kw, sym, Symbol}; |
83c7162d | 16 | use rustc_target::spec::abi::Abi; |
60c5eb7d | 17 | |
476ff2be SL |
18 | use std::iter; |
19 | ||
dc9dc135 XL |
20 | fn equate_intrinsic_type<'tcx>( |
21 | tcx: TyCtxt<'tcx>, | |
dfeec247 | 22 | it: &hir::ForeignItem<'_>, |
b7449926 | 23 | n_tps: usize, |
fc512014 | 24 | sig: ty::PolyFnSig<'tcx>, |
b7449926 | 25 | ) { |
e74abb32 | 26 | match it.kind { |
8faf50e0 | 27 | hir::ForeignItemKind::Fn(..) => {} |
041b39d2 | 28 | _ => { |
dfeec247 | 29 | struct_span_err!(tcx.sess, it.span, E0622, "intrinsic must be a function") |
041b39d2 XL |
30 | .span_label(it.span, "expected a function") |
31 | .emit(); | |
32 | return; | |
33 | } | |
34 | } | |
54a0048b | 35 | |
6a06907d | 36 | let i_n_tps = tcx.generics_of(it.def_id).own_counts().types; |
e9174d1e | 37 | if i_n_tps != n_tps { |
e74abb32 | 38 | let span = match it.kind { |
8faf50e0 | 39 | hir::ForeignItemKind::Fn(_, _, ref generics) => generics.span, |
dfeec247 | 40 | _ => bug!(), |
9e0c209e SL |
41 | }; |
42 | ||
1b1a35ee | 43 | tcx.sess.emit_err(WrongNumberOfTypeArgumentsToInstrinsic { |
dfeec247 | 44 | span, |
1b1a35ee XL |
45 | found: i_n_tps, |
46 | expected: n_tps, | |
47 | }); | |
041b39d2 | 48 | return; |
e9174d1e | 49 | } |
041b39d2 | 50 | |
fc512014 | 51 | let fty = tcx.mk_fn_ptr(sig); |
6a06907d XL |
52 | let cause = ObligationCause::new(it.span, it.hir_id(), ObligationCauseCode::IntrinsicType); |
53 | require_same_types(tcx, &cause, tcx.mk_fn_ptr(tcx.fn_sig(it.def_id)), fty); | |
e9174d1e SL |
54 | } |
55 | ||
9fa01778 | 56 | /// Returns `true` if the given intrinsic is unsafe to call or not. |
f035d41b | 57 | pub fn intrinsic_operation_unsafety(intrinsic: Symbol) -> hir::Unsafety { |
0731742a | 58 | match intrinsic { |
f035d41b XL |
59 | sym::abort |
60 | | sym::size_of | |
61 | | sym::min_align_of | |
62 | | sym::needs_drop | |
63 | | sym::caller_location | |
f035d41b XL |
64 | | sym::add_with_overflow |
65 | | sym::sub_with_overflow | |
66 | | sym::mul_with_overflow | |
67 | | sym::wrapping_add | |
68 | | sym::wrapping_sub | |
69 | | sym::wrapping_mul | |
70 | | sym::saturating_add | |
71 | | sym::saturating_sub | |
72 | | sym::rotate_left | |
73 | | sym::rotate_right | |
74 | | sym::ctpop | |
75 | | sym::ctlz | |
76 | | sym::cttz | |
77 | | sym::bswap | |
78 | | sym::bitreverse | |
79 | | sym::discriminant_value | |
80 | | sym::type_id | |
81 | | sym::likely | |
82 | | sym::unlikely | |
83 | | sym::ptr_guaranteed_eq | |
84 | | sym::ptr_guaranteed_ne | |
85 | | sym::minnumf32 | |
86 | | sym::minnumf64 | |
87 | | sym::maxnumf32 | |
88 | | sym::rustc_peek | |
89 | | sym::maxnumf64 | |
90 | | sym::type_name | |
5869c6ff | 91 | | sym::forget |
f035d41b | 92 | | sym::variant_count => hir::Unsafety::Normal, |
0731742a XL |
93 | _ => hir::Unsafety::Unsafe, |
94 | } | |
95 | } | |
96 | ||
1b1a35ee XL |
97 | /// Remember to add all intrinsics here, in `compiler/rustc_codegen_llvm/src/intrinsic.rs`, |
98 | /// and in `library/core/src/intrinsics.rs`. | |
dfeec247 | 99 | pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { |
e74abb32 | 100 | let param = |n| tcx.mk_ty_param(n, Symbol::intern(&format!("P{}", n))); |
6a06907d | 101 | let intrinsic_name = tcx.item_name(it.def_id.to_def_id()); |
f035d41b | 102 | let name_str = intrinsic_name.as_str(); |
a1dfa0c6 | 103 | |
dc9dc135 | 104 | let mk_va_list_ty = |mutbl| { |
a1dfa0c6 | 105 | tcx.lang_items().va_list().map(|did| { |
fc512014 XL |
106 | let region = tcx |
107 | .mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { kind: ty::BrAnon(0) })); | |
108 | let env_region = | |
109 | tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { kind: ty::BrEnv })); | |
a1dfa0c6 | 110 | let va_list_ty = tcx.type_of(did).subst(tcx, &[region.into()]); |
fc512014 | 111 | (tcx.mk_ref(env_region, ty::TypeAndMut { ty: va_list_ty, mutbl }), va_list_ty) |
a1dfa0c6 XL |
112 | }) |
113 | }; | |
114 | ||
f035d41b XL |
115 | let (n_tps, inputs, output, unsafety) = if name_str.starts_with("atomic_") { |
116 | let split: Vec<&str> = name_str.split('_').collect(); | |
0bf4aa26 | 117 | assert!(split.len() >= 2, "Atomic intrinsic in an incorrect format"); |
e9174d1e SL |
118 | |
119 | //We only care about the operation here | |
120 | let (n_tps, inputs, output) = match split[1] { | |
dfeec247 XL |
121 | "cxchg" | "cxchgweak" => ( |
122 | 1, | |
123 | vec![tcx.mk_mut_ptr(param(0)), param(0), param(0)], | |
124 | tcx.intern_tup(&[param(0), tcx.types.bool]), | |
125 | ), | |
126 | "load" => (1, vec![tcx.mk_imm_ptr(param(0))], param(0)), | |
127 | "store" => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()), | |
128 | ||
129 | "xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" | "min" | "umax" | |
130 | | "umin" => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], param(0)), | |
131 | "fence" | "singlethreadfence" => (0, Vec::new(), tcx.mk_unit()), | |
e9174d1e | 132 | op => { |
1b1a35ee | 133 | tcx.sess.emit_err(UnrecognizedAtomicOperation { span: it.span, op }); |
e9174d1e SL |
134 | return; |
135 | } | |
136 | }; | |
b7449926 | 137 | (n_tps, inputs, output, hir::Unsafety::Unsafe) |
e9174d1e | 138 | } else { |
f035d41b XL |
139 | let unsafety = intrinsic_operation_unsafety(intrinsic_name); |
140 | let (n_tps, inputs, output) = match intrinsic_name { | |
141 | sym::abort => (0, Vec::new(), tcx.types.never), | |
142 | sym::unreachable => (0, Vec::new(), tcx.types.never), | |
143 | sym::breakpoint => (0, Vec::new(), tcx.mk_unit()), | |
144 | sym::size_of | sym::pref_align_of | sym::min_align_of | sym::variant_count => { | |
145 | (1, Vec::new(), tcx.types.usize) | |
146 | } | |
147 | sym::size_of_val | sym::min_align_of_val => { | |
ba9703b0 XL |
148 | (1, vec![tcx.mk_imm_ptr(param(0))], tcx.types.usize) |
149 | } | |
f035d41b XL |
150 | sym::rustc_peek => (1, vec![param(0)], param(0)), |
151 | sym::caller_location => (0, vec![], tcx.caller_location_ty()), | |
152 | sym::assert_inhabited | sym::assert_zero_valid | sym::assert_uninit_valid => { | |
ba9703b0 XL |
153 | (1, Vec::new(), tcx.mk_unit()) |
154 | } | |
f035d41b XL |
155 | sym::forget => (1, vec![param(0)], tcx.mk_unit()), |
156 | sym::transmute => (2, vec![param(0)], param(1)), | |
f035d41b XL |
157 | sym::prefetch_read_data |
158 | | sym::prefetch_write_data | |
159 | | sym::prefetch_read_instruction | |
160 | | sym::prefetch_write_instruction => ( | |
dfeec247 XL |
161 | 1, |
162 | vec![ | |
163 | tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }), | |
164 | tcx.types.i32, | |
165 | ], | |
166 | tcx.mk_unit(), | |
167 | ), | |
f035d41b XL |
168 | sym::drop_in_place => (1, vec![tcx.mk_mut_ptr(param(0))], tcx.mk_unit()), |
169 | sym::needs_drop => (1, Vec::new(), tcx.types.bool), | |
e9174d1e | 170 | |
f035d41b XL |
171 | sym::type_name => (1, Vec::new(), tcx.mk_static_str()), |
172 | sym::type_id => (1, Vec::new(), tcx.types.u64), | |
173 | sym::offset | sym::arith_offset => ( | |
dfeec247 XL |
174 | 1, |
175 | vec![ | |
176 | tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }), | |
177 | tcx.types.isize, | |
178 | ], | |
179 | tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }), | |
180 | ), | |
f035d41b | 181 | sym::copy | sym::copy_nonoverlapping => ( |
dfeec247 XL |
182 | 1, |
183 | vec![ | |
184 | tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }), | |
185 | tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Mut }), | |
186 | tcx.types.usize, | |
187 | ], | |
188 | tcx.mk_unit(), | |
189 | ), | |
f035d41b | 190 | sym::volatile_copy_memory | sym::volatile_copy_nonoverlapping_memory => ( |
dfeec247 XL |
191 | 1, |
192 | vec![ | |
193 | tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Mut }), | |
194 | tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }), | |
195 | tcx.types.usize, | |
196 | ], | |
197 | tcx.mk_unit(), | |
198 | ), | |
f035d41b | 199 | sym::write_bytes | sym::volatile_set_memory => ( |
dfeec247 XL |
200 | 1, |
201 | vec![ | |
202 | tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Mut }), | |
203 | tcx.types.u8, | |
204 | tcx.types.usize, | |
205 | ], | |
206 | tcx.mk_unit(), | |
207 | ), | |
f035d41b XL |
208 | sym::sqrtf32 => (0, vec![tcx.types.f32], tcx.types.f32), |
209 | sym::sqrtf64 => (0, vec![tcx.types.f64], tcx.types.f64), | |
210 | sym::powif32 => (0, vec![tcx.types.f32, tcx.types.i32], tcx.types.f32), | |
211 | sym::powif64 => (0, vec![tcx.types.f64, tcx.types.i32], tcx.types.f64), | |
212 | sym::sinf32 => (0, vec![tcx.types.f32], tcx.types.f32), | |
213 | sym::sinf64 => (0, vec![tcx.types.f64], tcx.types.f64), | |
214 | sym::cosf32 => (0, vec![tcx.types.f32], tcx.types.f32), | |
215 | sym::cosf64 => (0, vec![tcx.types.f64], tcx.types.f64), | |
216 | sym::powf32 => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32), | |
217 | sym::powf64 => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64), | |
218 | sym::expf32 => (0, vec![tcx.types.f32], tcx.types.f32), | |
219 | sym::expf64 => (0, vec![tcx.types.f64], tcx.types.f64), | |
220 | sym::exp2f32 => (0, vec![tcx.types.f32], tcx.types.f32), | |
221 | sym::exp2f64 => (0, vec![tcx.types.f64], tcx.types.f64), | |
222 | sym::logf32 => (0, vec![tcx.types.f32], tcx.types.f32), | |
223 | sym::logf64 => (0, vec![tcx.types.f64], tcx.types.f64), | |
224 | sym::log10f32 => (0, vec![tcx.types.f32], tcx.types.f32), | |
225 | sym::log10f64 => (0, vec![tcx.types.f64], tcx.types.f64), | |
226 | sym::log2f32 => (0, vec![tcx.types.f32], tcx.types.f32), | |
227 | sym::log2f64 => (0, vec![tcx.types.f64], tcx.types.f64), | |
228 | sym::fmaf32 => (0, vec![tcx.types.f32, tcx.types.f32, tcx.types.f32], tcx.types.f32), | |
229 | sym::fmaf64 => (0, vec![tcx.types.f64, tcx.types.f64, tcx.types.f64], tcx.types.f64), | |
230 | sym::fabsf32 => (0, vec![tcx.types.f32], tcx.types.f32), | |
231 | sym::fabsf64 => (0, vec![tcx.types.f64], tcx.types.f64), | |
232 | sym::minnumf32 => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32), | |
233 | sym::minnumf64 => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64), | |
234 | sym::maxnumf32 => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32), | |
235 | sym::maxnumf64 => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64), | |
236 | sym::copysignf32 => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32), | |
237 | sym::copysignf64 => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64), | |
238 | sym::floorf32 => (0, vec![tcx.types.f32], tcx.types.f32), | |
239 | sym::floorf64 => (0, vec![tcx.types.f64], tcx.types.f64), | |
240 | sym::ceilf32 => (0, vec![tcx.types.f32], tcx.types.f32), | |
241 | sym::ceilf64 => (0, vec![tcx.types.f64], tcx.types.f64), | |
242 | sym::truncf32 => (0, vec![tcx.types.f32], tcx.types.f32), | |
243 | sym::truncf64 => (0, vec![tcx.types.f64], tcx.types.f64), | |
244 | sym::rintf32 => (0, vec![tcx.types.f32], tcx.types.f32), | |
245 | sym::rintf64 => (0, vec![tcx.types.f64], tcx.types.f64), | |
246 | sym::nearbyintf32 => (0, vec![tcx.types.f32], tcx.types.f32), | |
247 | sym::nearbyintf64 => (0, vec![tcx.types.f64], tcx.types.f64), | |
248 | sym::roundf32 => (0, vec![tcx.types.f32], tcx.types.f32), | |
249 | sym::roundf64 => (0, vec![tcx.types.f64], tcx.types.f64), | |
250 | ||
251 | sym::volatile_load | sym::unaligned_volatile_load => { | |
dfeec247 | 252 | (1, vec![tcx.mk_imm_ptr(param(0))], param(0)) |
e9174d1e | 253 | } |
f035d41b | 254 | sym::volatile_store | sym::unaligned_volatile_store => { |
dfeec247 | 255 | (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()) |
e9174d1e | 256 | } |
dfeec247 | 257 | |
f035d41b XL |
258 | sym::ctpop |
259 | | sym::ctlz | |
260 | | sym::ctlz_nonzero | |
261 | | sym::cttz | |
262 | | sym::cttz_nonzero | |
263 | | sym::bswap | |
264 | | sym::bitreverse => (1, vec![param(0)], param(0)), | |
dfeec247 | 265 | |
f035d41b | 266 | sym::add_with_overflow | sym::sub_with_overflow | sym::mul_with_overflow => { |
dfeec247 | 267 | (1, vec![param(0), param(0)], tcx.intern_tup(&[param(0), tcx.types.bool])) |
e9174d1e | 268 | } |
dfeec247 | 269 | |
f035d41b XL |
270 | sym::ptr_guaranteed_eq | sym::ptr_guaranteed_ne => { |
271 | (1, vec![tcx.mk_imm_ptr(param(0)), tcx.mk_imm_ptr(param(0))], tcx.types.bool) | |
272 | } | |
273 | ||
fc512014 XL |
274 | sym::const_allocate => { |
275 | (0, vec![tcx.types.usize, tcx.types.usize], tcx.mk_mut_ptr(tcx.types.u8)) | |
276 | } | |
277 | ||
f035d41b | 278 | sym::ptr_offset_from => { |
dfeec247 | 279 | (1, vec![tcx.mk_imm_ptr(param(0)), tcx.mk_imm_ptr(param(0))], tcx.types.isize) |
e9174d1e | 280 | } |
f035d41b | 281 | sym::unchecked_div | sym::unchecked_rem | sym::exact_div => { |
dfeec247 | 282 | (1, vec![param(0), param(0)], param(0)) |
e9174d1e | 283 | } |
f035d41b | 284 | sym::unchecked_shl | sym::unchecked_shr | sym::rotate_left | sym::rotate_right => { |
dfeec247 | 285 | (1, vec![param(0), param(0)], param(0)) |
e9174d1e | 286 | } |
f035d41b | 287 | sym::unchecked_add | sym::unchecked_sub | sym::unchecked_mul => { |
dfeec247 | 288 | (1, vec![param(0), param(0)], param(0)) |
e9174d1e | 289 | } |
f035d41b | 290 | sym::wrapping_add | sym::wrapping_sub | sym::wrapping_mul => { |
dfeec247 | 291 | (1, vec![param(0), param(0)], param(0)) |
e9174d1e | 292 | } |
f035d41b XL |
293 | sym::saturating_add | sym::saturating_sub => (1, vec![param(0), param(0)], param(0)), |
294 | sym::fadd_fast | sym::fsub_fast | sym::fmul_fast | sym::fdiv_fast | sym::frem_fast => { | |
dfeec247 | 295 | (1, vec![param(0), param(0)], param(0)) |
e9174d1e | 296 | } |
f035d41b | 297 | sym::float_to_int_unchecked => (2, vec![param(0)], param(1)), |
e9174d1e | 298 | |
f035d41b XL |
299 | sym::assume => (0, vec![tcx.types.bool], tcx.mk_unit()), |
300 | sym::likely => (0, vec![tcx.types.bool], tcx.types.bool), | |
301 | sym::unlikely => (0, vec![tcx.types.bool], tcx.types.bool), | |
e9174d1e | 302 | |
f035d41b | 303 | sym::discriminant_value => { |
f9f354fc XL |
304 | let assoc_items = |
305 | tcx.associated_items(tcx.lang_items().discriminant_kind_trait().unwrap()); | |
306 | let discriminant_def_id = assoc_items.in_definition_order().next().unwrap().def_id; | |
307 | ||
fc512014 | 308 | let br = ty::BoundRegion { kind: ty::BrAnon(0) }; |
f9f354fc XL |
309 | ( |
310 | 1, | |
fc512014 XL |
311 | vec![ |
312 | tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)), param(0)), | |
313 | ], | |
f9f354fc XL |
314 | tcx.mk_projection(discriminant_def_id, tcx.mk_substs([param(0).into()].iter())), |
315 | ) | |
316 | } | |
e9174d1e | 317 | |
f035d41b | 318 | kw::Try => { |
e9174d1e | 319 | let mut_u8 = tcx.mk_mut_ptr(tcx.types.u8); |
29967ef6 | 320 | let try_fn_ty = ty::Binder::dummy(tcx.mk_fn_sig( |
8bb4bdeb | 321 | iter::once(mut_u8), |
b7449926 | 322 | tcx.mk_unit(), |
8bb4bdeb XL |
323 | false, |
324 | hir::Unsafety::Normal, | |
325 | Abi::Rust, | |
326 | )); | |
29967ef6 | 327 | let catch_fn_ty = ty::Binder::dummy(tcx.mk_fn_sig( |
ba9703b0 XL |
328 | [mut_u8, mut_u8].iter().cloned(), |
329 | tcx.mk_unit(), | |
330 | false, | |
331 | hir::Unsafety::Normal, | |
332 | Abi::Rust, | |
333 | )); | |
334 | ( | |
335 | 0, | |
336 | vec![tcx.mk_fn_ptr(try_fn_ty), mut_u8, tcx.mk_fn_ptr(catch_fn_ty)], | |
337 | tcx.types.i32, | |
338 | ) | |
e9174d1e SL |
339 | } |
340 | ||
f035d41b | 341 | sym::va_start | sym::va_end => match mk_va_list_ty(hir::Mutability::Mut) { |
dfeec247 XL |
342 | Some((va_list_ref_ty, _)) => (0, vec![va_list_ref_ty], tcx.mk_unit()), |
343 | None => bug!("`va_list` language item needed for C-variadic intrinsics"), | |
344 | }, | |
a1dfa0c6 | 345 | |
f035d41b | 346 | sym::va_copy => match mk_va_list_ty(hir::Mutability::Not) { |
dfeec247 XL |
347 | Some((va_list_ref_ty, va_list_ty)) => { |
348 | let va_list_ptr_ty = tcx.mk_mut_ptr(va_list_ty); | |
349 | (0, vec![va_list_ptr_ty, va_list_ref_ty], tcx.mk_unit()) | |
a1dfa0c6 | 350 | } |
dfeec247 XL |
351 | None => bug!("`va_list` language item needed for C-variadic intrinsics"), |
352 | }, | |
a1dfa0c6 | 353 | |
f035d41b | 354 | sym::va_arg => match mk_va_list_ty(hir::Mutability::Mut) { |
dfeec247 XL |
355 | Some((va_list_ref_ty, _)) => (1, vec![va_list_ref_ty], param(0)), |
356 | None => bug!("`va_list` language item needed for C-variadic intrinsics"), | |
357 | }, | |
a1dfa0c6 | 358 | |
f035d41b | 359 | sym::nontemporal_store => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()), |
ff7c6d11 | 360 | |
f035d41b | 361 | other => { |
1b1a35ee | 362 | tcx.sess.emit_err(UnrecognizedIntrinsicFunction { span: it.span, name: other }); |
e9174d1e SL |
363 | return; |
364 | } | |
365 | }; | |
b7449926 | 366 | (n_tps, inputs, output, unsafety) |
e9174d1e | 367 | }; |
fc512014 XL |
368 | let sig = tcx.mk_fn_sig(inputs.into_iter(), output, false, unsafety, Abi::RustIntrinsic); |
369 | let sig = ty::Binder::bind(sig); | |
6a06907d | 370 | equate_intrinsic_type(tcx, it, n_tps, sig) |
e9174d1e SL |
371 | } |
372 | ||
373 | /// Type-check `extern "platform-intrinsic" { ... }` functions. | |
dfeec247 | 374 | pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { |
e9174d1e | 375 | let param = |n| { |
e74abb32 | 376 | let name = Symbol::intern(&format!("P{}", n)); |
94b46f34 | 377 | tcx.mk_ty_param(n, name) |
e9174d1e SL |
378 | }; |
379 | ||
3dfed10e | 380 | let name = it.ident.name; |
e9174d1e | 381 | |
3dfed10e XL |
382 | let (n_tps, inputs, output) = match name { |
383 | sym::simd_eq | sym::simd_ne | sym::simd_lt | sym::simd_le | sym::simd_gt | sym::simd_ge => { | |
e9174d1e SL |
384 | (2, vec![param(0), param(0)], param(1)) |
385 | } | |
3dfed10e XL |
386 | sym::simd_add |
387 | | sym::simd_sub | |
388 | | sym::simd_mul | |
389 | | sym::simd_rem | |
390 | | sym::simd_div | |
391 | | sym::simd_shl | |
392 | | sym::simd_shr | |
393 | | sym::simd_and | |
394 | | sym::simd_or | |
395 | | sym::simd_xor | |
396 | | sym::simd_fmin | |
397 | | sym::simd_fmax | |
398 | | sym::simd_fpow | |
399 | | sym::simd_saturating_add | |
400 | | sym::simd_saturating_sub => (1, vec![param(0), param(0)], param(0)), | |
6a06907d | 401 | sym::simd_neg => (1, vec![param(0)], param(0)), |
3dfed10e XL |
402 | sym::simd_fsqrt |
403 | | sym::simd_fsin | |
404 | | sym::simd_fcos | |
405 | | sym::simd_fexp | |
406 | | sym::simd_fexp2 | |
407 | | sym::simd_flog2 | |
408 | | sym::simd_flog10 | |
409 | | sym::simd_flog | |
410 | | sym::simd_fabs | |
411 | | sym::simd_floor | |
412 | | sym::simd_ceil => (1, vec![param(0)], param(0)), | |
413 | sym::simd_fpowi => (1, vec![param(0), tcx.types.i32], param(0)), | |
414 | sym::simd_fma => (1, vec![param(0), param(0), param(0)], param(0)), | |
415 | sym::simd_gather => (3, vec![param(0), param(1), param(2)], param(0)), | |
416 | sym::simd_scatter => (3, vec![param(0), param(1), param(2)], tcx.mk_unit()), | |
417 | sym::simd_insert => (2, vec![param(0), tcx.types.u32, param(1)], param(0)), | |
418 | sym::simd_extract => (2, vec![param(0), tcx.types.u32], param(1)), | |
419 | sym::simd_cast => (2, vec![param(0)], param(1)), | |
420 | sym::simd_bitmask => (2, vec![param(0)], param(1)), | |
421 | sym::simd_select | sym::simd_select_bitmask => { | |
422 | (2, vec![param(0), param(1), param(1)], param(1)) | |
94b46f34 | 423 | } |
3dfed10e XL |
424 | sym::simd_reduce_all | sym::simd_reduce_any => (1, vec![param(0)], tcx.types.bool), |
425 | sym::simd_reduce_add_ordered | sym::simd_reduce_mul_ordered => { | |
dfeec247 | 426 | (2, vec![param(0), param(1)], param(1)) |
e9174d1e | 427 | } |
3dfed10e XL |
428 | sym::simd_reduce_add_unordered |
429 | | sym::simd_reduce_mul_unordered | |
430 | | sym::simd_reduce_and | |
431 | | sym::simd_reduce_or | |
432 | | sym::simd_reduce_xor | |
433 | | sym::simd_reduce_min | |
434 | | sym::simd_reduce_max | |
435 | | sym::simd_reduce_min_nanless | |
436 | | sym::simd_reduce_max_nanless => (2, vec![param(0)], param(1)), | |
437 | name if name.as_str().starts_with("simd_shuffle") => { | |
438 | match name.as_str()["simd_shuffle".len()..].parse() { | |
439 | Ok(n) => { | |
440 | let params = vec![param(0), param(0), tcx.mk_array(tcx.types.u32, n)]; | |
441 | (2, params, param(1)) | |
442 | } | |
443 | Err(_) => { | |
1b1a35ee | 444 | tcx.sess.emit_err(SimdShuffleMissingLength { span: it.span, name }); |
3dfed10e XL |
445 | return; |
446 | } | |
dfeec247 | 447 | } |
3dfed10e | 448 | } |
e9174d1e | 449 | _ => { |
0731742a | 450 | let msg = format!("unrecognized platform-specific intrinsic function: `{}`", name); |
dfeec247 | 451 | tcx.sess.struct_span_err(it.span, &msg).emit(); |
0731742a | 452 | return; |
e9174d1e SL |
453 | } |
454 | }; | |
455 | ||
fc512014 XL |
456 | let sig = tcx.mk_fn_sig( |
457 | inputs.into_iter(), | |
dfeec247 | 458 | output, |
fc512014 XL |
459 | false, |
460 | hir::Unsafety::Unsafe, | |
461 | Abi::PlatformIntrinsic, | |
462 | ); | |
463 | let sig = ty::Binder::dummy(sig); | |
6a06907d | 464 | equate_intrinsic_type(tcx, it, n_tps, sig) |
e9174d1e | 465 | } |