intrinsic.rs 20.2 KB
Newer Older
1 2 3
//! Type-checking for the rust-intrinsic and platform-intrinsic
//! intrinsics that the compiler exposes.

M
Mark Rousskov 已提交
4
use crate::require_same_types;
5

6 7
use rustc_errors::struct_span_err;
use rustc_hir as hir;
8
use rustc_hir::def_id::DefId;
M
Mazdak Farrokhzad 已提交
9 10 11
use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
use rustc_middle::ty::subst::Subst;
use rustc_middle::ty::{self, Ty, TyCtxt};
12
use rustc_span::symbol::{kw, sym, Symbol};
13
use rustc_target::spec::abi::Abi;
14

15 16
use std::iter;

17
fn equate_intrinsic_type<'tcx>(
18
    tcx: TyCtxt<'tcx>,
19
    it: &hir::ForeignItem<'_>,
20
    def_id: DefId,
21 22 23 24 25 26
    n_tps: usize,
    abi: Abi,
    safety: hir::Unsafety,
    inputs: Vec<Ty<'tcx>>,
    output: Ty<'tcx>,
) {
27
    match it.kind {
C
csmoe 已提交
28
        hir::ForeignItemKind::Fn(..) => {}
29
        _ => {
M
Mark Rousskov 已提交
30
            struct_span_err!(tcx.sess, it.span, E0622, "intrinsic must be a function")
31 32 33 34 35
                .span_label(it.span, "expected a function")
                .emit();
            return;
        }
    }
36

V
varkor 已提交
37
    let i_n_tps = tcx.generics_of(def_id).own_counts().types;
38
    if i_n_tps != n_tps {
39
        let span = match it.kind {
C
csmoe 已提交
40
            hir::ForeignItemKind::Fn(_, _, ref generics) => generics.span,
M
Mark Rousskov 已提交
41
            _ => bug!(),
J
Johannes Löthberg 已提交
42 43
        };

M
Mark Rousskov 已提交
44 45 46 47 48
        struct_span_err!(
            tcx.sess,
            span,
            E0094,
            "intrinsic has wrong number of type \
49
                         parameters: found {}, expected {}",
M
Mark Rousskov 已提交
50 51 52 53 54
            i_n_tps,
            n_tps
        )
        .span_label(span, format!("expected {} type parameter", n_tps))
        .emit();
55
        return;
56
    }
57

58
    let fty = tcx.mk_fn_ptr(ty::Binder::bind(tcx.mk_fn_sig(
59 60 61
        inputs.into_iter(),
        output,
        false,
62
        safety,
M
Mark Rousskov 已提交
63
        abi,
64
    )));
L
ljedrz 已提交
65
    let cause = ObligationCause::new(it.span, it.hir_id, ObligationCauseCode::IntrinsicType);
66
    require_same_types(tcx, &cause, tcx.mk_fn_ptr(tcx.fn_sig(def_id)), fty);
67
}
68

A
Alexander Regueiro 已提交
69
/// Returns `true` if the given intrinsic is unsafe to call or not.
70
pub fn intrinsic_operation_unsafety(intrinsic: Symbol) -> hir::Unsafety {
M
Mazdak Farrokhzad 已提交
71
    match intrinsic {
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
        sym::abort
        | sym::size_of
        | sym::min_align_of
        | sym::needs_drop
        | sym::caller_location
        | sym::size_of_val
        | sym::min_align_of_val
        | sym::add_with_overflow
        | sym::sub_with_overflow
        | sym::mul_with_overflow
        | sym::wrapping_add
        | sym::wrapping_sub
        | sym::wrapping_mul
        | sym::saturating_add
        | sym::saturating_sub
        | sym::rotate_left
        | sym::rotate_right
        | sym::ctpop
        | sym::ctlz
        | sym::cttz
        | sym::bswap
        | sym::bitreverse
        | sym::discriminant_value
        | sym::type_id
        | sym::likely
        | sym::unlikely
        | sym::ptr_guaranteed_eq
        | sym::ptr_guaranteed_ne
        | sym::minnumf32
        | sym::minnumf64
        | sym::maxnumf32
        | sym::rustc_peek
        | sym::maxnumf64
        | sym::type_name
        | sym::variant_count => hir::Unsafety::Normal,
M
Mazdak Farrokhzad 已提交
107 108 109 110
        _ => hir::Unsafety::Unsafe,
    }
}

I
Irina Popa 已提交
111
/// Remember to add all intrinsics here, in librustc_codegen_llvm/intrinsic.rs,
112
/// and in libcore/intrinsics.rs
113
pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
114
    let param = |n| tcx.mk_ty_param(n, Symbol::intern(&format!("P{}", n)));
115 116 117
    let def_id = tcx.hir().local_def_id(it.hir_id).to_def_id();
    let intrinsic_name = tcx.item_name(def_id);
    let name_str = intrinsic_name.as_str();
118

119
    let mk_va_list_ty = |mutbl| {
120 121 122 123
        tcx.lang_items().va_list().map(|did| {
            let region = tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BrAnon(0)));
            let env_region = ty::ReLateBound(ty::INNERMOST, ty::BrEnv);
            let va_list_ty = tcx.type_of(did).subst(tcx, &[region.into()]);
M
Mark Rousskov 已提交
124 125 126 127
            (
                tcx.mk_ref(tcx.mk_region(env_region), ty::TypeAndMut { ty: va_list_ty, mutbl }),
                va_list_ty,
            )
128 129 130
        })
    };

131 132
    let (n_tps, inputs, output, unsafety) = if name_str.starts_with("atomic_") {
        let split: Vec<&str> = name_str.split('_').collect();
133
        assert!(split.len() >= 2, "Atomic intrinsic in an incorrect format");
134 135 136

        //We only care about the operation here
        let (n_tps, inputs, output) = match split[1] {
M
Mark Rousskov 已提交
137 138 139 140 141 142 143 144 145 146 147
            "cxchg" | "cxchgweak" => (
                1,
                vec![tcx.mk_mut_ptr(param(0)), param(0), param(0)],
                tcx.intern_tup(&[param(0), tcx.types.bool]),
            ),
            "load" => (1, vec![tcx.mk_imm_ptr(param(0))], param(0)),
            "store" => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()),

            "xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" | "min" | "umax"
            | "umin" => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], param(0)),
            "fence" | "singlethreadfence" => (0, Vec::new(), tcx.mk_unit()),
148
            op => {
M
Mark Rousskov 已提交
149 150 151 152 153 154 155 156 157
                struct_span_err!(
                    tcx.sess,
                    it.span,
                    E0092,
                    "unrecognized atomic operation function: `{}`",
                    op
                )
                .span_label(it.span, "unrecognized atomic operation")
                .emit();
158 159 160
                return;
            }
        };
161
        (n_tps, inputs, output, hir::Unsafety::Unsafe)
162
    } else {
163 164 165 166 167 168
        let unsafety = intrinsic_operation_unsafety(intrinsic_name);
        let (n_tps, inputs, output) = match intrinsic_name {
            sym::abort => (0, Vec::new(), tcx.types.never),
            sym::unreachable => (0, Vec::new(), tcx.types.never),
            sym::breakpoint => (0, Vec::new(), tcx.mk_unit()),
            sym::size_of | sym::pref_align_of | sym::min_align_of | sym::variant_count => {
N
Nathan Corbyn 已提交
169 170
                (1, Vec::new(), tcx.types.usize)
            }
171
            sym::size_of_val | sym::min_align_of_val => {
172 173
                (1, vec![tcx.mk_imm_ptr(param(0))], tcx.types.usize)
            }
174 175 176
            sym::rustc_peek => (1, vec![param(0)], param(0)),
            sym::caller_location => (0, vec![], tcx.caller_location_ty()),
            sym::assert_inhabited | sym::assert_zero_valid | sym::assert_uninit_valid => {
R
fmt  
Ralf Jung 已提交
177 178
                (1, Vec::new(), tcx.mk_unit())
            }
179 180 181 182 183 184 185
            sym::forget => (1, vec![param(0)], tcx.mk_unit()),
            sym::transmute => (2, vec![param(0)], param(1)),
            sym::move_val_init => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()),
            sym::prefetch_read_data
            | sym::prefetch_write_data
            | sym::prefetch_read_instruction
            | sym::prefetch_write_instruction => (
M
Mark Rousskov 已提交
186 187 188 189 190 191 192
                1,
                vec![
                    tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }),
                    tcx.types.i32,
                ],
                tcx.mk_unit(),
            ),
193 194
            sym::drop_in_place => (1, vec![tcx.mk_mut_ptr(param(0))], tcx.mk_unit()),
            sym::needs_drop => (1, Vec::new(), tcx.types.bool),
195

196 197 198
            sym::type_name => (1, Vec::new(), tcx.mk_static_str()),
            sym::type_id => (1, Vec::new(), tcx.types.u64),
            sym::offset | sym::arith_offset => (
M
Mark Rousskov 已提交
199 200 201 202 203 204 205
                1,
                vec![
                    tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }),
                    tcx.types.isize,
                ],
                tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }),
            ),
206
            sym::copy | sym::copy_nonoverlapping => (
M
Mark Rousskov 已提交
207 208 209 210 211 212 213 214
                1,
                vec![
                    tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }),
                    tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Mut }),
                    tcx.types.usize,
                ],
                tcx.mk_unit(),
            ),
215
            sym::volatile_copy_memory | sym::volatile_copy_nonoverlapping_memory => (
M
Mark Rousskov 已提交
216 217 218 219 220 221 222 223
                1,
                vec![
                    tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Mut }),
                    tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }),
                    tcx.types.usize,
                ],
                tcx.mk_unit(),
            ),
224
            sym::write_bytes | sym::volatile_set_memory => (
M
Mark Rousskov 已提交
225 226 227 228 229 230 231 232
                1,
                vec![
                    tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Mut }),
                    tcx.types.u8,
                    tcx.types.usize,
                ],
                tcx.mk_unit(),
            ),
233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276
            sym::sqrtf32 => (0, vec![tcx.types.f32], tcx.types.f32),
            sym::sqrtf64 => (0, vec![tcx.types.f64], tcx.types.f64),
            sym::powif32 => (0, vec![tcx.types.f32, tcx.types.i32], tcx.types.f32),
            sym::powif64 => (0, vec![tcx.types.f64, tcx.types.i32], tcx.types.f64),
            sym::sinf32 => (0, vec![tcx.types.f32], tcx.types.f32),
            sym::sinf64 => (0, vec![tcx.types.f64], tcx.types.f64),
            sym::cosf32 => (0, vec![tcx.types.f32], tcx.types.f32),
            sym::cosf64 => (0, vec![tcx.types.f64], tcx.types.f64),
            sym::powf32 => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
            sym::powf64 => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
            sym::expf32 => (0, vec![tcx.types.f32], tcx.types.f32),
            sym::expf64 => (0, vec![tcx.types.f64], tcx.types.f64),
            sym::exp2f32 => (0, vec![tcx.types.f32], tcx.types.f32),
            sym::exp2f64 => (0, vec![tcx.types.f64], tcx.types.f64),
            sym::logf32 => (0, vec![tcx.types.f32], tcx.types.f32),
            sym::logf64 => (0, vec![tcx.types.f64], tcx.types.f64),
            sym::log10f32 => (0, vec![tcx.types.f32], tcx.types.f32),
            sym::log10f64 => (0, vec![tcx.types.f64], tcx.types.f64),
            sym::log2f32 => (0, vec![tcx.types.f32], tcx.types.f32),
            sym::log2f64 => (0, vec![tcx.types.f64], tcx.types.f64),
            sym::fmaf32 => (0, vec![tcx.types.f32, tcx.types.f32, tcx.types.f32], tcx.types.f32),
            sym::fmaf64 => (0, vec![tcx.types.f64, tcx.types.f64, tcx.types.f64], tcx.types.f64),
            sym::fabsf32 => (0, vec![tcx.types.f32], tcx.types.f32),
            sym::fabsf64 => (0, vec![tcx.types.f64], tcx.types.f64),
            sym::minnumf32 => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
            sym::minnumf64 => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
            sym::maxnumf32 => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
            sym::maxnumf64 => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
            sym::copysignf32 => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
            sym::copysignf64 => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
            sym::floorf32 => (0, vec![tcx.types.f32], tcx.types.f32),
            sym::floorf64 => (0, vec![tcx.types.f64], tcx.types.f64),
            sym::ceilf32 => (0, vec![tcx.types.f32], tcx.types.f32),
            sym::ceilf64 => (0, vec![tcx.types.f64], tcx.types.f64),
            sym::truncf32 => (0, vec![tcx.types.f32], tcx.types.f32),
            sym::truncf64 => (0, vec![tcx.types.f64], tcx.types.f64),
            sym::rintf32 => (0, vec![tcx.types.f32], tcx.types.f32),
            sym::rintf64 => (0, vec![tcx.types.f64], tcx.types.f64),
            sym::nearbyintf32 => (0, vec![tcx.types.f32], tcx.types.f32),
            sym::nearbyintf64 => (0, vec![tcx.types.f64], tcx.types.f64),
            sym::roundf32 => (0, vec![tcx.types.f32], tcx.types.f32),
            sym::roundf64 => (0, vec![tcx.types.f64], tcx.types.f64),

            sym::volatile_load | sym::unaligned_volatile_load => {
M
Mark Rousskov 已提交
277
                (1, vec![tcx.mk_imm_ptr(param(0))], param(0))
278
            }
279
            sym::volatile_store | sym::unaligned_volatile_store => {
M
Mark Rousskov 已提交
280
                (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit())
281
            }
M
Mark Rousskov 已提交
282

283 284 285 286 287 288 289
            sym::ctpop
            | sym::ctlz
            | sym::ctlz_nonzero
            | sym::cttz
            | sym::cttz_nonzero
            | sym::bswap
            | sym::bitreverse => (1, vec![param(0)], param(0)),
M
Mark Rousskov 已提交
290

291
            sym::add_with_overflow | sym::sub_with_overflow | sym::mul_with_overflow => {
M
Mark Rousskov 已提交
292
                (1, vec![param(0), param(0)], tcx.intern_tup(&[param(0), tcx.types.bool]))
293
            }
M
Mark Rousskov 已提交
294

295
            sym::ptr_guaranteed_eq | sym::ptr_guaranteed_ne => {
296 297 298
                (1, vec![tcx.mk_imm_ptr(param(0)), tcx.mk_imm_ptr(param(0))], tcx.types.bool)
            }

299
            sym::ptr_offset_from => {
M
Mark Rousskov 已提交
300
                (1, vec![tcx.mk_imm_ptr(param(0)), tcx.mk_imm_ptr(param(0))], tcx.types.isize)
301
            }
302
            sym::unchecked_div | sym::unchecked_rem | sym::exact_div => {
M
Mark Rousskov 已提交
303
                (1, vec![param(0), param(0)], param(0))
304
            }
305
            sym::unchecked_shl | sym::unchecked_shr | sym::rotate_left | sym::rotate_right => {
M
Mark Rousskov 已提交
306
                (1, vec![param(0), param(0)], param(0))
307
            }
308
            sym::unchecked_add | sym::unchecked_sub | sym::unchecked_mul => {
M
Mark Rousskov 已提交
309
                (1, vec![param(0), param(0)], param(0))
310
            }
311
            sym::wrapping_add | sym::wrapping_sub | sym::wrapping_mul => {
M
Mark Rousskov 已提交
312
                (1, vec![param(0), param(0)], param(0))
313
            }
314 315
            sym::saturating_add | sym::saturating_sub => (1, vec![param(0), param(0)], param(0)),
            sym::fadd_fast | sym::fsub_fast | sym::fmul_fast | sym::fdiv_fast | sym::frem_fast => {
M
Mark Rousskov 已提交
316
                (1, vec![param(0), param(0)], param(0))
317
            }
318
            sym::float_to_int_unchecked => (2, vec![param(0)], param(1)),
319

320 321 322
            sym::assume => (0, vec![tcx.types.bool], tcx.mk_unit()),
            sym::likely => (0, vec![tcx.types.bool], tcx.types.bool),
            sym::unlikely => (0, vec![tcx.types.bool], tcx.types.bool),
323

324
            sym::discriminant_value => {
325 326 327 328 329 330 331 332 333 334 335 336 337
                let assoc_items =
                    tcx.associated_items(tcx.lang_items().discriminant_kind_trait().unwrap());
                let discriminant_def_id = assoc_items.in_definition_order().next().unwrap().def_id;

                (
                    1,
                    vec![tcx.mk_imm_ref(
                        tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BrAnon(0))),
                        param(0),
                    )],
                    tcx.mk_projection(discriminant_def_id, tcx.mk_substs([param(0).into()].iter())),
                )
            }
338

339
            kw::Try => {
340
                let mut_u8 = tcx.mk_mut_ptr(tcx.types.u8);
341
                let try_fn_ty = ty::Binder::bind(tcx.mk_fn_sig(
342
                    iter::once(mut_u8),
K
kenta7777 已提交
343
                    tcx.mk_unit(),
344 345 346 347
                    false,
                    hir::Unsafety::Normal,
                    Abi::Rust,
                ));
348 349 350 351 352 353 354 355 356 357 358 359
                let catch_fn_ty = ty::Binder::bind(tcx.mk_fn_sig(
                    [mut_u8, mut_u8].iter().cloned(),
                    tcx.mk_unit(),
                    false,
                    hir::Unsafety::Normal,
                    Abi::Rust,
                ));
                (
                    0,
                    vec![tcx.mk_fn_ptr(try_fn_ty), mut_u8, tcx.mk_fn_ptr(catch_fn_ty)],
                    tcx.types.i32,
                )
360 361
            }

362
            sym::va_start | sym::va_end => match mk_va_list_ty(hir::Mutability::Mut) {
M
Mark Rousskov 已提交
363 364 365
                Some((va_list_ref_ty, _)) => (0, vec![va_list_ref_ty], tcx.mk_unit()),
                None => bug!("`va_list` language item needed for C-variadic intrinsics"),
            },
366

367
            sym::va_copy => match mk_va_list_ty(hir::Mutability::Not) {
M
Mark Rousskov 已提交
368 369 370
                Some((va_list_ref_ty, va_list_ty)) => {
                    let va_list_ptr_ty = tcx.mk_mut_ptr(va_list_ty);
                    (0, vec![va_list_ptr_ty, va_list_ref_ty], tcx.mk_unit())
371
                }
M
Mark Rousskov 已提交
372 373
                None => bug!("`va_list` language item needed for C-variadic intrinsics"),
            },
374

375
            sym::va_arg => match mk_va_list_ty(hir::Mutability::Mut) {
M
Mark Rousskov 已提交
376 377 378
                Some((va_list_ref_ty, _)) => (1, vec![va_list_ref_ty], param(0)),
                None => bug!("`va_list` language item needed for C-variadic intrinsics"),
            },
379

380
            sym::nontemporal_store => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()),
381

382
            other => {
M
Mark Rousskov 已提交
383 384 385 386 387
                struct_span_err!(
                    tcx.sess,
                    it.span,
                    E0093,
                    "unrecognized intrinsic function: `{}`",
388
                    other,
M
Mark Rousskov 已提交
389 390 391
                )
                .span_label(it.span, "unrecognized intrinsic")
                .emit();
392 393 394
                return;
            }
        };
395
        (n_tps, inputs, output, unsafety)
396
    };
397
    equate_intrinsic_type(tcx, it, def_id, n_tps, Abi::RustIntrinsic, unsafety, inputs, output)
398 399 400
}

/// Type-check `extern "platform-intrinsic" { ... }` functions.
401
pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
402
    let param = |n| {
403
        let name = Symbol::intern(&format!("P{}", n));
404
        tcx.mk_ty_param(n, name)
405 406
    };

407
    let def_id = tcx.hir().local_def_id(it.hir_id).to_def_id();
408
    let name = it.ident.name;
409

410 411
    let (n_tps, inputs, output) = match name {
        sym::simd_eq | sym::simd_ne | sym::simd_lt | sym::simd_le | sym::simd_gt | sym::simd_ge => {
412 413
            (2, vec![param(0), param(0)], param(1))
        }
414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449
        sym::simd_add
        | sym::simd_sub
        | sym::simd_mul
        | sym::simd_rem
        | sym::simd_div
        | sym::simd_shl
        | sym::simd_shr
        | sym::simd_and
        | sym::simd_or
        | sym::simd_xor
        | sym::simd_fmin
        | sym::simd_fmax
        | sym::simd_fpow
        | sym::simd_saturating_add
        | sym::simd_saturating_sub => (1, vec![param(0), param(0)], param(0)),
        sym::simd_fsqrt
        | sym::simd_fsin
        | sym::simd_fcos
        | sym::simd_fexp
        | sym::simd_fexp2
        | sym::simd_flog2
        | sym::simd_flog10
        | sym::simd_flog
        | sym::simd_fabs
        | sym::simd_floor
        | sym::simd_ceil => (1, vec![param(0)], param(0)),
        sym::simd_fpowi => (1, vec![param(0), tcx.types.i32], param(0)),
        sym::simd_fma => (1, vec![param(0), param(0), param(0)], param(0)),
        sym::simd_gather => (3, vec![param(0), param(1), param(2)], param(0)),
        sym::simd_scatter => (3, vec![param(0), param(1), param(2)], tcx.mk_unit()),
        sym::simd_insert => (2, vec![param(0), tcx.types.u32, param(1)], param(0)),
        sym::simd_extract => (2, vec![param(0), tcx.types.u32], param(1)),
        sym::simd_cast => (2, vec![param(0)], param(1)),
        sym::simd_bitmask => (2, vec![param(0)], param(1)),
        sym::simd_select | sym::simd_select_bitmask => {
            (2, vec![param(0), param(1), param(1)], param(1))
450
        }
451 452
        sym::simd_reduce_all | sym::simd_reduce_any => (1, vec![param(0)], tcx.types.bool),
        sym::simd_reduce_add_ordered | sym::simd_reduce_mul_ordered => {
M
Mark Rousskov 已提交
453
            (2, vec![param(0), param(1)], param(1))
454
        }
455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480
        sym::simd_reduce_add_unordered
        | sym::simd_reduce_mul_unordered
        | sym::simd_reduce_and
        | sym::simd_reduce_or
        | sym::simd_reduce_xor
        | sym::simd_reduce_min
        | sym::simd_reduce_max
        | sym::simd_reduce_min_nanless
        | sym::simd_reduce_max_nanless => (2, vec![param(0)], param(1)),
        name if name.as_str().starts_with("simd_shuffle") => {
            match name.as_str()["simd_shuffle".len()..].parse() {
                Ok(n) => {
                    let params = vec![param(0), param(0), tcx.mk_array(tcx.types.u32, n)];
                    (2, params, param(1))
                }
                Err(_) => {
                    struct_span_err!(
                        tcx.sess,
                        it.span,
                        E0439,
                        "invalid `simd_shuffle`, needs length: `{}`",
                        name
                    )
                    .emit();
                    return;
                }
M
Mark Rousskov 已提交
481
            }
482
        }
483
        _ => {
484
            let msg = format!("unrecognized platform-specific intrinsic function: `{}`", name);
485
            tcx.sess.struct_span_err(it.span, &msg).emit();
486
            return;
487 488 489
        }
    };

M
Mark Rousskov 已提交
490 491 492
    equate_intrinsic_type(
        tcx,
        it,
493
        def_id,
M
Mark Rousskov 已提交
494 495 496 497 498 499
        n_tps,
        Abi::PlatformIntrinsic,
        hir::Unsafety::Unsafe,
        inputs,
        output,
    )
500
}