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