1 //! Operands with fixed register encodings.
2 
3 use crate::{AsReg, Size};
4 use alloc::string::String;
5 
6 /// A _fixed_ register.
7 ///
8 /// Some operands are implicit to the instruction and thus use a fixed register
9 /// for execution. Because this assembler is generic over any register type
10 /// (`R`), this wrapper provides a way to record the fixed register encoding we
11 /// expect to use (`E`).
12 ///
13 /// ```
14 /// # use cranelift_assembler_x64::{AsReg, Fixed, gpr};
15 /// # let valid_reg = 0;
16 /// let fixed = Fixed::<u8, { gpr::enc::RAX }>(valid_reg);
17 /// assert_eq!(fixed.enc(), gpr::enc::RAX);
18 /// ```
19 ///
20 /// ```should_panic
21 /// # use cranelift_assembler_x64::{AsReg, Fixed, gpr};
22 /// # let invalid_reg = 42;
23 /// let fixed = Fixed::<u8, { gpr::enc::RAX }>(invalid_reg);
24 /// fixed.enc(); // Will panic because `invalid_reg` does not match `RAX`.
25 /// ```
26 #[derive(Copy, Clone, Debug, PartialEq)]
27 pub struct Fixed<R, const E: u8>(pub R);
28 
29 impl<R, const E: u8> Fixed<R, E> {
30     /// Return the fixed register encoding.
31     ///
32     /// Regardless of what `R` is (e.g., pre-register allocation), we want to be
33     /// able to know what this register should encode as.
expected_enc(&self) -> u834     pub fn expected_enc(&self) -> u8 {
35         E
36     }
37 
38     /// Return the register name at the given `size`.
to_string(&self, size: Option<Size>) -> String where R: AsReg,39     pub fn to_string(&self, size: Option<Size>) -> String
40     where
41         R: AsReg,
42     {
43         self.0.to_string(size)
44     }
45 }
46 
47 impl<R: AsReg, const E: u8> AsReg for Fixed<R, E> {
new(reg: u8) -> Self48     fn new(reg: u8) -> Self {
49         assert!(reg == E);
50         Self(R::new(reg))
51     }
52 
enc(&self) -> u853     fn enc(&self) -> u8 {
54         assert!(self.0.enc() == E);
55         self.0.enc()
56     }
57 }
58 
59 impl<R, const E: u8> AsRef<R> for Fixed<R, E> {
as_ref(&self) -> &R60     fn as_ref(&self) -> &R {
61         &self.0
62     }
63 }
64 
65 impl<R, const E: u8> From<R> for Fixed<R, E> {
from(reg: R) -> Fixed<R, E>66     fn from(reg: R) -> Fixed<R, E> {
67         Fixed(reg)
68     }
69 }
70