1use rustc_abi::ExternAbi;
4use rustc_errors::DiagMessage;
5use rustc_hir::{self as hir, LangItem};
6use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
7use rustc_middle::ty::{self, Ty, TyCtxt};
8use rustc_span::def_id::LocalDefId;
9use rustc_span::{Span, Symbol, sym};
10
11use crate::check::check_function_signature;
12use crate::errors::{
13 UnrecognizedAtomicOperation, UnrecognizedIntrinsicFunction,
14 WrongNumberOfGenericArgumentsToIntrinsic,
15};
16
17fn equate_intrinsic_type<'tcx>(
18 tcx: TyCtxt<'tcx>,
19 span: Span,
20 def_id: LocalDefId,
21 n_tps: usize,
22 n_lts: usize,
23 n_cts: usize,
24 sig: ty::PolyFnSig<'tcx>,
25) {
26 let (generics, span) = match tcx.hir_node_by_def_id(def_id) {
27 hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn { generics, .. }, .. }) => {
28 (tcx.generics_of(def_id), generics.span)
29 }
30 _ => tcx.dcx().span_bug(span, "intrinsic must be a function"),
31 };
32 let own_counts = generics.own_counts();
33
34 let gen_count_ok = |found: usize, expected: usize, descr: &str| -> bool {
35 if found != expected {
36 tcx.dcx().emit_err(WrongNumberOfGenericArgumentsToIntrinsic {
37 span,
38 found,
39 expected,
40 descr,
41 });
42 false
43 } else {
44 true
45 }
46 };
47
48 if gen_count_ok(own_counts.lifetimes, n_lts, "lifetime")
51 && gen_count_ok(own_counts.types, n_tps, "type")
52 && gen_count_ok(own_counts.consts, n_cts, "const")
53 {
54 let _ = check_function_signature(
55 tcx,
56 ObligationCause::new(span, def_id, ObligationCauseCode::IntrinsicType),
57 def_id.into(),
58 sig,
59 );
60 }
61}
62
63fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hir::Safety {
65 let is_in_list = match tcx.item_name(intrinsic_id.into()) {
66 sym::abort
71 | sym::assert_inhabited
72 | sym::assert_zero_valid
73 | sym::assert_mem_uninitialized_valid
74 | sym::box_new
75 | sym::breakpoint
76 | sym::size_of
77 | sym::min_align_of
78 | sym::needs_drop
79 | sym::caller_location
80 | sym::add_with_overflow
81 | sym::sub_with_overflow
82 | sym::mul_with_overflow
83 | sym::carrying_mul_add
84 | sym::wrapping_add
85 | sym::wrapping_sub
86 | sym::wrapping_mul
87 | sym::saturating_add
88 | sym::saturating_sub
89 | sym::rotate_left
90 | sym::rotate_right
91 | sym::ctpop
92 | sym::ctlz
93 | sym::cttz
94 | sym::bswap
95 | sym::bitreverse
96 | sym::three_way_compare
97 | sym::discriminant_value
98 | sym::type_id
99 | sym::select_unpredictable
100 | sym::cold_path
101 | sym::ptr_guaranteed_cmp
102 | sym::minnumf16
103 | sym::minnumf32
104 | sym::minnumf64
105 | sym::minnumf128
106 | sym::maxnumf16
107 | sym::maxnumf32
108 | sym::maxnumf64
109 | sym::maxnumf128
110 | sym::rustc_peek
111 | sym::type_name
112 | sym::forget
113 | sym::black_box
114 | sym::variant_count
115 | sym::is_val_statically_known
116 | sym::ptr_mask
117 | sym::aggregate_raw_ptr
118 | sym::ptr_metadata
119 | sym::ub_checks
120 | sym::contract_checks
121 | sym::contract_check_requires
122 | sym::contract_check_ensures
123 | sym::fadd_algebraic
124 | sym::fsub_algebraic
125 | sym::fmul_algebraic
126 | sym::fdiv_algebraic
127 | sym::frem_algebraic
128 | sym::round_ties_even_f16
129 | sym::round_ties_even_f32
130 | sym::round_ties_even_f64
131 | sym::round_ties_even_f128
132 | sym::const_eval_select => hir::Safety::Safe,
133 _ => hir::Safety::Unsafe,
134 };
135
136 if tcx.fn_sig(intrinsic_id).skip_binder().safety() != is_in_list {
137 tcx.dcx().struct_span_err(
138 tcx.def_span(intrinsic_id),
139 DiagMessage::from(format!(
140 "intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `{}`",
141 tcx.item_name(intrinsic_id.into())
142 )
143 )).emit();
144 }
145
146 is_in_list
147}
148
149pub(crate) fn check_intrinsic_type(
152 tcx: TyCtxt<'_>,
153 intrinsic_id: LocalDefId,
154 span: Span,
155 intrinsic_name: Symbol,
156) {
157 let generics = tcx.generics_of(intrinsic_id);
158 let param = |n| {
159 if let &ty::GenericParamDef { name, kind: ty::GenericParamDefKind::Type { .. }, .. } =
160 generics.param_at(n as usize, tcx)
161 {
162 Ty::new_param(tcx, n, name)
163 } else {
164 Ty::new_error_with_message(tcx, span, "expected param")
165 }
166 };
167 let name_str = intrinsic_name.as_str();
168
169 let bound_vars = tcx.mk_bound_variable_kinds(&[
170 ty::BoundVariableKind::Region(ty::BoundRegionKind::Anon),
171 ty::BoundVariableKind::Region(ty::BoundRegionKind::Anon),
172 ty::BoundVariableKind::Region(ty::BoundRegionKind::ClosureEnv),
173 ]);
174 let mk_va_list_ty = |mutbl| {
175 let did = tcx.require_lang_item(LangItem::VaList, Some(span));
176 let region = ty::Region::new_bound(
177 tcx,
178 ty::INNERMOST,
179 ty::BoundRegion { var: ty::BoundVar::ZERO, kind: ty::BoundRegionKind::Anon },
180 );
181 let env_region = ty::Region::new_bound(
182 tcx,
183 ty::INNERMOST,
184 ty::BoundRegion {
185 var: ty::BoundVar::from_u32(2),
186 kind: ty::BoundRegionKind::ClosureEnv,
187 },
188 );
189 let va_list_ty = tcx.type_of(did).instantiate(tcx, &[region.into()]);
190 (Ty::new_ref(tcx, env_region, va_list_ty, mutbl), va_list_ty)
191 };
192
193 let (n_tps, n_lts, n_cts, inputs, output, safety) = if name_str.starts_with("atomic_") {
194 let split: Vec<&str> = name_str.split('_').collect();
195 assert!(split.len() >= 2, "Atomic intrinsic in an incorrect format");
196
197 let (n_tps, inputs, output) = match split[1] {
200 "cxchg" | "cxchgweak" => (
201 1,
202 vec![Ty::new_mut_ptr(tcx, param(0)), param(0), param(0)],
203 Ty::new_tup(tcx, &[param(0), tcx.types.bool]),
204 ),
205 "load" => (1, vec![Ty::new_imm_ptr(tcx, param(0))], param(0)),
206 "store" => (1, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], tcx.types.unit),
207
208 "xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" | "min" | "umax"
209 | "umin" => (1, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], param(0)),
210 "fence" | "singlethreadfence" => (0, Vec::new(), tcx.types.unit),
211 op => {
212 tcx.dcx().emit_err(UnrecognizedAtomicOperation { span, op });
213 return;
214 }
215 };
216 (n_tps, 0, 0, inputs, output, hir::Safety::Unsafe)
217 } else if intrinsic_name == sym::contract_check_ensures {
218 (2, 0, 0, vec![param(0), param(1)], param(1), hir::Safety::Safe)
223 } else {
224 let safety = intrinsic_operation_unsafety(tcx, intrinsic_id);
225 let (n_tps, n_cts, inputs, output) = match intrinsic_name {
226 sym::abort => (0, 0, vec![], tcx.types.never),
227 sym::unreachable => (0, 0, vec![], tcx.types.never),
228 sym::breakpoint => (0, 0, vec![], tcx.types.unit),
229 sym::size_of | sym::pref_align_of | sym::min_align_of | sym::variant_count => {
230 (1, 0, vec![], tcx.types.usize)
231 }
232 sym::size_of_val | sym::min_align_of_val => {
233 (1, 0, vec![Ty::new_imm_ptr(tcx, param(0))], tcx.types.usize)
234 }
235 sym::rustc_peek => (1, 0, vec![param(0)], param(0)),
236 sym::caller_location => (0, 0, vec![], tcx.caller_location_ty()),
237 sym::assert_inhabited
238 | sym::assert_zero_valid
239 | sym::assert_mem_uninitialized_valid => (1, 0, vec![], tcx.types.unit),
240 sym::forget => (1, 0, vec![param(0)], tcx.types.unit),
241 sym::transmute | sym::transmute_unchecked => (2, 0, vec![param(0)], param(1)),
242 sym::prefetch_read_data
243 | sym::prefetch_write_data
244 | sym::prefetch_read_instruction
245 | sym::prefetch_write_instruction => {
246 (1, 0, vec![Ty::new_imm_ptr(tcx, param(0)), tcx.types.i32], tcx.types.unit)
247 }
248 sym::needs_drop => (1, 0, vec![], tcx.types.bool),
249
250 sym::type_name => (1, 0, vec![], Ty::new_static_str(tcx)),
251 sym::type_id => (1, 0, vec![], tcx.types.u128),
252 sym::offset => (2, 0, vec![param(0), param(1)], param(0)),
253 sym::arith_offset => (
254 1,
255 0,
256 vec![Ty::new_imm_ptr(tcx, param(0)), tcx.types.isize],
257 Ty::new_imm_ptr(tcx, param(0)),
258 ),
259 sym::ptr_mask => (
260 1,
261 0,
262 vec![Ty::new_imm_ptr(tcx, param(0)), tcx.types.usize],
263 Ty::new_imm_ptr(tcx, param(0)),
264 ),
265
266 sym::copy | sym::copy_nonoverlapping => (
267 1,
268 0,
269 vec![
270 Ty::new_imm_ptr(tcx, param(0)),
271 Ty::new_mut_ptr(tcx, param(0)),
272 tcx.types.usize,
273 ],
274 tcx.types.unit,
275 ),
276 sym::volatile_copy_memory | sym::volatile_copy_nonoverlapping_memory => (
277 1,
278 0,
279 vec![
280 Ty::new_mut_ptr(tcx, param(0)),
281 Ty::new_imm_ptr(tcx, param(0)),
282 tcx.types.usize,
283 ],
284 tcx.types.unit,
285 ),
286 sym::compare_bytes => {
287 let byte_ptr = Ty::new_imm_ptr(tcx, tcx.types.u8);
288 (0, 0, vec![byte_ptr, byte_ptr, tcx.types.usize], tcx.types.i32)
289 }
290 sym::write_bytes | sym::volatile_set_memory => (
291 1,
292 0,
293 vec![Ty::new_mut_ptr(tcx, param(0)), tcx.types.u8, tcx.types.usize],
294 tcx.types.unit,
295 ),
296
297 sym::sqrtf16 => (0, 0, vec![tcx.types.f16], tcx.types.f16),
298 sym::sqrtf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
299 sym::sqrtf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
300 sym::sqrtf128 => (0, 0, vec![tcx.types.f128], tcx.types.f128),
301
302 sym::powif16 => (0, 0, vec![tcx.types.f16, tcx.types.i32], tcx.types.f16),
303 sym::powif32 => (0, 0, vec![tcx.types.f32, tcx.types.i32], tcx.types.f32),
304 sym::powif64 => (0, 0, vec![tcx.types.f64, tcx.types.i32], tcx.types.f64),
305 sym::powif128 => (0, 0, vec![tcx.types.f128, tcx.types.i32], tcx.types.f128),
306
307 sym::sinf16 => (0, 0, vec![tcx.types.f16], tcx.types.f16),
308 sym::sinf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
309 sym::sinf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
310 sym::sinf128 => (0, 0, vec![tcx.types.f128], tcx.types.f128),
311
312 sym::cosf16 => (0, 0, vec![tcx.types.f16], tcx.types.f16),
313 sym::cosf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
314 sym::cosf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
315 sym::cosf128 => (0, 0, vec![tcx.types.f128], tcx.types.f128),
316
317 sym::powf16 => (0, 0, vec![tcx.types.f16, tcx.types.f16], tcx.types.f16),
318 sym::powf32 => (0, 0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
319 sym::powf64 => (0, 0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
320 sym::powf128 => (0, 0, vec![tcx.types.f128, tcx.types.f128], tcx.types.f128),
321
322 sym::expf16 => (0, 0, vec![tcx.types.f16], tcx.types.f16),
323 sym::expf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
324 sym::expf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
325 sym::expf128 => (0, 0, vec![tcx.types.f128], tcx.types.f128),
326
327 sym::exp2f16 => (0, 0, vec![tcx.types.f16], tcx.types.f16),
328 sym::exp2f32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
329 sym::exp2f64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
330 sym::exp2f128 => (0, 0, vec![tcx.types.f128], tcx.types.f128),
331
332 sym::logf16 => (0, 0, vec![tcx.types.f16], tcx.types.f16),
333 sym::logf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
334 sym::logf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
335 sym::logf128 => (0, 0, vec![tcx.types.f128], tcx.types.f128),
336
337 sym::log10f16 => (0, 0, vec![tcx.types.f16], tcx.types.f16),
338 sym::log10f32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
339 sym::log10f64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
340 sym::log10f128 => (0, 0, vec![tcx.types.f128], tcx.types.f128),
341
342 sym::log2f16 => (0, 0, vec![tcx.types.f16], tcx.types.f16),
343 sym::log2f32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
344 sym::log2f64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
345 sym::log2f128 => (0, 0, vec![tcx.types.f128], tcx.types.f128),
346
347 sym::fmaf16 => (0, 0, vec![tcx.types.f16, tcx.types.f16, tcx.types.f16], tcx.types.f16),
348 sym::fmaf32 => (0, 0, vec![tcx.types.f32, tcx.types.f32, tcx.types.f32], tcx.types.f32),
349 sym::fmaf64 => (0, 0, vec![tcx.types.f64, tcx.types.f64, tcx.types.f64], tcx.types.f64),
350 sym::fmaf128 => {
351 (0, 0, vec![tcx.types.f128, tcx.types.f128, tcx.types.f128], tcx.types.f128)
352 }
353
354 sym::fmuladdf16 => {
355 (0, 0, vec![tcx.types.f16, tcx.types.f16, tcx.types.f16], tcx.types.f16)
356 }
357 sym::fmuladdf32 => {
358 (0, 0, vec![tcx.types.f32, tcx.types.f32, tcx.types.f32], tcx.types.f32)
359 }
360 sym::fmuladdf64 => {
361 (0, 0, vec![tcx.types.f64, tcx.types.f64, tcx.types.f64], tcx.types.f64)
362 }
363 sym::fmuladdf128 => {
364 (0, 0, vec![tcx.types.f128, tcx.types.f128, tcx.types.f128], tcx.types.f128)
365 }
366
367 sym::fabsf16 => (0, 0, vec![tcx.types.f16], tcx.types.f16),
368 sym::fabsf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
369 sym::fabsf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
370 sym::fabsf128 => (0, 0, vec![tcx.types.f128], tcx.types.f128),
371
372 sym::minnumf16 => (0, 0, vec![tcx.types.f16, tcx.types.f16], tcx.types.f16),
373 sym::minnumf32 => (0, 0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
374 sym::minnumf64 => (0, 0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
375 sym::minnumf128 => (0, 0, vec![tcx.types.f128, tcx.types.f128], tcx.types.f128),
376
377 sym::maxnumf16 => (0, 0, vec![tcx.types.f16, tcx.types.f16], tcx.types.f16),
378 sym::maxnumf32 => (0, 0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
379 sym::maxnumf64 => (0, 0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
380 sym::maxnumf128 => (0, 0, vec![tcx.types.f128, tcx.types.f128], tcx.types.f128),
381
382 sym::copysignf16 => (0, 0, vec![tcx.types.f16, tcx.types.f16], tcx.types.f16),
383 sym::copysignf32 => (0, 0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
384 sym::copysignf64 => (0, 0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
385 sym::copysignf128 => (0, 0, vec![tcx.types.f128, tcx.types.f128], tcx.types.f128),
386
387 sym::floorf16 => (0, 0, vec![tcx.types.f16], tcx.types.f16),
388 sym::floorf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
389 sym::floorf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
390 sym::floorf128 => (0, 0, vec![tcx.types.f128], tcx.types.f128),
391
392 sym::ceilf16 => (0, 0, vec![tcx.types.f16], tcx.types.f16),
393 sym::ceilf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
394 sym::ceilf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
395 sym::ceilf128 => (0, 0, vec![tcx.types.f128], tcx.types.f128),
396
397 sym::truncf16 => (0, 0, vec![tcx.types.f16], tcx.types.f16),
398 sym::truncf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
399 sym::truncf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
400 sym::truncf128 => (0, 0, vec![tcx.types.f128], tcx.types.f128),
401
402 sym::round_ties_even_f16 => (0, 0, vec![tcx.types.f16], tcx.types.f16),
403 sym::round_ties_even_f32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
404 sym::round_ties_even_f64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
405 sym::round_ties_even_f128 => (0, 0, vec![tcx.types.f128], tcx.types.f128),
406
407 sym::roundf16 => (0, 0, vec![tcx.types.f16], tcx.types.f16),
408 sym::roundf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
409 sym::roundf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
410 sym::roundf128 => (0, 0, vec![tcx.types.f128], tcx.types.f128),
411
412 sym::volatile_load | sym::unaligned_volatile_load => {
413 (1, 0, vec![Ty::new_imm_ptr(tcx, param(0))], param(0))
414 }
415 sym::volatile_store | sym::unaligned_volatile_store => {
416 (1, 0, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], tcx.types.unit)
417 }
418
419 sym::ctpop | sym::ctlz | sym::ctlz_nonzero | sym::cttz | sym::cttz_nonzero => {
420 (1, 0, vec![param(0)], tcx.types.u32)
421 }
422
423 sym::bswap | sym::bitreverse => (1, 0, vec![param(0)], param(0)),
424
425 sym::three_way_compare => {
426 (1, 0, vec![param(0), param(0)], tcx.ty_ordering_enum(Some(span)))
427 }
428
429 sym::add_with_overflow | sym::sub_with_overflow | sym::mul_with_overflow => {
430 (1, 0, vec![param(0), param(0)], Ty::new_tup(tcx, &[param(0), tcx.types.bool]))
431 }
432
433 sym::carrying_mul_add => {
434 (2, 0, vec![param(0); 4], Ty::new_tup(tcx, &[param(1), param(0)]))
435 }
436
437 sym::ptr_guaranteed_cmp => (
438 1,
439 0,
440 vec![Ty::new_imm_ptr(tcx, param(0)), Ty::new_imm_ptr(tcx, param(0))],
441 tcx.types.u8,
442 ),
443
444 sym::const_allocate => {
445 (0, 0, vec![tcx.types.usize, tcx.types.usize], Ty::new_mut_ptr(tcx, tcx.types.u8))
446 }
447 sym::const_deallocate => (
448 0,
449 0,
450 vec![Ty::new_mut_ptr(tcx, tcx.types.u8), tcx.types.usize, tcx.types.usize],
451 tcx.types.unit,
452 ),
453
454 sym::ptr_offset_from => (
455 1,
456 0,
457 vec![Ty::new_imm_ptr(tcx, param(0)), Ty::new_imm_ptr(tcx, param(0))],
458 tcx.types.isize,
459 ),
460 sym::ptr_offset_from_unsigned => (
461 1,
462 0,
463 vec![Ty::new_imm_ptr(tcx, param(0)), Ty::new_imm_ptr(tcx, param(0))],
464 tcx.types.usize,
465 ),
466 sym::unchecked_div | sym::unchecked_rem | sym::exact_div | sym::disjoint_bitor => {
467 (1, 0, vec![param(0), param(0)], param(0))
468 }
469 sym::unchecked_shl | sym::unchecked_shr => (2, 0, vec![param(0), param(1)], param(0)),
470 sym::rotate_left | sym::rotate_right => (1, 0, vec![param(0), tcx.types.u32], param(0)),
471 sym::unchecked_add | sym::unchecked_sub | sym::unchecked_mul => {
472 (1, 0, vec![param(0), param(0)], param(0))
473 }
474 sym::wrapping_add | sym::wrapping_sub | sym::wrapping_mul => {
475 (1, 0, vec![param(0), param(0)], param(0))
476 }
477 sym::saturating_add | sym::saturating_sub => (1, 0, vec![param(0), param(0)], param(0)),
478 sym::fadd_fast | sym::fsub_fast | sym::fmul_fast | sym::fdiv_fast | sym::frem_fast => {
479 (1, 0, vec![param(0), param(0)], param(0))
480 }
481 sym::fadd_algebraic
482 | sym::fsub_algebraic
483 | sym::fmul_algebraic
484 | sym::fdiv_algebraic
485 | sym::frem_algebraic => (1, 0, vec![param(0), param(0)], param(0)),
486 sym::float_to_int_unchecked => (2, 0, vec![param(0)], param(1)),
487
488 sym::assume => (0, 0, vec![tcx.types.bool], tcx.types.unit),
489 sym::select_unpredictable => (1, 0, vec![tcx.types.bool, param(0), param(0)], param(0)),
490 sym::cold_path => (0, 0, vec![], tcx.types.unit),
491
492 sym::read_via_copy => (1, 0, vec![Ty::new_imm_ptr(tcx, param(0))], param(0)),
493 sym::write_via_move => {
494 (1, 0, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], tcx.types.unit)
495 }
496
497 sym::typed_swap_nonoverlapping => {
498 (1, 0, vec![Ty::new_mut_ptr(tcx, param(0)); 2], tcx.types.unit)
499 }
500
501 sym::discriminant_value => {
502 let assoc_items = tcx.associated_item_def_ids(
503 tcx.require_lang_item(hir::LangItem::DiscriminantKind, None),
504 );
505 let discriminant_def_id = assoc_items[0];
506
507 let br =
508 ty::BoundRegion { var: ty::BoundVar::ZERO, kind: ty::BoundRegionKind::Anon };
509 (
510 1,
511 0,
512 vec![Ty::new_imm_ref(
513 tcx,
514 ty::Region::new_bound(tcx, ty::INNERMOST, br),
515 param(0),
516 )],
517 Ty::new_projection_from_args(
518 tcx,
519 discriminant_def_id,
520 tcx.mk_args(&[param(0).into()]),
521 ),
522 )
523 }
524
525 sym::catch_unwind => {
526 let mut_u8 = Ty::new_mut_ptr(tcx, tcx.types.u8);
527 let try_fn_ty = ty::Binder::dummy(tcx.mk_fn_sig(
528 [mut_u8],
529 tcx.types.unit,
530 false,
531 hir::Safety::Safe,
532 ExternAbi::Rust,
533 ));
534 let catch_fn_ty = ty::Binder::dummy(tcx.mk_fn_sig(
535 [mut_u8, mut_u8],
536 tcx.types.unit,
537 false,
538 hir::Safety::Safe,
539 ExternAbi::Rust,
540 ));
541 (
542 0,
543 0,
544 vec![Ty::new_fn_ptr(tcx, try_fn_ty), mut_u8, Ty::new_fn_ptr(tcx, catch_fn_ty)],
545 tcx.types.i32,
546 )
547 }
548
549 sym::va_start | sym::va_end => {
550 (0, 0, vec![mk_va_list_ty(hir::Mutability::Mut).0], tcx.types.unit)
551 }
552
553 sym::va_copy => {
554 let (va_list_ref_ty, va_list_ty) = mk_va_list_ty(hir::Mutability::Not);
555 let va_list_ptr_ty = Ty::new_mut_ptr(tcx, va_list_ty);
556 (0, 0, vec![va_list_ptr_ty, va_list_ref_ty], tcx.types.unit)
557 }
558
559 sym::va_arg => (1, 0, vec![mk_va_list_ty(hir::Mutability::Mut).0], param(0)),
560
561 sym::nontemporal_store => {
562 (1, 0, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], tcx.types.unit)
563 }
564
565 sym::raw_eq => {
566 let br =
567 ty::BoundRegion { var: ty::BoundVar::ZERO, kind: ty::BoundRegionKind::Anon };
568 let param_ty_lhs =
569 Ty::new_imm_ref(tcx, ty::Region::new_bound(tcx, ty::INNERMOST, br), param(0));
570 let br = ty::BoundRegion {
571 var: ty::BoundVar::from_u32(1),
572 kind: ty::BoundRegionKind::Anon,
573 };
574 let param_ty_rhs =
575 Ty::new_imm_ref(tcx, ty::Region::new_bound(tcx, ty::INNERMOST, br), param(0));
576 (1, 0, vec![param_ty_lhs, param_ty_rhs], tcx.types.bool)
577 }
578
579 sym::black_box => (1, 0, vec![param(0)], param(0)),
580
581 sym::is_val_statically_known => (1, 0, vec![param(0)], tcx.types.bool),
582
583 sym::const_eval_select => (4, 0, vec![param(0), param(1), param(2)], param(3)),
584
585 sym::vtable_size | sym::vtable_align => {
586 (0, 0, vec![Ty::new_imm_ptr(tcx, tcx.types.unit)], tcx.types.usize)
587 }
588
589 sym::aggregate_raw_ptr => (3, 0, vec![param(1), param(2)], param(0)),
592 sym::ptr_metadata => (2, 0, vec![Ty::new_imm_ptr(tcx, param(0))], param(1)),
593
594 sym::ub_checks => (0, 0, Vec::new(), tcx.types.bool),
595
596 sym::box_new => (1, 0, vec![param(0)], Ty::new_box(tcx, param(0))),
597
598 sym::contract_checks => (0, 0, Vec::new(), tcx.types.bool),
600 sym::contract_check_requires => (1, 0, vec![param(0)], tcx.types.unit),
602
603 sym::simd_eq
604 | sym::simd_ne
605 | sym::simd_lt
606 | sym::simd_le
607 | sym::simd_gt
608 | sym::simd_ge => (2, 0, vec![param(0), param(0)], param(1)),
609 sym::simd_add
610 | sym::simd_sub
611 | sym::simd_mul
612 | sym::simd_rem
613 | sym::simd_div
614 | sym::simd_shl
615 | sym::simd_shr
616 | sym::simd_and
617 | sym::simd_or
618 | sym::simd_xor
619 | sym::simd_fmin
620 | sym::simd_fmax
621 | sym::simd_saturating_add
622 | sym::simd_saturating_sub => (1, 0, vec![param(0), param(0)], param(0)),
623 sym::simd_arith_offset => (2, 0, vec![param(0), param(1)], param(0)),
624 sym::simd_neg
625 | sym::simd_bswap
626 | sym::simd_bitreverse
627 | sym::simd_ctlz
628 | sym::simd_cttz
629 | sym::simd_ctpop
630 | sym::simd_fsqrt
631 | sym::simd_fsin
632 | sym::simd_fcos
633 | sym::simd_fexp
634 | sym::simd_fexp2
635 | sym::simd_flog2
636 | sym::simd_flog10
637 | sym::simd_flog
638 | sym::simd_fabs
639 | sym::simd_ceil
640 | sym::simd_floor
641 | sym::simd_round
642 | sym::simd_trunc => (1, 0, vec![param(0)], param(0)),
643 sym::simd_fma | sym::simd_relaxed_fma => {
644 (1, 0, vec![param(0), param(0), param(0)], param(0))
645 }
646 sym::simd_gather => (3, 0, vec![param(0), param(1), param(2)], param(0)),
647 sym::simd_masked_load => (3, 0, vec![param(0), param(1), param(2)], param(2)),
648 sym::simd_masked_store => (3, 0, vec![param(0), param(1), param(2)], tcx.types.unit),
649 sym::simd_scatter => (3, 0, vec![param(0), param(1), param(2)], tcx.types.unit),
650 sym::simd_insert | sym::simd_insert_dyn => {
651 (2, 0, vec![param(0), tcx.types.u32, param(1)], param(0))
652 }
653 sym::simd_extract | sym::simd_extract_dyn => {
654 (2, 0, vec![param(0), tcx.types.u32], param(1))
655 }
656 sym::simd_cast
657 | sym::simd_as
658 | sym::simd_cast_ptr
659 | sym::simd_expose_provenance
660 | sym::simd_with_exposed_provenance => (2, 0, vec![param(0)], param(1)),
661 sym::simd_bitmask => (2, 0, vec![param(0)], param(1)),
662 sym::simd_select | sym::simd_select_bitmask => {
663 (2, 0, vec![param(0), param(1), param(1)], param(1))
664 }
665 sym::simd_reduce_all | sym::simd_reduce_any => (1, 0, vec![param(0)], tcx.types.bool),
666 sym::simd_reduce_add_ordered | sym::simd_reduce_mul_ordered => {
667 (2, 0, vec![param(0), param(1)], param(1))
668 }
669 sym::simd_reduce_add_unordered
670 | sym::simd_reduce_mul_unordered
671 | sym::simd_reduce_and
672 | sym::simd_reduce_or
673 | sym::simd_reduce_xor
674 | sym::simd_reduce_min
675 | sym::simd_reduce_max => (2, 0, vec![param(0)], param(1)),
676 sym::simd_shuffle => (3, 0, vec![param(0), param(0), param(1)], param(2)),
677 sym::simd_shuffle_const_generic => (2, 1, vec![param(0), param(0)], param(1)),
678
679 other => {
680 tcx.dcx().emit_err(UnrecognizedIntrinsicFunction { span, name: other });
681 return;
682 }
683 };
684 (n_tps, 0, n_cts, inputs, output, safety)
685 };
686 let sig = tcx.mk_fn_sig(inputs, output, false, safety, ExternAbi::Rust);
687 let sig = ty::Binder::bind_with_vars(sig, bound_vars);
688 equate_intrinsic_type(tcx, span, intrinsic_id, n_tps, n_lts, n_cts, sig)
689}