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