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