cranelift_assembler_x64/
gpr.rs

1//! Pure register operands; see [`Gpr`].
2
3use crate::rex::RexFlags;
4use crate::AsReg;
5
6/// A general purpose x64 register (e.g., `%rax`).
7///
8/// This container wraps true register type `R` to allow users to specify their
9/// own; by default this will use `u8`.
10#[derive(Clone, Copy, Debug)]
11pub struct Gpr<R: AsReg = u8>(pub(crate) R);
12
13impl<R: AsReg> Gpr<R> {
14    /// Create a [`Gpr`] that may be real (immediately emit-able in machine
15    /// code) or virtual (waiting for register allocation).
16    pub fn new(reg: R) -> Self {
17        Self(reg)
18    }
19
20    /// Return the register's hardware encoding; the underlying type `R` _must_
21    /// be a real register at this point.
22    ///
23    /// # Panics
24    ///
25    /// Panics if the register is not a valid x64 register.
26    pub fn enc(&self) -> u8 {
27        let enc = self.0.enc();
28        assert!(enc < 16, "invalid register: {enc}");
29        enc
30    }
31
32    /// Return the register name at the given `size`.
33    pub fn to_string(&self, size: Size) -> String {
34        self.0.to_string(Some(size))
35    }
36
37    /// Proxy on the 8-bit REX flag emission; helpful for simplifying generated
38    /// code.
39    pub(crate) fn always_emit_if_8bit_needed(&self, rex: &mut RexFlags) {
40        rex.always_emit_if_8bit_needed(self.enc());
41    }
42}
43
44impl<R: AsReg> AsRef<R> for Gpr<R> {
45    fn as_ref(&self) -> &R {
46        &self.0
47    }
48}
49
50impl<R: AsReg> AsMut<R> for Gpr<R> {
51    fn as_mut(&mut self) -> &mut R {
52        &mut self.0
53    }
54}
55
56/// A single x64 register encoding can access a different number of bits.
57#[derive(Copy, Clone, Debug)]
58pub enum Size {
59    /// An 8-bit access.
60    Byte,
61    /// A 16-bit access.
62    Word,
63    /// A 32-bit access.
64    Doubleword,
65    /// A 64-bit access.
66    Quadword,
67}
68
69/// Like [`Gpr`], but with `%rsp` disallowed.
70///
71/// This is due to avoid special cases of REX encodings, see Intel SDM Vol. 2A,
72/// table 2-5.
73#[derive(Clone, Copy, Debug)]
74pub struct NonRspGpr<R: AsReg>(R);
75
76impl<R: AsReg> NonRspGpr<R> {
77    /// See [`Gpr::new`].
78    pub fn new(reg: R) -> Self {
79        Self(reg)
80    }
81
82    /// See [`Gpr::enc`].
83    ///
84    /// # Panics
85    ///
86    /// Panics if the register is invalid or `%rsp`.
87    pub fn enc(&self) -> u8 {
88        let enc = self.0.enc();
89        assert!(enc < 16, "invalid register: {enc}");
90        assert_ne!(enc, enc::RSP, "invalid register: %rsp");
91        enc
92    }
93}
94
95impl<R: AsReg> AsMut<R> for NonRspGpr<R> {
96    fn as_mut(&mut self) -> &mut R {
97        &mut self.0
98    }
99}
100
101/// Encode x64 registers.
102pub mod enc {
103    use super::Size;
104
105    pub const RAX: u8 = 0;
106    pub const RCX: u8 = 1;
107    pub const RDX: u8 = 2;
108    pub const RBX: u8 = 3;
109    pub const RSP: u8 = 4;
110    pub const RBP: u8 = 5;
111    pub const RSI: u8 = 6;
112    pub const RDI: u8 = 7;
113    pub const R8: u8 = 8;
114    pub const R9: u8 = 9;
115    pub const R10: u8 = 10;
116    pub const R11: u8 = 11;
117    pub const R12: u8 = 12;
118    pub const R13: u8 = 13;
119    pub const R14: u8 = 14;
120    pub const R15: u8 = 15;
121
122    /// Return the name of a GPR encoding (`enc`) at the given `size`.
123    ///
124    /// # Panics
125    ///
126    /// This function will panic if the encoding is not a valid x64 register.
127    pub fn to_string(enc: u8, size: Size) -> &'static str {
128        use Size::{Byte, Doubleword, Quadword, Word};
129        match enc {
130            RAX => match size {
131                Byte => "%al",
132                Word => "%ax",
133                Doubleword => "%eax",
134                Quadword => "%rax",
135            },
136            RBX => match size {
137                Byte => "%bl",
138                Word => "%bx",
139                Doubleword => "%ebx",
140                Quadword => "%rbx",
141            },
142            RCX => match size {
143                Byte => "%cl",
144                Word => "%cx",
145                Doubleword => "%ecx",
146                Quadword => "%rcx",
147            },
148            RDX => match size {
149                Byte => "%dl",
150                Word => "%dx",
151                Doubleword => "%edx",
152                Quadword => "%rdx",
153            },
154            RSI => match size {
155                Byte => "%sil",
156                Word => "%si",
157                Doubleword => "%esi",
158                Quadword => "%rsi",
159            },
160            RDI => match size {
161                Byte => "%dil",
162                Word => "%di",
163                Doubleword => "%edi",
164                Quadword => "%rdi",
165            },
166            RBP => match size {
167                Byte => "%bpl",
168                Word => "%bp",
169                Doubleword => "%ebp",
170                Quadword => "%rbp",
171            },
172            RSP => match size {
173                Byte => "%spl",
174                Word => "%sp",
175                Doubleword => "%esp",
176                Quadword => "%rsp",
177            },
178            R8 => match size {
179                Byte => "%r8b",
180                Word => "%r8w",
181                Doubleword => "%r8d",
182                Quadword => "%r8",
183            },
184            R9 => match size {
185                Byte => "%r9b",
186                Word => "%r9w",
187                Doubleword => "%r9d",
188                Quadword => "%r9",
189            },
190            R10 => match size {
191                Byte => "%r10b",
192                Word => "%r10w",
193                Doubleword => "%r10d",
194                Quadword => "%r10",
195            },
196            R11 => match size {
197                Byte => "%r11b",
198                Word => "%r11w",
199                Doubleword => "%r11d",
200                Quadword => "%r11",
201            },
202            R12 => match size {
203                Byte => "%r12b",
204                Word => "%r12w",
205                Doubleword => "%r12d",
206                Quadword => "%r12",
207            },
208            R13 => match size {
209                Byte => "%r13b",
210                Word => "%r13w",
211                Doubleword => "%r13d",
212                Quadword => "%r13",
213            },
214            R14 => match size {
215                Byte => "%r14b",
216                Word => "%r14w",
217                Doubleword => "%r14d",
218                Quadword => "%r14",
219            },
220            R15 => match size {
221                Byte => "%r15b",
222                Word => "%r15w",
223                Doubleword => "%r15d",
224                Quadword => "%r15",
225            },
226            _ => panic!("%invalid{enc}"),
227        }
228    }
229}