1 //! Contains traits that a user of this assembler must implement.
2 
3 use crate::gpr;
4 use crate::xmm;
5 use crate::{Amode, GprMem, XmmMem};
6 use std::fmt;
7 use std::{num::NonZeroU8, ops::Index, vec::Vec};
8 
9 /// Describe how an instruction is emitted into a code buffer.
10 pub trait CodeSink {
11     /// Add 1 byte to the code section.
12     fn put1(&mut self, _: u8);
13 
14     /// Add 2 bytes to the code section.
15     fn put2(&mut self, _: u16);
16 
17     /// Add 4 bytes to the code section.
18     fn put4(&mut self, _: u32);
19 
20     /// Add 8 bytes to the code section.
21     fn put8(&mut self, _: u64);
22 
23     /// Inform the code buffer of a possible trap at the current location;
24     /// required for assembling memory accesses.
25     fn add_trap(&mut self, code: TrapCode);
26 
27     /// Return the byte offset of the current location in the code buffer;
28     /// required for assembling RIP-relative memory accesses.
29     fn current_offset(&self) -> u32;
30 
31     /// Inform the code buffer of a use of `label` at `offset`; required for
32     /// assembling RIP-relative memory accesses.
33     fn use_label_at_offset(&mut self, offset: u32, label: Label);
34 
35     /// Return the label for a constant `id`; required for assembling
36     /// RIP-relative memory accesses of constants.
37     fn get_label_for_constant(&mut self, id: Constant) -> Label;
38 }
39 
40 /// Provide a convenient implementation for testing.
41 impl CodeSink for Vec<u8> {
42     fn put1(&mut self, v: u8) {
43         self.extend_from_slice(&[v]);
44     }
45 
46     fn put2(&mut self, v: u16) {
47         self.extend_from_slice(&v.to_le_bytes());
48     }
49 
50     fn put4(&mut self, v: u32) {
51         self.extend_from_slice(&v.to_le_bytes());
52     }
53 
54     fn put8(&mut self, v: u64) {
55         self.extend_from_slice(&v.to_le_bytes());
56     }
57 
58     fn add_trap(&mut self, _: TrapCode) {}
59 
60     fn current_offset(&self) -> u32 {
61         self.len().try_into().unwrap()
62     }
63 
64     fn use_label_at_offset(&mut self, _: u32, _: Label) {}
65 
66     fn get_label_for_constant(&mut self, c: Constant) -> Label {
67         Label(c.0)
68     }
69 }
70 
71 /// Wrap [`CodeSink`]-specific labels.
72 #[derive(Debug, Copy, Clone)]
73 #[cfg_attr(any(test, feature = "fuzz"), derive(arbitrary::Arbitrary))]
74 pub struct Label(pub u32);
75 
76 /// Wrap [`CodeSink`]-specific constant keys.
77 #[derive(Debug, Copy, Clone)]
78 #[cfg_attr(any(test, feature = "fuzz"), derive(arbitrary::Arbitrary))]
79 pub struct Constant(pub u32);
80 
81 /// Wrap [`CodeSink`]-specific trap codes.
82 #[derive(Debug, Clone, Copy)]
83 #[cfg_attr(any(test, feature = "fuzz"), derive(arbitrary::Arbitrary))]
84 pub struct TrapCode(pub NonZeroU8);
85 
86 impl fmt::Display for TrapCode {
87     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
88         write!(f, "trap={}", self.0)
89     }
90 }
91 
92 /// A table mapping `KnownOffset` identifiers to their `i32` offset values.
93 ///
94 /// When encoding instructions, Cranelift may not know all of the information
95 /// needed to construct an immediate. Specifically, addressing modes that
96 /// require knowing the size of the tail arguments or outgoing arguments (see
97 /// `SyntheticAmode::finalize`) will not know these sizes until emission.
98 ///
99 /// This table allows up to do a "late" look up of these values by their
100 /// `KnownOffset`.
101 pub trait KnownOffsetTable: Index<usize, Output = i32> {}
102 impl KnownOffsetTable for Vec<i32> {}
103 /// Provide a convenient implementation for testing.
104 impl KnownOffsetTable for [i32; 2] {}
105 
106 /// A `KnownOffset` is a unique identifier for a specific offset known only at
107 /// emission time.
108 pub type KnownOffset = u8;
109 
110 /// A type set fixing the register types used in the assembler.
111 ///
112 /// This assembler is parameterizable over register types; this allows the
113 /// assembler users (e.g., Cranelift) to define their own register types
114 /// independent of this crate.
115 pub trait Registers {
116     /// An x64 general purpose register that may be read.
117     type ReadGpr: AsReg;
118 
119     /// An x64 general purpose register that may be read and written.
120     type ReadWriteGpr: AsReg;
121 
122     /// An x64 general purpose register that may be written.
123     type WriteGpr: AsReg;
124 
125     /// An x64 SSE register that may be read.
126     type ReadXmm: AsReg;
127 
128     /// An x64 SSE register that may be read and written.
129     type ReadWriteXmm: AsReg;
130 
131     /// An x64 SSE register that may be written.
132     type WriteXmm: AsReg;
133 }
134 
135 /// Describe how to interact with an external register type.
136 pub trait AsReg: Copy + Clone + std::fmt::Debug + PartialEq {
137     /// Create a register from its hardware encoding.
138     ///
139     /// This is primarily useful for fuzzing, though it is also useful for
140     /// generating fixed registers.
141     fn new(enc: u8) -> Self;
142 
143     /// Return the register's hardware encoding; e.g., `0` for `%rax`.
144     fn enc(&self) -> u8;
145 
146     /// Return the register name.
147     fn to_string(&self, size: Option<gpr::Size>) -> String {
148         match size {
149             Some(size) => gpr::enc::to_string(self.enc(), size).into(),
150             None => xmm::enc::to_string(self.enc()).into(),
151         }
152     }
153 }
154 
155 /// Provide a convenient implementation for testing.
156 impl AsReg for u8 {
157     fn new(enc: u8) -> Self {
158         enc
159     }
160     fn enc(&self) -> u8 {
161         *self
162     }
163 }
164 
165 /// Describe a visitor for the register operands of an instruction.
166 ///
167 /// Due to how Cranelift's register allocation works, we allow the visitor to
168 /// modify the register operands in place. This allows Cranelift to convert
169 /// virtual registers (`[128..N)`) to physical registers (`[0..16)`) without
170 /// re-allocating the entire instruction object.
171 pub trait RegisterVisitor<R: Registers> {
172     /// Visit a read-only register.
173     fn read_gpr(&mut self, reg: &mut R::ReadGpr);
174     /// Visit a read-write register.
175     fn read_write_gpr(&mut self, reg: &mut R::ReadWriteGpr);
176     /// Visit a write-only register.
177     fn write_gpr(&mut self, reg: &mut R::WriteGpr);
178 
179     /// Visit a read-only fixed register; this register can be modified in-place
180     /// but must emit as the hardware encoding `enc`.
181     fn fixed_read_gpr(&mut self, reg: &mut R::ReadGpr, enc: u8);
182     /// Visit a read-write fixed register; this register can be modified
183     /// in-place but must emit as the hardware encoding `enc`.
184     fn fixed_read_write_gpr(&mut self, reg: &mut R::ReadWriteGpr, enc: u8);
185     /// Visit a write-only fixed register; this register can be modified
186     /// in-place but must emit as the hardware encoding `enc`.
187     fn fixed_write_gpr(&mut self, reg: &mut R::WriteGpr, enc: u8);
188 
189     /// Visit a read-only SSE register.
190     fn read_xmm(&mut self, reg: &mut R::ReadXmm);
191     /// Visit a read-write SSE register.
192     fn read_write_xmm(&mut self, reg: &mut R::ReadWriteXmm);
193     /// Visit a write-only SSE register.
194     fn write_xmm(&mut self, reg: &mut R::WriteXmm);
195 
196     /// Visit a read-only fixed SSE register; this register can be modified
197     /// in-place but must emit as the hardware encoding `enc`.
198     fn fixed_read_xmm(&mut self, reg: &mut R::ReadXmm, enc: u8);
199     /// Visit a read-write fixed SSE register; this register can be modified
200     /// in-place but must emit as the hardware encoding `enc`.
201     fn fixed_read_write_xmm(&mut self, reg: &mut R::ReadWriteXmm, enc: u8);
202     /// Visit a read-only fixed SSE register; this register can be modified
203     /// in-place but must emit as the hardware encoding `enc`.
204     fn fixed_write_xmm(&mut self, reg: &mut R::WriteXmm, enc: u8);
205 
206     /// Visit the registers in an [`Amode`].
207     ///
208     /// This is helpful for generated code: it allows capturing the `R::ReadGpr`
209     /// type (which an `Amode` method cannot) and simplifies the code to be
210     /// generated.
211     fn read_amode(&mut self, amode: &mut Amode<R::ReadGpr>) {
212         match amode {
213             Amode::ImmReg { base, .. } => {
214                 self.read_gpr(base);
215             }
216             Amode::ImmRegRegShift { base, index, .. } => {
217                 self.read_gpr(base);
218                 self.read_gpr(index.as_mut());
219             }
220             Amode::RipRelative { .. } => {}
221         }
222     }
223 
224     /// Helper method to handle a read/write [`GprMem`] operand.
225     fn read_write_gpr_mem(&mut self, op: &mut GprMem<R::ReadWriteGpr, R::ReadGpr>) {
226         match op {
227             GprMem::Gpr(r) => self.read_write_gpr(r),
228             GprMem::Mem(m) => self.read_amode(m),
229         }
230     }
231 
232     /// Helper method to handle a write [`GprMem`] operand.
233     fn write_gpr_mem(&mut self, op: &mut GprMem<R::WriteGpr, R::ReadGpr>) {
234         match op {
235             GprMem::Gpr(r) => self.write_gpr(r),
236             GprMem::Mem(m) => self.read_amode(m),
237         }
238     }
239 
240     /// Helper method to handle a read-only [`GprMem`] operand.
241     fn read_gpr_mem(&mut self, op: &mut GprMem<R::ReadGpr, R::ReadGpr>) {
242         match op {
243             GprMem::Gpr(r) => self.read_gpr(r),
244             GprMem::Mem(m) => self.read_amode(m),
245         }
246     }
247 
248     /// Helper method to handle a read-only [`XmmMem`] operand.
249     fn read_xmm_mem(&mut self, op: &mut XmmMem<R::ReadXmm, R::ReadGpr>) {
250         match op {
251             XmmMem::Xmm(r) => self.read_xmm(r),
252             XmmMem::Mem(m) => self.read_amode(m),
253         }
254     }
255 
256     /// Helper method to handle a write [`XmmMem`] operand.
257     fn write_xmm_mem(&mut self, op: &mut XmmMem<R::WriteXmm, R::ReadGpr>) {
258         match op {
259             XmmMem::Xmm(r) => self.write_xmm(r),
260             XmmMem::Mem(m) => self.read_amode(m),
261         }
262     }
263 }
264