1 //! An ISA-independent constant pool.
2 
3 use cranelift_codegen::{
4     MachBuffer, VCodeConstant, VCodeConstantData, VCodeConstants, VCodeInst, ir,
5 };
6 
7 pub(crate) struct ConstantPool {
8     inner: ir::ConstantPool,
9     constants: VCodeConstants,
10 }
11 
12 impl ConstantPool {
new() -> Self13     pub fn new() -> Self {
14         Self {
15             inner: ir::ConstantPool::new(),
16             constants: Default::default(),
17         }
18     }
19 
20     /// Register a constant and return a handle, ready for emission.
register<I: VCodeInst>( &mut self, data: &[u8], buffer: &mut MachBuffer<I>, ) -> VCodeConstant21     pub fn register<I: VCodeInst>(
22         &mut self,
23         data: &[u8],
24         buffer: &mut MachBuffer<I>,
25     ) -> VCodeConstant {
26         let constant_handle = self.inner.insert(data.into());
27         let constant_data = self.inner.get(constant_handle);
28 
29         // NB: The insertion will only happen if the pool doesn't already use the constant data.
30         // The reason why the order of operations is apparently inversed is to be sure to insert
31         // the `VCodeConstantData` in the `MachBuffer` only once, as no deduplication happens at
32         // such layer.
33         let vcode_constant_data = VCodeConstantData::Pool(constant_handle, constant_data.clone());
34         let must_register = !self.constants.pool_uses(&vcode_constant_data);
35         let vcode_constant = self.constants.insert(VCodeConstantData::Pool(
36             constant_handle,
37             constant_data.clone(),
38         ));
39 
40         if must_register {
41             buffer.register_constant(&vcode_constant, &vcode_constant_data);
42         }
43         vcode_constant
44     }
45 
46     /// Get the finalized constants.
constants(self) -> VCodeConstants47     pub fn constants(self) -> VCodeConstants {
48         self.constants
49     }
50 }
51