]> git.proxmox.com Git - rustc.git/blame - library/stdarch/crates/stdarch-verify/tests/x86-intel.rs
New upstream version 1.48.0~beta.8+dfsg1
[rustc.git] / library / stdarch / crates / stdarch-verify / tests / x86-intel.rs
CommitLineData
0531ce1d 1#![allow(bad_style)]
416331ca 2#![allow(unused)]
0731742a
XL
3#![allow(
4 clippy::shadow_reuse,
5 clippy::cast_lossless,
6 clippy::match_same_arms,
7 clippy::nonminimal_bool,
8 clippy::print_stdout,
9 clippy::use_debug,
10 clippy::eq_op,
11 clippy::useless_format
8faf50e0 12)]
0531ce1d 13
0531ce1d
XL
14use std::collections::{BTreeMap, HashMap};
15
0731742a 16use serde::Deserialize;
0531ce1d
XL
17
18const PRINT_INSTRUCTION_VIOLATIONS: bool = false;
19const PRINT_MISSING_LISTS: bool = false;
20const PRINT_MISSING_LISTS_MARKDOWN: bool = false;
21
22struct Function {
23 name: &'static str,
24 arguments: &'static [&'static Type],
25 ret: Option<&'static Type>,
26 target_feature: Option<&'static str>,
27 instrs: &'static [&'static str],
28 file: &'static str,
29 required_const: &'static [usize],
e1599b0c 30 has_test: bool,
0531ce1d
XL
31}
32
33static F32: Type = Type::PrimFloat(32);
34static F64: Type = Type::PrimFloat(64);
35static I16: Type = Type::PrimSigned(16);
36static I32: Type = Type::PrimSigned(32);
37static I64: Type = Type::PrimSigned(64);
38static I8: Type = Type::PrimSigned(8);
39static U16: Type = Type::PrimUnsigned(16);
40static U32: Type = Type::PrimUnsigned(32);
41static U64: Type = Type::PrimUnsigned(64);
0731742a 42static U128: Type = Type::PrimUnsigned(128);
0531ce1d 43static U8: Type = Type::PrimUnsigned(8);
0731742a 44static ORDERING: Type = Type::Ordering;
0531ce1d
XL
45
46static M64: Type = Type::M64;
47static M128: Type = Type::M128;
48static M128I: Type = Type::M128I;
49static M128D: Type = Type::M128D;
50static M256: Type = Type::M256;
51static M256I: Type = Type::M256I;
52static M256D: Type = Type::M256D;
0731742a
XL
53static M512: Type = Type::M512;
54static M512I: Type = Type::M512I;
55static M512D: Type = Type::M512D;
f9f354fc 56static MMASK8: Type = Type::MMASK8;
0731742a 57static MMASK16: Type = Type::MMASK16;
3dfed10e 58static MM_CMPINT_ENUM: Type = Type::MM_CMPINT_ENUM;
1b1a35ee
XL
59static MM_MANTISSA_NORM_ENUM: Type = Type::MM_MANTISSA_NORM_ENUM;
60static MM_MANTISSA_SIGN_ENUM: Type = Type::MM_MANTISSA_SIGN_ENUM;
61static MM_PERM_ENUM: Type = Type::MM_PERM_ENUM;
0531ce1d
XL
62
63static TUPLE: Type = Type::Tuple;
64static CPUID: Type = Type::CpuidResult;
0731742a 65static NEVER: Type = Type::Never;
0531ce1d
XL
66
67#[derive(Debug)]
68enum Type {
69 PrimFloat(u8),
70 PrimSigned(u8),
71 PrimUnsigned(u8),
416331ca
XL
72 MutPtr(&'static Type),
73 ConstPtr(&'static Type),
0531ce1d
XL
74 M64,
75 M128,
76 M128D,
77 M128I,
78 M256,
79 M256D,
80 M256I,
0731742a
XL
81 M512,
82 M512D,
83 M512I,
f9f354fc 84 MMASK8,
0731742a 85 MMASK16,
3dfed10e 86 MM_CMPINT_ENUM,
1b1a35ee
XL
87 MM_MANTISSA_NORM_ENUM,
88 MM_MANTISSA_SIGN_ENUM,
89 MM_PERM_ENUM,
0531ce1d
XL
90 Tuple,
91 CpuidResult,
0731742a
XL
92 Never,
93 Ordering,
0531ce1d
XL
94}
95
416331ca 96stdarch_verify::x86_functions!(static FUNCTIONS);
0531ce1d
XL
97
98#[derive(Deserialize)]
99struct Data {
100 #[serde(rename = "intrinsic", default)]
101 intrinsics: Vec<Intrinsic>,
102}
103
104#[derive(Deserialize)]
105struct Intrinsic {
3dfed10e
XL
106 #[serde(rename = "return")]
107 return_: Return,
0531ce1d
XL
108 name: String,
109 #[serde(rename = "CPUID", default)]
110 cpuid: Vec<String>,
111 #[serde(rename = "parameter", default)]
112 parameters: Vec<Parameter>,
113 #[serde(default)]
114 instruction: Vec<Instruction>,
115}
116
117#[derive(Deserialize)]
118struct Parameter {
119 #[serde(rename = "type")]
120 type_: String,
121}
122
3dfed10e
XL
123#[derive(Deserialize)]
124struct Return {
125 #[serde(rename = "type")]
126 type_: String,
127}
128
0531ce1d
XL
129#[derive(Deserialize, Debug)]
130struct Instruction {
131 name: String,
132}
133
134macro_rules! bail {
135 ($($t:tt)*) => (return Err(format!($($t)*)))
136}
137
138#[test]
139fn verify_all_signatures() {
140 // This XML document was downloaded from Intel's site. To update this you
141 // can visit intel's intrinsics guide online documentation:
142 //
143 // https://software.intel.com/sites/landingpage/IntrinsicsGuide/#
144 //
145 // Open up the network console and you'll see an xml file was downloaded
146 // (currently called data-3.4.xml). That's the file we downloaded
147 // here.
148 let xml = include_bytes!("../x86-intel.xml");
149
150 let xml = &xml[..];
9fa01778 151 let data: Data = serde_xml_rs::from_reader(xml).expect("failed to deserialize xml");
0531ce1d
XL
152 let mut map = HashMap::new();
153 for intrinsic in &data.intrinsics {
154 map.entry(&intrinsic.name[..])
155 .or_insert_with(Vec::new)
156 .push(intrinsic);
157 }
158
159 let mut all_valid = true;
160 'outer: for rust in FUNCTIONS {
e1599b0c
XL
161 if !rust.has_test {
162 // FIXME: this list should be almost empty
163 let skip = [
164 "__readeflags",
165 "__readeflags",
166 "__writeeflags",
167 "__writeeflags",
168 "_mm_comige_ss",
169 "_mm_cvt_ss2si",
170 "_mm_cvtt_ss2si",
171 "_mm_cvt_si2ss",
172 "_mm_set_ps1",
173 "_mm_load_ps1",
174 "_mm_store_ps1",
175 "_mm_getcsr",
176 "_mm_setcsr",
177 "_MM_GET_EXCEPTION_MASK",
178 "_MM_GET_EXCEPTION_STATE",
179 "_MM_GET_FLUSH_ZERO_MODE",
180 "_MM_GET_ROUNDING_MODE",
181 "_MM_SET_EXCEPTION_MASK",
182 "_MM_SET_EXCEPTION_STATE",
183 "_MM_SET_FLUSH_ZERO_MODE",
184 "_MM_SET_ROUNDING_MODE",
185 "_mm_prefetch",
186 "_mm_undefined_ps",
187 "_m_pmaxsw",
188 "_m_pmaxub",
189 "_m_pminsw",
190 "_m_pminub",
191 "_m_pavgb",
192 "_m_pavgw",
193 "_m_psadbw",
194 "_mm_cvt_pi2ps",
195 "_m_maskmovq",
196 "_m_pextrw",
197 "_m_pinsrw",
198 "_m_pmovmskb",
199 "_m_pshufw",
200 "_mm_cvtt_ps2pi",
201 "_mm_cvt_ps2pi",
202 "__cpuid_count",
203 "__cpuid",
204 "__get_cpuid_max",
205 "_xsave",
206 "_xrstor",
207 "_xsetbv",
208 "_xgetbv",
209 "_xsaveopt",
210 "_xsavec",
211 "_xsaves",
212 "_xrstors",
213 "_mm_bslli_si128",
214 "_mm_bsrli_si128",
215 "_mm_undefined_pd",
216 "_mm_undefined_si128",
217 "_mm_cvtps_ph",
218 "_mm256_cvtps_ph",
219 "_rdtsc",
220 "__rdtscp",
221 "_mm256_castps128_ps256",
222 "_mm256_castpd128_pd256",
223 "_mm256_castsi128_si256",
224 "_mm256_undefined_ps",
225 "_mm256_undefined_pd",
226 "_mm256_undefined_si256",
227 "_bextr2_u32",
228 "_mm_tzcnt_32",
e1599b0c
XL
229 "_m_paddb",
230 "_m_paddw",
231 "_m_paddd",
232 "_m_paddsb",
233 "_m_paddsw",
234 "_m_paddusb",
235 "_m_paddusw",
236 "_m_psubb",
237 "_m_psubw",
238 "_m_psubd",
239 "_m_psubsb",
240 "_m_psubsw",
241 "_m_psubusb",
242 "_m_psubusw",
243 "_mm_set_pi16",
244 "_mm_set_pi32",
245 "_mm_set_pi8",
246 "_mm_set1_pi16",
247 "_mm_set1_pi32",
248 "_mm_set1_pi8",
249 "_mm_setr_pi16",
250 "_mm_setr_pi32",
251 "_mm_setr_pi8",
252 "ud2",
253 "_mm_min_epi8",
254 "_mm_min_epi32",
255 "_xbegin",
256 "_xend",
257 "_rdrand16_step",
258 "_rdrand32_step",
259 "_rdseed16_step",
260 "_rdseed32_step",
261 "_fxsave",
262 "_fxrstor",
263 "_t1mskc_u64",
264 "_mm256_shuffle_epi32",
265 "_mm256_bslli_epi128",
266 "_mm256_bsrli_epi128",
267 "_mm256_unpackhi_epi8",
268 "_mm256_unpacklo_epi8",
269 "_mm256_unpackhi_epi16",
270 "_mm256_unpacklo_epi16",
271 "_mm256_unpackhi_epi32",
272 "_mm256_unpacklo_epi32",
273 "_mm256_unpackhi_epi64",
274 "_mm256_unpacklo_epi64",
275 "_xsave64",
276 "_xrstor64",
277 "_xsaveopt64",
278 "_xsavec64",
279 "_xsaves64",
280 "_xrstors64",
281 "_mm_cvtsi64x_si128",
282 "_mm_cvtsi128_si64x",
283 "_mm_cvtsi64x_sd",
284 "cmpxchg16b",
285 "_rdrand64_step",
286 "_rdseed64_step",
287 "_bextr2_u64",
288 "_mm_tzcnt_64",
289 "_fxsave64",
290 "_fxrstor64",
3dfed10e
XL
291 "_mm512_undefined_ps",
292 "_mm512_undefined_pd",
e1599b0c
XL
293 ];
294 if !skip.contains(&rust.name) {
295 println!(
296 "missing run-time test named `test_{}` for `{}`",
297 {
298 let mut id = rust.name;
299 while id.starts_with('_') {
300 id = &id[1..];
301 }
302 id
303 },
304 rust.name
305 );
306 all_valid = false;
307 }
308 }
309
0531ce1d 310 match rust.name {
0731742a
XL
311 // These aren't defined by Intel but they're defined by what appears
312 // to be all other compilers. For more information see
416331ca 313 // rust-lang/stdarch#307, and otherwise these signatures
0731742a
XL
314 // have all been manually verified.
315 "__readeflags" |
316 "__writeeflags" |
317 "__cpuid_count" |
318 "__cpuid" |
319 "__get_cpuid_max" |
320 // Not listed with intel, but manually verified
321 "cmpxchg16b" |
322 // The UD2 intrinsic is not defined by Intel, but it was agreed on
323 // in the RFC Issue 2512:
324 // https://github.com/rust-lang/rfcs/issues/2512
325 "ud2"
326 => continue,
48663c56
XL
327 // Intel requires the mask argument for _mm_shuffle_ps to be an
328 // unsigned integer, but all other _mm_shuffle_.. intrinsics
329 // take a signed-integer. This breaks `_MM_SHUFFLE` for
330 // `_mm_shuffle_ps`:
331 "_mm_shuffle_ps" => continue,
0531ce1d
XL
332 _ => {}
333 }
334
335 // these are all AMD-specific intrinsics
336 if let Some(feature) = rust.target_feature {
337 if feature.contains("sse4a") || feature.contains("tbm") {
338 continue;
339 }
340 }
341
342 let intel = match map.remove(rust.name) {
343 Some(i) => i,
344 None => panic!("missing intel definition for {}", rust.name),
345 };
346
347 let mut errors = Vec::new();
348 for intel in intel {
349 match matches(rust, intel) {
350 Ok(()) => continue 'outer,
351 Err(e) => errors.push(e),
352 }
353 }
354 println!("failed to verify `{}`", rust.name);
355 for error in errors {
356 println!(" * {}", error);
357 }
358 all_valid = false;
359 }
360 assert!(all_valid);
361
362 let mut missing = BTreeMap::new();
363 for (name, intel) in &map {
364 // currently focused mainly on missing SIMD intrinsics, but there's
365 // definitely some other assorted ones that we're missing.
366 if !name.starts_with("_mm") {
367 continue;
368 }
369
370 // we'll get to avx-512 later
371 // let avx512 = intel.iter().any(|i| {
372 // i.name.starts_with("_mm512") || i.cpuid.iter().any(|c| {
373 // c.contains("512")
374 // })
375 // });
376 // if avx512 {
377 // continue
378 // }
379
380 for intel in intel {
381 missing
382 .entry(&intel.cpuid)
383 .or_insert_with(Vec::new)
384 .push(intel);
385 }
386 }
387
388 // generate a bulleted list of missing intrinsics
389 if PRINT_MISSING_LISTS || PRINT_MISSING_LISTS_MARKDOWN {
390 for (k, v) in missing {
391 if PRINT_MISSING_LISTS_MARKDOWN {
392 println!("\n<details><summary>{:?}</summary><p>\n", k);
393 for intel in v {
394 let url = format!(
395 "https://software.intel.com/sites/landingpage\
396 /IntrinsicsGuide/#text={}&expand=5236",
397 intel.name
398 );
399 println!(" * [ ] [`{}`]({})", intel.name, url);
400 }
401 println!("</p></details>\n");
402 } else {
403 println!("\n{:?}\n", k);
404 for intel in v {
405 println!("\t{}", intel.name);
406 }
407 }
408 }
409 }
410}
411
412fn matches(rust: &Function, intel: &Intrinsic) -> Result<(), String> {
413 // Verify that all `#[target_feature]` annotations are correct,
414 // ensuring that we've actually enabled the right instruction
415 // set for this intrinsic.
416 match rust.name {
0731742a
XL
417 "_bswap" | "_bswap64" => {}
418
419 // These don't actually have a target feature unlike their brethren with
420 // the `x` inside the name which requires adx
421 "_addcarry_u32" | "_addcarry_u64" | "_subborrow_u32" | "_subborrow_u64" => {}
422
532ac7d7
XL
423 "_bittest"
424 | "_bittestandset"
425 | "_bittestandreset"
426 | "_bittestandcomplement"
427 | "_bittest64"
428 | "_bittestandset64"
429 | "_bittestandreset64"
430 | "_bittestandcomplement64" => {}
431
0531ce1d
XL
432 _ => {
433 if intel.cpuid.is_empty() {
434 bail!("missing cpuid for {}", rust.name);
435 }
436 }
437 }
438
439 for cpuid in &intel.cpuid {
532ac7d7
XL
440 // The pause intrinsic is in the SSE2 module, but it is backwards
441 // compatible with CPUs without SSE2, and it therefore does not need the
442 // target-feature attribute.
443 if rust.name == "_mm_pause" {
444 continue;
445 }
0531ce1d
XL
446 // this is needed by _xsave and probably some related intrinsics,
447 // but let's just skip it for now.
448 if *cpuid == "XSS" {
449 continue;
450 }
451
452 // these flags on the rdtsc/rtdscp intrinsics we don't test for right
453 // now, but we may wish to add these one day!
454 //
455 // For more info see #308
456 if *cpuid == "TSC" || *cpuid == "RDTSCP" {
457 continue;
458 }
459
460 let cpuid = cpuid
461 .chars()
462 .flat_map(|c| c.to_lowercase())
463 .collect::<String>();
464
416331ca 465 // Fix mismatching feature names:
9fa01778 466 let fixup_cpuid = |cpuid: String| match cpuid.as_ref() {
416331ca
XL
467 // The XML file names IFMA as "avx512ifma52", while Rust calls
468 // it "avx512ifma".
9fa01778 469 "avx512ifma52" => String::from("avx512ifma"),
3dfed10e
XL
470 // Some AVX512f intrinsics are also supported by Knight's Corner.
471 // The XML lists them as avx512f/kncni, but we are solely gating
472 // them behind avx512f since we don't have a KNC feature yet.
473 "avx512f/kncni" => String::from("avx512f"),
416331ca
XL
474 // See: https://github.com/rust-lang/stdarch/issues/738
475 // The intrinsics guide calls `f16c` `fp16c` in disagreement with
476 // Intel's architecture manuals.
477 "fp16c" => String::from("f16c"),
9fa01778
XL
478 _ => cpuid,
479 };
480 let fixed_cpuid = fixup_cpuid(cpuid);
481
8faf50e0
XL
482 let rust_feature = rust
483 .target_feature
484 .expect(&format!("no target feature listed for {}", rust.name));
9fa01778
XL
485
486 if rust_feature.contains(&fixed_cpuid) {
0531ce1d
XL
487 continue;
488 }
489 bail!(
490 "intel cpuid `{}` not in `{}` for {}",
9fa01778 491 fixed_cpuid,
0531ce1d
XL
492 rust_feature,
493 rust.name
494 )
495 }
496
497 if PRINT_INSTRUCTION_VIOLATIONS {
498 if rust.instrs.is_empty() {
499 if !intel.instruction.is_empty() {
500 println!(
501 "instruction not listed for `{}`, but intel lists {:?}",
502 rust.name, intel.instruction
503 );
504 }
505
506 // If intel doesn't list any instructions and we do then don't
507 // bother trying to look for instructions in intel, we've just got
508 // some extra assertions on our end.
509 } else if !intel.instruction.is_empty() {
510 for instr in rust.instrs {
0731742a 511 let asserting = intel.instruction.iter().any(|a| a.name.starts_with(instr));
0531ce1d
XL
512 if !asserting {
513 println!(
514 "intel failed to list `{}` as an instruction for `{}`",
515 instr, rust.name
516 );
517 }
518 }
519 }
520 }
521
522 // Make sure we've got the right return type.
523 if let Some(t) = rust.ret {
3dfed10e
XL
524 equate(t, &intel.return_.type_, rust.name, false)?;
525 } else if intel.return_.type_ != "" && intel.return_.type_ != "void" {
0531ce1d
XL
526 bail!(
527 "{} returns `{}` with intel, void in rust",
528 rust.name,
3dfed10e 529 intel.return_.type_
0531ce1d
XL
530 )
531 }
532
533 // If there's no arguments on Rust's side intel may list one "void"
534 // argument, so handle that here.
535 if rust.arguments.is_empty() && intel.parameters.len() == 1 {
536 if intel.parameters[0].type_ != "void" {
537 bail!("rust has 0 arguments, intel has one for")
538 }
539 } else {
540 // Otherwise we want all parameters to be exactly the same
541 if rust.arguments.len() != intel.parameters.len() {
542 bail!("wrong number of arguments on {}", rust.name)
543 }
0731742a 544 for (i, (a, b)) in intel.parameters.iter().zip(rust.arguments).enumerate() {
0531ce1d
XL
545 let is_const = rust.required_const.contains(&i);
546 equate(b, &a.type_, &intel.name, is_const)?;
547 }
548 }
549
0731742a
XL
550 let any_i64 = rust
551 .arguments
552 .iter()
553 .cloned()
554 .chain(rust.ret)
555 .any(|arg| match *arg {
556 Type::PrimSigned(64) | Type::PrimUnsigned(64) => true,
557 _ => false,
558 });
0531ce1d
XL
559 let any_i64_exempt = match rust.name {
560 // These intrinsics have all been manually verified against Clang's
561 // headers to be available on x86, and the u64 arguments seem
562 // spurious I guess?
0731742a
XL
563 "_xsave" | "_xrstor" | "_xsetbv" | "_xgetbv" | "_xsaveopt" | "_xsavec" | "_xsaves"
564 | "_xrstors" => true,
0531ce1d
XL
565
566 // Apparently all of clang/msvc/gcc accept these intrinsics on
567 // 32-bit, so let's do the same
0731742a 568 "_mm_set_epi64x" | "_mm_set1_epi64x" | "_mm256_set_epi64x" | "_mm256_setr_epi64x"
9fa01778 569 | "_mm256_set1_epi64x" | "_mm512_set1_epi64" => true,
0531ce1d
XL
570
571 // These return a 64-bit argument but they're assembled from other
572 // 32-bit registers, so these work on 32-bit just fine. See #308 for
573 // more info.
574 "_rdtsc" | "__rdtscp" => true,
575
576 _ => false,
577 };
578 if any_i64 && !any_i64_exempt && !rust.file.contains("x86_64") {
579 bail!(
580 "intrinsic `{}` uses a 64-bit bare type but may be \
581 available on 32-bit platforms",
582 rust.name
583 )
584 }
585 Ok(())
586}
587
0731742a 588fn equate(t: &Type, intel: &str, intrinsic: &str, is_const: bool) -> Result<(), String> {
416331ca
XL
589 // Make pointer adjacent to the type: float * foo => float* foo
590 let mut intel = intel.replace(" *", "*");
591 // Make mutability modifier adjacent to the pointer:
592 // float const * foo => float const* foo
593 intel = intel.replace("const *", "const*");
594 // Normalize mutability modifier to after the type:
595 // const float* foo => float const*
596 if intel.starts_with("const") && intel.ends_with("*") {
597 intel = intel.replace("const ", "");
598 intel = intel.replace("*", " const*");
599 }
0531ce1d
XL
600 let require_const = || {
601 if is_const {
602 return Ok(());
603 }
8faf50e0 604 Err(format!("argument required to be const but isn't"))
0531ce1d
XL
605 };
606 match (t, &intel[..]) {
607 (&Type::PrimFloat(32), "float") => {}
608 (&Type::PrimFloat(64), "double") => {}
609 (&Type::PrimSigned(16), "__int16") => {}
610 (&Type::PrimSigned(16), "short") => {}
611 (&Type::PrimSigned(32), "__int32") => {}
612 (&Type::PrimSigned(32), "const int") => require_const()?,
613 (&Type::PrimSigned(32), "int") => {}
614 (&Type::PrimSigned(64), "__int64") => {}
615 (&Type::PrimSigned(64), "long long") => {}
616 (&Type::PrimSigned(8), "__int8") => {}
617 (&Type::PrimSigned(8), "char") => {}
618 (&Type::PrimUnsigned(16), "unsigned short") => {}
619 (&Type::PrimUnsigned(32), "unsigned int") => {}
416331ca 620 (&Type::PrimUnsigned(32), "const unsigned int") => {}
0531ce1d
XL
621 (&Type::PrimUnsigned(64), "unsigned __int64") => {}
622 (&Type::PrimUnsigned(8), "unsigned char") => {}
416331ca
XL
623 (&Type::M64, "__m64") => {}
624 (&Type::M128, "__m128") => {}
625 (&Type::M128I, "__m128i") => {}
626 (&Type::M128D, "__m128d") => {}
627 (&Type::M256, "__m256") => {}
628 (&Type::M256I, "__m256i") => {}
629 (&Type::M256D, "__m256d") => {}
630 (&Type::M512, "__m512") => {}
631 (&Type::M512I, "__m512i") => {}
632 (&Type::M512D, "__m512d") => {}
633
634 (&Type::MutPtr(&Type::PrimFloat(32)), "float*") => {}
635 (&Type::MutPtr(&Type::PrimFloat(64)), "double*") => {}
3dfed10e
XL
636 (&Type::MutPtr(&Type::PrimFloat(32)), "void*") => {}
637 (&Type::MutPtr(&Type::PrimFloat(64)), "void*") => {}
416331ca
XL
638 (&Type::MutPtr(&Type::PrimSigned(32)), "int*") => {}
639 (&Type::MutPtr(&Type::PrimSigned(32)), "__int32*") => {}
640 (&Type::MutPtr(&Type::PrimSigned(64)), "__int64*") => {}
641 (&Type::MutPtr(&Type::PrimSigned(8)), "char*") => {}
642 (&Type::MutPtr(&Type::PrimUnsigned(16)), "unsigned short*") => {}
643 (&Type::MutPtr(&Type::PrimUnsigned(32)), "unsigned int*") => {}
644 (&Type::MutPtr(&Type::PrimUnsigned(64)), "unsigned __int64*") => {}
645 (&Type::MutPtr(&Type::PrimUnsigned(8)), "void*") => {}
646 (&Type::MutPtr(&Type::M64), "__m64*") => {}
647 (&Type::MutPtr(&Type::M128), "__m128*") => {}
648 (&Type::MutPtr(&Type::M128I), "__m128i*") => {}
649 (&Type::MutPtr(&Type::M128D), "__m128d*") => {}
650 (&Type::MutPtr(&Type::M256), "__m256*") => {}
651 (&Type::MutPtr(&Type::M256I), "__m256i*") => {}
652 (&Type::MutPtr(&Type::M256D), "__m256d*") => {}
653 (&Type::MutPtr(&Type::M512), "__m512*") => {}
654 (&Type::MutPtr(&Type::M512I), "__m512i*") => {}
655 (&Type::MutPtr(&Type::M512D), "__m512d*") => {}
656
657 (&Type::ConstPtr(&Type::PrimFloat(32)), "float const*") => {}
658 (&Type::ConstPtr(&Type::PrimFloat(64)), "double const*") => {}
3dfed10e
XL
659 (&Type::ConstPtr(&Type::PrimFloat(32)), "void const*") => {}
660 (&Type::ConstPtr(&Type::PrimFloat(64)), "void const*") => {}
416331ca
XL
661 (&Type::ConstPtr(&Type::PrimSigned(32)), "int const*") => {}
662 (&Type::ConstPtr(&Type::PrimSigned(32)), "__int32 const*") => {}
663 (&Type::ConstPtr(&Type::PrimSigned(64)), "__int64 const*") => {}
664 (&Type::ConstPtr(&Type::PrimSigned(8)), "char const*") => {}
665 (&Type::ConstPtr(&Type::PrimUnsigned(16)), "unsigned short const*") => {}
666 (&Type::ConstPtr(&Type::PrimUnsigned(32)), "unsigned int const*") => {}
667 (&Type::ConstPtr(&Type::PrimUnsigned(64)), "unsigned __int64 const*") => {}
668 (&Type::ConstPtr(&Type::PrimUnsigned(8)), "void const*") => {}
669 (&Type::ConstPtr(&Type::M64), "__m64 const*") => {}
670 (&Type::ConstPtr(&Type::M128), "__m128 const*") => {}
671 (&Type::ConstPtr(&Type::M128I), "__m128i const*") => {}
672 (&Type::ConstPtr(&Type::M128D), "__m128d const*") => {}
673 (&Type::ConstPtr(&Type::M256), "__m256 const*") => {}
674 (&Type::ConstPtr(&Type::M256I), "__m256i const*") => {}
675 (&Type::ConstPtr(&Type::M256D), "__m256d const*") => {}
676 (&Type::ConstPtr(&Type::M512), "__m512 const*") => {}
677 (&Type::ConstPtr(&Type::M512I), "__m512i const*") => {}
678 (&Type::ConstPtr(&Type::M512D), "__m512d const*") => {}
0731742a 679
f9f354fc 680 (&Type::MMASK8, "__mmask8") => {}
0731742a 681 (&Type::MMASK16, "__mmask16") => {}
3dfed10e 682 (&Type::MM_CMPINT_ENUM, "_MM_CMPINT_ENUM") => {}
1b1a35ee
XL
683 (&Type::MM_MANTISSA_NORM_ENUM, "_MM_MANTISSA_NORM_ENUM") => {}
684 (&Type::MM_MANTISSA_SIGN_ENUM, "_MM_MANTISSA_SIGN_ENUM") => {}
685 (&Type::MM_PERM_ENUM, "_MM_PERM_ENUM") => {}
0731742a 686
0531ce1d
XL
687 // This is a macro (?) in C which seems to mutate its arguments, but
688 // that means that we're taking pointers to arguments in rust
689 // as we're not exposing it as a macro.
416331ca
XL
690 (&Type::MutPtr(&Type::M128), "__m128") if intrinsic == "_MM_TRANSPOSE4_PS" => {}
691
692 // The _rdtsc intrinsic uses a __int64 return type, but this is a bug in
693 // the intrinsics guide: https://github.com/rust-lang/stdarch/issues/559
694 // We have manually fixed the bug by changing the return type to `u64`.
695 (&Type::PrimUnsigned(64), "__int64") if intrinsic == "_rdtsc" => {}
696
697 // The _bittest and _bittest64 intrinsics takes a mutable pointer in the
698 // intrinsics guide even though it never writes through the pointer:
699 (&Type::ConstPtr(&Type::PrimSigned(32)), "__int32*") if intrinsic == "_bittest" => {}
700 (&Type::ConstPtr(&Type::PrimSigned(64)), "__int64*") if intrinsic == "_bittest64" => {}
701 // The _xrstor, _fxrstor, _xrstor64, _fxrstor64 intrinsics take a
702 // mutable pointer in the intrinsics guide even though they never write
703 // through the pointer:
704 (&Type::ConstPtr(&Type::PrimUnsigned(8)), "void*")
705 if intrinsic == "_xrstor"
706 || intrinsic == "_xrstor64"
707 || intrinsic == "_fxrstor"
708 || intrinsic == "_fxrstor64" => {}
0531ce1d
XL
709
710 _ => bail!(
711 "failed to equate: `{}` and {:?} for {}",
712 intel,
713 t,
714 intrinsic
715 ),
716 }
717 Ok(())
718}