1 //! Data structure for tracking the (possibly multiple) registers that hold one
2 //! SSA `Value`.
3 
4 use regalloc2::{PReg, VReg};
5 
6 use super::{RealReg, Reg, VirtualReg, Writable};
7 use core::fmt::Debug;
8 
9 const VALUE_REGS_PARTS: usize = 2;
10 
11 /// Location at which a `Value` is stored in register(s): the value is located
12 /// in one or more registers, depending on its width. A value may be stored in
13 /// more than one register if the machine has no registers wide enough
14 /// otherwise: for example, on a 32-bit architecture, we may store `I64` values
15 /// in two registers, and `I128` values in four.
16 ///
17 /// By convention, the register parts are kept in machine-endian order here.
18 ///
19 /// N.B.: we cap the capacity of this at four (when any 32-bit target is
20 /// enabled) or two (otherwise), and we use special in-band sentinel `Reg`
21 /// values (`Reg::invalid()`) to avoid the need to carry a separate length. This
22 /// allows the struct to be `Copy` (no heap or drop overhead) and be only 16 or
23 /// 8 bytes, which is important for compiler performance.
24 #[derive(Clone, Copy, PartialEq, Eq)]
25 pub struct ValueRegs<R: Clone + Copy + Debug + PartialEq + Eq + InvalidSentinel> {
26     parts: [R; VALUE_REGS_PARTS],
27 }
28 
29 impl<R: Clone + Copy + Debug + PartialEq + Eq + InvalidSentinel> Debug for ValueRegs<R> {
fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result30     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
31         let mut f = f.debug_tuple("ValueRegs");
32         let mut last_valid = true;
33         for part in self.parts {
34             if part.is_invalid_sentinel() {
35                 last_valid = false;
36             } else {
37                 debug_assert!(last_valid);
38                 f.field(&part);
39             }
40         }
41         f.finish()
42     }
43 }
44 
45 /// A type with an "invalid" sentinel value.
46 pub trait InvalidSentinel: Copy + Eq {
47     /// The invalid sentinel value.
invalid_sentinel() -> Self48     fn invalid_sentinel() -> Self;
49     /// Is this the invalid sentinel?
is_invalid_sentinel(self) -> bool50     fn is_invalid_sentinel(self) -> bool {
51         self == Self::invalid_sentinel()
52     }
53 }
54 impl InvalidSentinel for Reg {
invalid_sentinel() -> Self55     fn invalid_sentinel() -> Self {
56         Reg::from(VReg::invalid())
57     }
58 }
59 impl InvalidSentinel for VirtualReg {
invalid_sentinel() -> Self60     fn invalid_sentinel() -> Self {
61         VirtualReg::from(VReg::invalid())
62     }
63 }
64 impl InvalidSentinel for RealReg {
invalid_sentinel() -> Self65     fn invalid_sentinel() -> Self {
66         RealReg::from(PReg::invalid())
67     }
68 }
69 impl InvalidSentinel for Writable<Reg> {
invalid_sentinel() -> Self70     fn invalid_sentinel() -> Self {
71         Writable::from_reg(Reg::invalid_sentinel())
72     }
73 }
74 
75 impl<R: Clone + Copy + Debug + PartialEq + Eq + InvalidSentinel> ValueRegs<R> {
76     /// Create an invalid Value-in-Reg.
invalid() -> Self77     pub fn invalid() -> Self {
78         ValueRegs {
79             parts: [R::invalid_sentinel(); VALUE_REGS_PARTS],
80         }
81     }
82 
83     /// Is this Value-to-Reg mapping valid?
is_valid(self) -> bool84     pub fn is_valid(self) -> bool {
85         !self.parts[0].is_invalid_sentinel()
86     }
87     /// Is this Value-to-Reg mapping invalid?
is_invalid(self) -> bool88     pub fn is_invalid(self) -> bool {
89         self.parts[0].is_invalid_sentinel()
90     }
91 
92     /// Return the single register used for this value, if any.
only_reg(self) -> Option<R>93     pub fn only_reg(self) -> Option<R> {
94         if self.len() == 1 {
95             Some(self.parts[0])
96         } else {
97             None
98         }
99     }
100 
101     /// Return a slice of the registers storing this value.
regs(&self) -> &[R]102     pub fn regs(&self) -> &[R] {
103         &self.parts[0..self.len()]
104     }
105 
106     /// Return a mutable slice of the registers storing this value.
regs_mut(&mut self) -> &mut [R]107     pub fn regs_mut(&mut self) -> &mut [R] {
108         let len = self.len();
109         &mut self.parts[0..len]
110     }
111 }
112 
113 impl<R: Clone + Copy + Debug + PartialEq + Eq + InvalidSentinel> ValueRegs<R> {
114     /// Create a Value-in-R location for a value stored in one register.
one(reg: R) -> Self115     pub fn one(reg: R) -> Self {
116         ValueRegs {
117             parts: [reg, R::invalid_sentinel()],
118         }
119     }
120     /// Create a Value-in-R location for a value stored in two registers.
two(r1: R, r2: R) -> Self121     pub fn two(r1: R, r2: R) -> Self {
122         ValueRegs { parts: [r1, r2] }
123     }
124 
125     /// Return the number of registers used.
len(self) -> usize126     pub fn len(self) -> usize {
127         // If rustc/LLVM is smart enough, this might even be vectorized...
128         (self.parts[0] != R::invalid_sentinel()) as usize
129             + (self.parts[1] != R::invalid_sentinel()) as usize
130     }
131 
132     /// Map individual registers via a map function.
map<NewR, F>(self, f: F) -> ValueRegs<NewR> where NewR: Clone + Copy + Debug + PartialEq + Eq + InvalidSentinel, F: Fn(R) -> NewR,133     pub fn map<NewR, F>(self, f: F) -> ValueRegs<NewR>
134     where
135         NewR: Clone + Copy + Debug + PartialEq + Eq + InvalidSentinel,
136         F: Fn(R) -> NewR,
137     {
138         ValueRegs {
139             parts: [f(self.parts[0]), f(self.parts[1])],
140         }
141     }
142 }
143 
144 /// Create a writable ValueRegs.
writable_value_regs(regs: ValueRegs<Reg>) -> ValueRegs<Writable<Reg>>145 pub(crate) fn writable_value_regs(regs: ValueRegs<Reg>) -> ValueRegs<Writable<Reg>> {
146     regs.map(|r| Writable::from_reg(r))
147 }
148 
149 /// Strip a writable ValueRegs down to a readonly ValueRegs.
non_writable_value_regs(regs: ValueRegs<Writable<Reg>>) -> ValueRegs<Reg>150 pub(crate) fn non_writable_value_regs(regs: ValueRegs<Writable<Reg>>) -> ValueRegs<Reg> {
151     regs.map(|r| r.to_reg())
152 }
153