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