1pub trait Feature {
3 fn name(&self) -> &'static str;
5
6 fn required(&self) -> bool;
8
9 fn vector_length(&self) -> usize;
11
12 fn check(&self) -> bool {
14 if self.required() {
15 return true;
16 }
17
18 self.check_volatile()
19 }
20
21 fn check_volatile(&self) -> bool;
23}
24
25#[cfg_attr(not(target_arch = "x86_64"), expect(unused))]
27pub fn iterate<F: FnMut(&dyn Feature)>(mut f: F) {
28 #[cfg(target_arch = "x86_64")]
29 {
30 f(&Avx2);
31 f(&Avx512F);
32 f(&Avx512VL);
33 }
34}
35
36macro_rules! define_x86_feature {
37 ($name:ident, $cpuid_name:ident, $feature:tt) => {
38 #[cfg(target_arch = "x86_64")]
39 cpufeatures::new!($cpuid_name, $feature);
40
41 #[cfg(target_arch = "x86_64")]
42 #[derive(Default)]
43 #[doc = concat!("X86 ", stringify!($feature), " feature.")]
44 pub struct $name;
45
46 #[cfg(target_arch = "x86_64")]
47 impl Feature for $name {
48 fn name(&self) -> &'static str {
49 stringify!($feature)
50 }
51
52 fn required(&self) -> bool {
53 cfg!(target_feature = $feature)
54 }
55
56 fn vector_length(&self) -> usize {
57 32
58 }
59
60 fn check_volatile(&self) -> bool {
61 $cpuid_name::get()
62 }
63 }
64 };
65}
66
67define_x86_feature!(Avx2, cpuid_avx2, "avx2");
68define_x86_feature!(Avx512F, cpuid_avx512f, "avx512f");
69define_x86_feature!(Avx512VL, cpuid_avx512vl, "avx512vl");
70
71#[cfg(test)]
72mod tests {
73 #[cfg_attr(not(target_arch = "x86_64"), expect(unused_imports))]
74 use super::*;
75
76 #[test]
77 #[cfg(target_arch = "x86_64")]
78 fn test_avx2() {
79 if !cfg!(target_feature = "avx2") {
80 assert_eq!(Avx2.check(), std::arch::is_x86_feature_detected!("avx2"));
81 } else {
82 assert!(Avx2.check());
83 }
84 }
85
86 #[test]
87 #[cfg(target_arch = "x86_64")]
88 fn test_avx512f() {
89 if !cfg!(target_feature = "avx512f") {
90 assert_eq!(
91 Avx512F.check(),
92 std::arch::is_x86_feature_detected!("avx512f")
93 );
94 } else {
95 assert!(Avx512F.check());
96 }
97 }
98
99 #[test]
100 #[cfg(target_arch = "x86_64")]
101 fn test_avx512vl() {
102 if !cfg!(target_feature = "avx512vl") {
103 assert_eq!(
104 Avx512VL.check(),
105 std::arch::is_x86_feature_detected!("avx512vl")
106 );
107 } else {
108 assert!(Avx512VL.check());
109 }
110 }
111}