cranelift_assembler_x64_meta/dsl/
features.rs

1//! A DSL for describing x64 CPU features.
2
3use core::fmt;
4use std::ops::BitOr;
5
6/// A collection of CPU features.
7///
8/// An instruction is valid when _any_ of the features in the collection are
9/// enabled; i.e., the collection is an `OR` expression.
10///
11/// ```
12/// # use cranelift_assembler_x64_meta::dsl::{Features, Feature};
13/// let fs = Feature::_64b | Feature::compat;
14/// assert_eq!(fs.to_string(), "_64b | compat");
15/// ```
16#[derive(PartialEq)]
17pub struct Features(Vec<Feature>);
18
19impl Features {
20    #[must_use]
21    pub fn is_empty(&self) -> bool {
22        self.0.is_empty()
23    }
24
25    pub fn iter(&self) -> impl Iterator<Item = &Feature> {
26        self.0.iter()
27    }
28}
29
30impl fmt::Display for Features {
31    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
32        write!(
33            f,
34            "{}",
35            self.0
36                .iter()
37                .map(ToString::to_string)
38                .collect::<Vec<_>>()
39                .join(" | ")
40        )
41    }
42}
43
44/// A CPU feature.
45///
46/// IA-32e mode is the typical mode of operation for modern 64-bit x86
47/// processors. It consists of two sub-modes:
48/// - __64-bit mode__: uses the full 64-bit address space
49/// - __compatibility mode__: allows use of legacy 32-bit code
50#[derive(Clone, Copy, PartialEq)]
51#[allow(non_camel_case_types, reason = "makes DSL definitions easier to read")]
52pub enum Feature {
53    _64b,
54    compat,
55}
56
57/// List all CPU features.
58///
59/// It is critical that this list contains _all_ variants of the [`Feature`]
60/// `enum`. We use this list here in the `meta` level so that we can accurately
61/// transcribe each variant to an `enum` available in the generated layer above.
62/// If this list is incomplete, we will (fortunately) see compile errors for
63/// generated functions that use the missing variants.
64pub const ALL_FEATURES: &[Feature] = &[Feature::_64b, Feature::compat];
65
66impl fmt::Display for Feature {
67    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
68        match self {
69            Feature::_64b => write!(f, "_64b"),
70            Feature::compat => write!(f, "compat"),
71        }
72    }
73}
74
75impl From<Feature> for Features {
76    fn from(flag: Feature) -> Self {
77        Features(vec![flag])
78    }
79}
80
81impl From<Option<Feature>> for Features {
82    fn from(flag: Option<Feature>) -> Self {
83        Features(flag.into_iter().collect())
84    }
85}
86
87impl BitOr for Feature {
88    type Output = Features;
89    fn bitor(self, rhs: Self) -> Self::Output {
90        Features(vec![self, rhs])
91    }
92}