1use super::arch_traits::Arch;
2
3#[repr(u8)]
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6pub enum X86Feature {
7 AVX = 0,
9 AVX2,
11 AVX512F,
13 AVX512BW,
15 AVX512CD,
17 AVX512DQ,
19 AVX512VL,
21}
22
23impl X86Feature {
24 pub const fn mask(self) -> u64 {
25 1u64 << self as u8
26 }
27}
28
29const DEFAULT_X86_FEATURES: u64 = X86Feature::AVX.mask()
30 | X86Feature::AVX2.mask()
31 | X86Feature::AVX512F.mask()
32 | X86Feature::AVX512BW.mask()
33 | X86Feature::AVX512CD.mask()
34 | X86Feature::AVX512DQ.mask()
35 | X86Feature::AVX512VL.mask();
36
37const fn default_x86_features(arch: Arch) -> u64 {
38 match arch {
39 Arch::X86 | Arch::X64 => DEFAULT_X86_FEATURES,
40 _ => 0,
41 }
42}
43
44#[repr(u8)]
46#[derive(Debug, Clone, Copy, PartialEq, Eq)]
47pub enum ObjectFormat {
48 Unknown = 0,
50 JIT,
52 ELF,
54 COFF,
56 XCOFF,
58 MachO,
60 MaxValue,
62}
63
64#[repr(u8)]
66#[derive(Debug, Clone, Copy, PartialEq, Eq)]
67pub enum PlatformABI {
68 Unknown = 0,
70 MSVC,
72 GNU,
74 Android,
76 Cygwin,
78 Darwin,
80 MaxValue,
82}
83
84#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
85pub struct Environment {
86 arch: Arch,
87 is_pic: bool,
88 x86_features: u64,
89}
90
91impl Default for Environment {
92 fn default() -> Self {
93 Self::host()
94 }
95}
96
97impl Environment {
98 pub const fn new(arch: Arch) -> Self {
99 Self {
100 arch,
101 is_pic: false,
102 x86_features: default_x86_features(arch),
103 }
104 }
105
106 pub const fn host() -> Self {
107 Self {
108 arch: Arch::HOST,
109 is_pic: false,
110 x86_features: default_x86_features(Arch::HOST),
111 }
112 }
113
114 pub fn set_pic(&mut self, value: bool) {
118 self.is_pic = value;
119 }
120
121 pub fn pic(&self) -> bool {
122 self.is_pic
123 }
124
125 pub fn set_x86_feature(&mut self, feature: X86Feature, value: bool) {
127 if value {
128 self.x86_features |= feature.mask();
129 } else {
130 self.x86_features &= !feature.mask();
131 }
132 }
133
134 pub const fn x86_feature(&self, feature: X86Feature) -> bool {
135 (self.x86_features & feature.mask()) != 0
136 }
137
138 pub fn set_avx(&mut self, value: bool) {
139 self.set_x86_feature(X86Feature::AVX, value);
140 }
141
142 pub const fn avx(&self) -> bool {
143 self.x86_feature(X86Feature::AVX)
144 }
145
146 pub fn set_avx2(&mut self, value: bool) {
147 self.set_x86_feature(X86Feature::AVX2, value);
148 }
149
150 pub const fn avx2(&self) -> bool {
151 self.x86_feature(X86Feature::AVX2)
152 }
153
154 pub fn set_avx512f(&mut self, value: bool) {
155 self.set_x86_feature(X86Feature::AVX512F, value);
156 }
157
158 pub const fn avx512f(&self) -> bool {
159 self.x86_feature(X86Feature::AVX512F)
160 }
161
162 pub fn set_avx512bw(&mut self, value: bool) {
163 self.set_x86_feature(X86Feature::AVX512BW, value);
164 }
165
166 pub const fn avx512bw(&self) -> bool {
167 self.x86_feature(X86Feature::AVX512BW)
168 }
169
170 pub fn set_avx512cd(&mut self, value: bool) {
171 self.set_x86_feature(X86Feature::AVX512CD, value);
172 }
173
174 pub const fn avx512cd(&self) -> bool {
175 self.x86_feature(X86Feature::AVX512CD)
176 }
177
178 pub fn set_avx512dq(&mut self, value: bool) {
179 self.set_x86_feature(X86Feature::AVX512DQ, value);
180 }
181
182 pub const fn avx512dq(&self) -> bool {
183 self.x86_feature(X86Feature::AVX512DQ)
184 }
185
186 pub fn set_avx512vl(&mut self, value: bool) {
187 self.set_x86_feature(X86Feature::AVX512VL, value);
188 }
189
190 pub const fn avx512vl(&self) -> bool {
191 self.x86_feature(X86Feature::AVX512VL)
192 }
193
194 pub const fn arch(&self) -> Arch {
195 self.arch
196 }
197}
198
199#[cfg(test)]
200mod tests {
201 use super::{Environment, X86Feature};
202 use crate::core::arch_traits::Arch;
203
204 #[test]
205 fn x86_targets_enable_vector_features_by_default() {
206 let env = Environment::new(Arch::X64);
207
208 assert!(env.avx());
209 assert!(env.avx2());
210 assert!(env.avx512f());
211 assert!(env.avx512bw());
212 assert!(env.avx512cd());
213 assert!(env.avx512dq());
214 assert!(env.avx512vl());
215 }
216
217 #[test]
218 fn non_x86_targets_start_without_x86_features() {
219 let env = Environment::new(Arch::AArch64);
220
221 assert!(!env.x86_feature(X86Feature::AVX));
222 assert!(!env.x86_feature(X86Feature::AVX512F));
223 }
224
225 #[test]
226 fn x86_features_can_be_toggled() {
227 let mut env = Environment::new(Arch::X64);
228
229 env.set_avx(false);
230 env.set_x86_feature(X86Feature::AVX512VL, false);
231
232 assert!(!env.avx());
233 assert!(!env.avx512vl());
234 }
235}