Skip to main content

asmkit/core/
target.rs

1use super::arch_traits::Arch;
2
3/// X86 ISA extensions that can affect code generation.
4#[repr(u8)]
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6pub enum X86Feature {
7    /// Advanced vector extensions.
8    AVX = 0,
9    /// Advanced vector extensions 2.
10    AVX2,
11    /// AVX-512 foundation.
12    AVX512F,
13    /// AVX-512 byte and word instructions.
14    AVX512BW,
15    /// AVX-512 conflict detection instructions.
16    AVX512CD,
17    /// AVX-512 doubleword and quadword instructions.
18    AVX512DQ,
19    /// AVX-512 vector length extensions.
20    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/// Object format.
45#[repr(u8)]
46#[derive(Debug, Clone, Copy, PartialEq, Eq)]
47pub enum ObjectFormat {
48    /// Unknown or uninitialized object format.
49    Unknown = 0,
50    /// JIT code generation object.
51    JIT,
52    /// Executable and linkable format (ELF).
53    ELF,
54    /// Common object file format.
55    COFF,
56    /// Extended COFF object format.
57    XCOFF,
58    /// Mach object file format.
59    MachO,
60    /// Maximum value of `ObjectFormat`.
61    MaxValue,
62}
63
64/// Platform ABI (application binary interface).
65#[repr(u8)]
66#[derive(Debug, Clone, Copy, PartialEq, Eq)]
67pub enum PlatformABI {
68    /// Unknown or uninitialized environment.
69    Unknown = 0,
70    /// Microsoft ABI.
71    MSVC,
72    /// GNU ABI.
73    GNU,
74    /// Android Environment / ABI.
75    Android,
76    /// Cygwin ABI.
77    Cygwin,
78    /// Darwin ABI.
79    Darwin,
80    /// Maximum value of `PlatformABI`.
81    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    /// Enable or disable PIC (Position independent code).
115    ///
116    /// If enabled code for calls and jumps to symbols will emit near relocations
117    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    /// Enable or disable an x86 ISA extension.
126    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}