1use std::{collections::BTreeMap, fmt, str::FromStr, sync::Arc};
2
3use cranelift_entity::{entity_impl, EntityRef};
4
5pub trait IntoBytes {
6 fn into_bytes(self) -> Vec<u8>;
7}
8impl IntoBytes for Vec<u8> {
9 #[inline(always)]
10 fn into_bytes(self) -> Vec<u8> {
11 self
12 }
13}
14impl IntoBytes for i8 {
15 #[inline]
16 fn into_bytes(self) -> Vec<u8> {
17 vec![self as u8]
18 }
19}
20impl IntoBytes for i16 {
21 #[inline]
22 fn into_bytes(self) -> Vec<u8> {
23 self.to_le_bytes().to_vec()
24 }
25}
26
27#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
29pub struct Constant(u32);
30entity_impl!(Constant, "const");
31
32#[derive(Debug, Clone, PartialEq, Eq, Default, PartialOrd, Ord, Hash)]
36#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
37pub struct ConstantData(#[cfg_attr(feature = "serde", serde(with = "serde_bytes"))] Vec<u8>);
38impl ConstantData {
39 pub fn len(&self) -> usize {
41 self.0.len()
42 }
43
44 pub fn is_empty(&self) -> bool {
46 self.0.is_empty()
47 }
48
49 pub fn as_slice(&self) -> &[u8] {
51 self.0.as_slice()
52 }
53
54 pub fn append(mut self, bytes: impl IntoBytes) -> Self {
56 let mut bytes = bytes.into_bytes();
57 self.0.append(&mut bytes);
58 self
59 }
60
61 pub fn zext(mut self, expected_size: usize) -> Self {
64 assert!(
65 self.len() <= expected_size,
66 "the constant is already larger than {} bytes",
67 expected_size
68 );
69 self.0.resize(expected_size, 0);
70 self
71 }
72
73 pub fn as_u32(&self) -> Option<u32> {
75 let bytes = self.as_slice();
76 if bytes.len() != 4 {
77 return None;
78 }
79 let bytes = bytes.as_ptr() as *const [u8; 4];
80 Some(u32::from_le_bytes(unsafe { bytes.read() }))
81 }
82}
83impl From<ConstantData> for Vec<u8> {
84 #[inline(always)]
85 fn from(data: ConstantData) -> Self {
86 data.0
87 }
88}
89impl FromIterator<u8> for ConstantData {
90 fn from_iter<T: IntoIterator<Item = u8>>(iter: T) -> Self {
91 Self(iter.into_iter().collect())
92 }
93}
94impl From<Vec<u8>> for ConstantData {
95 fn from(v: Vec<u8>) -> Self {
96 Self(v)
97 }
98}
99impl<const N: usize> From<[u8; N]> for ConstantData {
100 fn from(v: [u8; N]) -> Self {
101 Self(v.to_vec())
102 }
103}
104impl From<&[u8]> for ConstantData {
105 fn from(v: &[u8]) -> Self {
106 Self(v.to_vec())
107 }
108}
109impl fmt::Display for ConstantData {
110 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
114 fmt::LowerHex::fmt(self, f)
115 }
116}
117impl fmt::LowerHex for ConstantData {
118 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
122 if !self.is_empty() {
123 if f.alternate() {
124 f.write_str("0x")?;
125 }
126 for byte in self.0.iter().rev() {
127 write!(f, "{byte:02x}")?;
128 }
129 }
130 Ok(())
131 }
132}
133impl FromStr for ConstantData {
134 type Err = ();
135
136 #[inline]
137 fn from_str(s: &str) -> Result<Self, Self::Err> {
138 Self::from_str_be(s).map_err(|_| ())
139 }
140}
141impl ConstantData {
142 pub fn from_str_be(s: &str) -> Result<Self, &'static str> {
143 const NOT_EVEN: &str = "invalid hex-encoded data: expected an even number of hex digits";
144 const NOT_HEX: &str = "invalid hex-encoded data: contains invalid hex digits";
145
146 let s = s.strip_prefix("0x").unwrap_or(s);
147 let len = s.len();
148 if len % 2 != 0 {
149 return Err(NOT_EVEN);
150 }
151 let pairs = len / 2;
153 let mut data = Vec::with_capacity(pairs);
154 let mut chars = s.chars();
155 while let Some(a) = chars.next() {
156 let a = a.to_digit(16).ok_or(NOT_HEX)?;
157 let b = chars.next().unwrap().to_digit(16).ok_or(NOT_HEX)?;
158 data.push(((a << 4) + b) as u8);
159 }
160
161 Ok(Self(data))
162 }
163
164 pub fn from_str_le(s: &str) -> Result<Self, &'static str> {
165 let mut data = Self::from_str_be(s)?;
166 data.0.reverse();
168 Ok(data)
169 }
170}
171
172#[derive(Default)]
174pub struct ConstantPool {
175 constants: BTreeMap<Constant, Arc<ConstantData>>,
181
182 cache: BTreeMap<Arc<ConstantData>, Constant>,
186}
187impl ConstantPool {
188 pub fn is_empty(&self) -> bool {
190 self.constants.is_empty()
191 }
192
193 pub fn len(&self) -> usize {
195 self.constants.len()
196 }
197
198 pub fn get(&self, id: Constant) -> Arc<ConstantData> {
200 Arc::clone(&self.constants[&id])
201 }
202
203 pub fn get_by_ref(&self, id: Constant) -> &ConstantData {
205 self.constants[&id].as_ref()
206 }
207
208 pub fn contains(&self, data: &ConstantData) -> bool {
210 self.cache.contains_key(data)
211 }
212
213 pub fn insert(&mut self, data: ConstantData) -> Constant {
217 if let Some(cst) = self.cache.get(&data) {
218 return *cst;
219 }
220
221 let data = Arc::new(data);
222 let id = Constant::new(self.len());
223 self.constants.insert(id, Arc::clone(&data));
224 self.cache.insert(data, id);
225 id
226 }
227
228 pub fn insert_arc(&mut self, data: Arc<ConstantData>) -> Constant {
230 if let Some(cst) = self.cache.get(data.as_ref()) {
231 return *cst;
232 }
233
234 let id = Constant::new(self.len());
235 self.constants.insert(id, Arc::clone(&data));
236 self.cache.insert(data, id);
237 id
238 }
239
240 #[inline]
242 pub fn iter(&self) -> impl Iterator<Item = (Constant, Arc<ConstantData>)> + '_ {
243 self.constants.iter().map(|(k, v)| (*k, Arc::clone(v)))
244 }
245}