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