1use crate::ir::immediates::{Ieee128, IntoBytes, V128Imm};
12use crate::ir::Constant;
13use alloc::collections::BTreeMap;
14use alloc::vec::Vec;
15use core::fmt;
16use core::slice::Iter;
17use core::str::{from_utf8, FromStr};
18use cranelift_entity::EntityRef;
19
20#[cfg(feature = "enable-serde")]
21use serde_derive::{Deserialize, Serialize};
22
23#[derive(Clone, Hash, Eq, PartialEq, Debug, Default, PartialOrd, Ord)]
29#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
30pub struct ConstantData(Vec<u8>);
31
32impl FromIterator<u8> for ConstantData {
33 fn from_iter<T: IntoIterator<Item = u8>>(iter: T) -> Self {
34 let v = iter.into_iter().collect();
35 Self(v)
36 }
37}
38
39impl From<Vec<u8>> for ConstantData {
40 fn from(v: Vec<u8>) -> Self {
41 Self(v)
42 }
43}
44
45impl From<&[u8]> for ConstantData {
46 fn from(v: &[u8]) -> Self {
47 Self(v.to_vec())
48 }
49}
50
51impl From<V128Imm> for ConstantData {
52 fn from(v: V128Imm) -> Self {
53 Self(v.to_vec())
54 }
55}
56
57impl From<Ieee128> for ConstantData {
58 fn from(v: Ieee128) -> Self {
59 Self(v.into_bytes())
60 }
61}
62
63impl TryFrom<&ConstantData> for Ieee128 {
64 type Error = <[u8; 16] as TryFrom<&'static [u8]>>::Error;
65
66 fn try_from(value: &ConstantData) -> Result<Self, Self::Error> {
67 Ok(Ieee128::with_bits(u128::from_le_bytes(
68 value.as_slice().try_into()?,
69 )))
70 }
71}
72
73impl ConstantData {
74 pub fn len(&self) -> usize {
76 self.0.len()
77 }
78
79 pub fn is_empty(&self) -> bool {
81 self.0.is_empty()
82 }
83
84 pub fn as_slice(&self) -> &[u8] {
86 self.0.as_slice()
87 }
88
89 pub fn into_vec(self) -> Vec<u8> {
91 self.0
92 }
93
94 pub fn iter(&self) -> Iter<u8> {
96 self.0.iter()
97 }
98
99 pub fn append(mut self, bytes: impl IntoBytes) -> Self {
101 let mut to_add = bytes.into_bytes();
102 self.0.append(&mut to_add);
103 self
104 }
105
106 pub fn expand_to(mut self, expected_size: usize) -> Self {
109 if self.len() > expected_size {
110 panic!(
111 "The constant data is already expanded beyond {} bytes",
112 expected_size
113 )
114 }
115 self.0.resize(expected_size, 0);
116 self
117 }
118}
119
120impl fmt::Display for ConstantData {
121 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
131 if !self.is_empty() {
132 write!(f, "0x")?;
133 for b in self.0.iter().rev() {
134 write!(f, "{:02x}", b)?;
135 }
136 }
137 Ok(())
138 }
139}
140
141impl FromStr for ConstantData {
142 type Err = &'static str;
143
144 fn from_str(s: &str) -> Result<Self, &'static str> {
152 if s.len() <= 2 || &s[0..2] != "0x" {
153 return Err("Expected a hexadecimal string, e.g. 0x1234");
154 }
155
156 let cleaned: Vec<u8> = s[2..]
158 .as_bytes()
159 .iter()
160 .filter(|&&b| b as char != '_')
161 .cloned()
162 .collect(); if cleaned.is_empty() {
165 Err("Hexadecimal string must have some digits")
166 } else if cleaned.len() % 2 != 0 {
167 Err("Hexadecimal string must have an even number of digits")
168 } else if cleaned.len() > 32 {
169 Err("Hexadecimal string has too many digits to fit in a 128-bit vector")
170 } else {
171 let mut buffer = Vec::with_capacity((s.len() - 2) / 2);
172 for i in (0..cleaned.len()).step_by(2) {
173 let pair = from_utf8(&cleaned[i..i + 2])
174 .or_else(|_| Err("Unable to parse hexadecimal pair as UTF-8"))?;
175 let byte = u8::from_str_radix(pair, 16)
176 .or_else(|_| Err("Unable to parse as hexadecimal"))?;
177 buffer.insert(0, byte);
178 }
179 Ok(Self(buffer))
180 }
181 }
182}
183
184#[derive(Clone, PartialEq, Hash)]
187#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
188pub struct ConstantPool {
189 handles_to_values: BTreeMap<Constant, ConstantData>,
195
196 values_to_handles: BTreeMap<ConstantData, Constant>,
200}
201
202impl ConstantPool {
203 pub fn new() -> Self {
205 Self {
206 handles_to_values: BTreeMap::new(),
207 values_to_handles: BTreeMap::new(),
208 }
209 }
210
211 pub fn clear(&mut self) {
213 self.handles_to_values.clear();
214 self.values_to_handles.clear();
215 }
216
217 pub fn insert(&mut self, constant_value: ConstantData) -> Constant {
221 if let Some(cst) = self.values_to_handles.get(&constant_value) {
222 return *cst;
223 }
224
225 let constant_handle = Constant::new(self.len());
226 self.set(constant_handle, constant_value);
227 constant_handle
228 }
229
230 pub fn get(&self, constant_handle: Constant) -> &ConstantData {
232 assert!(self.handles_to_values.contains_key(&constant_handle));
233 self.handles_to_values.get(&constant_handle).unwrap()
234 }
235
236 pub fn set(&mut self, constant_handle: Constant, constant_value: ConstantData) {
240 let replaced = self
241 .handles_to_values
242 .insert(constant_handle, constant_value.clone());
243 assert!(
244 replaced.is_none(),
245 "attempted to overwrite an existing constant {:?}: {:?} => {:?}",
246 constant_handle,
247 &constant_value,
248 replaced.unwrap()
249 );
250 self.values_to_handles
251 .insert(constant_value, constant_handle);
252 }
253
254 pub fn iter(&self) -> impl Iterator<Item = (&Constant, &ConstantData)> {
256 self.handles_to_values.iter()
257 }
258
259 pub fn entries_mut(&mut self) -> impl Iterator<Item = &mut ConstantData> {
261 self.handles_to_values.values_mut()
262 }
263
264 pub fn len(&self) -> usize {
266 self.handles_to_values.len()
267 }
268
269 pub fn byte_size(&self) -> usize {
271 self.handles_to_values.values().map(|c| c.len()).sum()
272 }
273}
274
275#[cfg(test)]
276mod tests {
277 use super::*;
278 use std::string::ToString;
279
280 #[test]
281 fn empty() {
282 let sut = ConstantPool::new();
283 assert_eq!(sut.len(), 0);
284 }
285
286 #[test]
287 fn insert() {
288 let mut sut = ConstantPool::new();
289 sut.insert(vec![1, 2, 3].into());
290 sut.insert(vec![4, 5, 6].into());
291 assert_eq!(sut.len(), 2);
292 }
293
294 #[test]
295 fn insert_duplicate() {
296 let mut sut = ConstantPool::new();
297 let a = sut.insert(vec![1, 2, 3].into());
298 sut.insert(vec![4, 5, 6].into());
299 let b = sut.insert(vec![1, 2, 3].into());
300 assert_eq!(a, b);
301 }
302
303 #[test]
304 fn clear() {
305 let mut sut = ConstantPool::new();
306 sut.insert(vec![1, 2, 3].into());
307 assert_eq!(sut.len(), 1);
308
309 sut.clear();
310 assert_eq!(sut.len(), 0);
311 }
312
313 #[test]
314 fn iteration_order() {
315 let mut sut = ConstantPool::new();
316 sut.insert(vec![1, 2, 3].into());
317 sut.insert(vec![4, 5, 6].into());
318 sut.insert(vec![1, 2, 3].into());
319 let data = sut.iter().map(|(_, v)| v).collect::<Vec<&ConstantData>>();
320 assert_eq!(data, vec![&vec![1, 2, 3].into(), &vec![4, 5, 6].into()]);
321 }
322
323 #[test]
324 fn get() {
325 let mut sut = ConstantPool::new();
326 let data = vec![1, 2, 3];
327 let handle = sut.insert(data.clone().into());
328 assert_eq!(sut.get(handle), &data.into());
329 }
330
331 #[test]
332 fn set() {
333 let mut sut = ConstantPool::new();
334 let handle = Constant::with_number(42).unwrap();
335 let data = vec![1, 2, 3];
336 sut.set(handle, data.clone().into());
337 assert_eq!(sut.get(handle), &data.into());
338 }
339
340 #[test]
341 #[should_panic]
342 fn disallow_overwriting_constant() {
343 let mut sut = ConstantPool::new();
344 let handle = Constant::with_number(42).unwrap();
345 sut.set(handle, vec![].into());
346 sut.set(handle, vec![1].into());
347 }
348
349 #[test]
350 #[should_panic]
351 fn get_nonexistent_constant() {
352 let sut = ConstantPool::new();
353 let a = Constant::with_number(42).unwrap();
354 sut.get(a); }
356
357 #[test]
358 fn display_constant_data() {
359 assert_eq!(ConstantData::from([0].as_ref()).to_string(), "0x00");
360 assert_eq!(ConstantData::from([42].as_ref()).to_string(), "0x2a");
361 assert_eq!(
362 ConstantData::from([3, 2, 1, 0].as_ref()).to_string(),
363 "0x00010203"
364 );
365 assert_eq!(
366 ConstantData::from(3735928559u32.to_le_bytes().as_ref()).to_string(),
367 "0xdeadbeef"
368 );
369 assert_eq!(
370 ConstantData::from(0x0102030405060708u64.to_le_bytes().as_ref()).to_string(),
371 "0x0102030405060708"
372 );
373 }
374
375 #[test]
376 fn iterate_over_constant_data() {
377 let c = ConstantData::from([1, 2, 3].as_ref());
378 let mut iter = c.iter();
379 assert_eq!(iter.next(), Some(&1));
380 assert_eq!(iter.next(), Some(&2));
381 assert_eq!(iter.next(), Some(&3));
382 assert_eq!(iter.next(), None);
383 }
384
385 #[test]
386 fn add_to_constant_data() {
387 let d = ConstantData::from([1, 2].as_ref());
388 let e = d.append(i16::from(3u8));
389 assert_eq!(e.into_vec(), vec![1, 2, 3, 0])
390 }
391
392 #[test]
393 fn extend_constant_data() {
394 let d = ConstantData::from([1, 2].as_ref());
395 assert_eq!(d.expand_to(4).into_vec(), vec![1, 2, 0, 0])
396 }
397
398 #[test]
399 #[should_panic]
400 fn extend_constant_data_to_invalid_length() {
401 ConstantData::from([1, 2].as_ref()).expand_to(1);
402 }
403
404 #[test]
405 fn parse_constant_data_and_restringify() {
406 fn parse_ok(from: &str, to: &str) {
408 let parsed = from.parse::<ConstantData>().unwrap();
409 assert_eq!(parsed.to_string(), to);
410 }
411
412 fn parse_err(from: &str, error_msg: &str) {
414 let parsed = from.parse::<ConstantData>();
415 assert!(
416 parsed.is_err(),
417 "Expected a parse error but parsing succeeded: {}",
418 from
419 );
420 assert_eq!(parsed.err().unwrap(), error_msg);
421 }
422
423 parse_ok("0x00", "0x00");
424 parse_ok("0x00000042", "0x00000042");
425 parse_ok(
426 "0x0102030405060708090a0b0c0d0e0f00",
427 "0x0102030405060708090a0b0c0d0e0f00",
428 );
429 parse_ok("0x_0000_0043_21", "0x0000004321");
430
431 parse_err("", "Expected a hexadecimal string, e.g. 0x1234");
432 parse_err("0x", "Expected a hexadecimal string, e.g. 0x1234");
433 parse_err(
434 "0x042",
435 "Hexadecimal string must have an even number of digits",
436 );
437 parse_err(
438 "0x00000000000000000000000000000000000000000000000000",
439 "Hexadecimal string has too many digits to fit in a 128-bit vector",
440 );
441 parse_err("0xrstu", "Unable to parse as hexadecimal");
442 parse_err("0x__", "Hexadecimal string must have some digits");
443 }
444
445 #[test]
446 fn verify_stored_bytes_in_constant_data() {
447 assert_eq!("0x01".parse::<ConstantData>().unwrap().into_vec(), [1]);
448 assert_eq!(ConstantData::from([1, 0].as_ref()).0, [1, 0]);
449 assert_eq!(ConstantData::from(vec![1, 0, 0, 0]).0, [1, 0, 0, 0]);
450 }
451
452 #[test]
453 fn check_constant_data_endianness_as_uimm128() {
454 fn parse_to_uimm128(from: &str) -> Vec<u8> {
455 from.parse::<ConstantData>()
456 .unwrap()
457 .expand_to(16)
458 .into_vec()
459 }
460
461 assert_eq!(
462 parse_to_uimm128("0x42"),
463 [0x42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
464 );
465 assert_eq!(
466 parse_to_uimm128("0x00"),
467 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
468 );
469 assert_eq!(
470 parse_to_uimm128("0x12345678"),
471 [0x78, 0x56, 0x34, 0x12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
472 );
473 assert_eq!(
474 parse_to_uimm128("0x1234_5678"),
475 [0x78, 0x56, 0x34, 0x12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
476 );
477 }
478
479 #[test]
480 fn constant_ieee128() {
481 let value = Ieee128::with_bits(0x000102030405060708090a0b0c0d0e0f);
482 let constant = ConstantData::from(value);
483 assert_eq!(
484 constant.as_slice(),
485 &[0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0]
486 );
487 assert_eq!(Ieee128::try_from(&constant).unwrap().bits(), value.bits());
488 }
489}