]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_typeck/src/check/intrinsic.rs
Merge tag 'debian/1.52.1+dfsg1-1_exp2' into proxmox/buster
[rustc.git] / compiler / rustc_typeck / src / check / intrinsic.rs
CommitLineData
e9174d1e
SL
1//! Type-checking for the rust-intrinsic and platform-intrinsic
2//! intrinsics that the compiler exposes.
3
1b1a35ee
XL
4use crate::errors::{
5 SimdShuffleMissingLength, UnrecognizedAtomicOperation, UnrecognizedIntrinsicFunction,
6 WrongNumberOfTypeArgumentsToInstrinsic,
7};
9fa01778 8use crate::require_same_types;
e9174d1e 9
dfeec247
XL
10use rustc_errors::struct_span_err;
11use rustc_hir as hir;
ba9703b0
XL
12use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
13use rustc_middle::ty::subst::Subst;
fc512014 14use rustc_middle::ty::{self, TyCtxt};
f035d41b 15use rustc_span::symbol::{kw, sym, Symbol};
83c7162d 16use rustc_target::spec::abi::Abi;
60c5eb7d 17
476ff2be
SL
18use std::iter;
19
dc9dc135
XL
20fn 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 57pub 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 99pub 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 374pub 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}