1*9c3d1028Sbjorn3 //! Defines `DataDescription`. 2747ad3c4Slazypassion 31dc27c93Sbjorn3 use cranelift_codegen::binemit::{Addend, CodeOffset, Reloc}; 4747ad3c4Slazypassion use cranelift_codegen::entity::PrimaryMap; 56e828df6SBenjamin Bouvier use cranelift_codegen::ir; 60b613caaSCarlo Kok use std::borrow::ToOwned; 7747ad3c4Slazypassion use std::boxed::Box; 80b613caaSCarlo Kok use std::string::String; 9747ad3c4Slazypassion use std::vec::Vec; 10747ad3c4Slazypassion 11b23f534cSAfonso Bordado use crate::ModuleRelocTarget; 1290ac295eSAlex Crichton use crate::module::ModuleReloc; 138a9b1a90SBenjamin Bouvier 14747ad3c4Slazypassion /// This specifies how data is to be initialized. 15141af752Sbjorn3 #[derive(Clone, PartialEq, Eq, Debug)] 169ec02f9dSChristopher Serr #[cfg_attr( 179ec02f9dSChristopher Serr feature = "enable-serde", 189ec02f9dSChristopher Serr derive(serde_derive::Serialize, serde_derive::Deserialize) 199ec02f9dSChristopher Serr )] 20747ad3c4Slazypassion pub enum Init { 21747ad3c4Slazypassion /// This indicates that no initialization has been specified yet. 22747ad3c4Slazypassion Uninitialized, 23747ad3c4Slazypassion /// Initialize the data with all zeros. 24747ad3c4Slazypassion Zeros { 25747ad3c4Slazypassion /// The size of the data. 26747ad3c4Slazypassion size: usize, 27747ad3c4Slazypassion }, 28747ad3c4Slazypassion /// Initialize the data with the specified contents. 29747ad3c4Slazypassion Bytes { 30747ad3c4Slazypassion /// The contents, which also implies the size of the data. 31747ad3c4Slazypassion contents: Box<[u8]>, 32747ad3c4Slazypassion }, 33747ad3c4Slazypassion } 34747ad3c4Slazypassion 35747ad3c4Slazypassion impl Init { 36747ad3c4Slazypassion /// Return the size of the data to be initialized. size(&self) -> usize37747ad3c4Slazypassion pub fn size(&self) -> usize { 38747ad3c4Slazypassion match *self { 399f506692SPeter Huene Self::Uninitialized => panic!("data size not initialized yet"), 409f506692SPeter Huene Self::Zeros { size } => size, 419f506692SPeter Huene Self::Bytes { ref contents } => contents.len(), 42747ad3c4Slazypassion } 43747ad3c4Slazypassion } 44747ad3c4Slazypassion } 45747ad3c4Slazypassion 46747ad3c4Slazypassion /// A description of a data object. 4767c85b88Sbjorn3 #[derive(Clone, Debug)] 489ec02f9dSChristopher Serr #[cfg_attr( 499ec02f9dSChristopher Serr feature = "enable-serde", 509ec02f9dSChristopher Serr derive(serde_derive::Serialize, serde_derive::Deserialize) 519ec02f9dSChristopher Serr )] 52747ad3c4Slazypassion pub struct DataDescription { 53747ad3c4Slazypassion /// How the data should be initialized. 54747ad3c4Slazypassion pub init: Init, 55747ad3c4Slazypassion /// External function declarations. 56b23f534cSAfonso Bordado pub function_decls: PrimaryMap<ir::FuncRef, ModuleRelocTarget>, 57747ad3c4Slazypassion /// External data object declarations. 58b23f534cSAfonso Bordado pub data_decls: PrimaryMap<ir::GlobalValue, ModuleRelocTarget>, 59747ad3c4Slazypassion /// Function addresses to write at specified offsets. 60747ad3c4Slazypassion pub function_relocs: Vec<(CodeOffset, ir::FuncRef)>, 61747ad3c4Slazypassion /// Data addresses to write at specified offsets. 62747ad3c4Slazypassion pub data_relocs: Vec<(CodeOffset, ir::GlobalValue, Addend)>, 636b470798SCarlo Kok /// Object file section 640b613caaSCarlo Kok pub custom_segment_section: Option<(String, String)>, 65*9c3d1028Sbjorn3 /// Alignment in bytes. `None` means that the default alignment of the 66*9c3d1028Sbjorn3 /// respective module should be used. 6784c6ec32Sbjorn3 pub align: Option<u64>, 68*9c3d1028Sbjorn3 /// Whether or not to request the linker to preserve this data object even 69*9c3d1028Sbjorn3 /// if not referenced. 70*9c3d1028Sbjorn3 pub used: bool, 71747ad3c4Slazypassion } 72747ad3c4Slazypassion 731dc27c93Sbjorn3 impl DataDescription { 7467c85b88Sbjorn3 /// Allocate a new `DataDescription`. new() -> Self7567c85b88Sbjorn3 pub fn new() -> Self { 7667c85b88Sbjorn3 Self { 7767c85b88Sbjorn3 init: Init::Uninitialized, 7867c85b88Sbjorn3 function_decls: PrimaryMap::new(), 7967c85b88Sbjorn3 data_decls: PrimaryMap::new(), 8067c85b88Sbjorn3 function_relocs: vec![], 8167c85b88Sbjorn3 data_relocs: vec![], 8267c85b88Sbjorn3 custom_segment_section: None, 8367c85b88Sbjorn3 align: None, 84*9c3d1028Sbjorn3 used: false, 8567c85b88Sbjorn3 } 8667c85b88Sbjorn3 } 8767c85b88Sbjorn3 8867c85b88Sbjorn3 /// Clear all data structures in this `DataDescription`. clear(&mut self)8967c85b88Sbjorn3 pub fn clear(&mut self) { 9067c85b88Sbjorn3 self.init = Init::Uninitialized; 9167c85b88Sbjorn3 self.function_decls.clear(); 9267c85b88Sbjorn3 self.data_decls.clear(); 9367c85b88Sbjorn3 self.function_relocs.clear(); 9467c85b88Sbjorn3 self.data_relocs.clear(); 9567c85b88Sbjorn3 self.custom_segment_section = None; 9667c85b88Sbjorn3 self.align = None; 97*9c3d1028Sbjorn3 self.used = false; 9867c85b88Sbjorn3 } 9967c85b88Sbjorn3 10067c85b88Sbjorn3 /// Define a zero-initialized object with the given size. define_zeroinit(&mut self, size: usize)10167c85b88Sbjorn3 pub fn define_zeroinit(&mut self, size: usize) { 10267c85b88Sbjorn3 debug_assert_eq!(self.init, Init::Uninitialized); 10367c85b88Sbjorn3 self.init = Init::Zeros { size }; 10467c85b88Sbjorn3 } 10567c85b88Sbjorn3 10667c85b88Sbjorn3 /// Define an object initialized with the given contents. 10767c85b88Sbjorn3 /// 10867c85b88Sbjorn3 /// TODO: Can we avoid a Box here? define(&mut self, contents: Box<[u8]>)10967c85b88Sbjorn3 pub fn define(&mut self, contents: Box<[u8]>) { 11067c85b88Sbjorn3 debug_assert_eq!(self.init, Init::Uninitialized); 11167c85b88Sbjorn3 self.init = Init::Bytes { contents }; 11267c85b88Sbjorn3 } 11367c85b88Sbjorn3 11467c85b88Sbjorn3 /// Override the segment/section for data, only supported on Object backend set_segment_section(&mut self, seg: &str, sec: &str)11567c85b88Sbjorn3 pub fn set_segment_section(&mut self, seg: &str, sec: &str) { 11667c85b88Sbjorn3 self.custom_segment_section = Some((seg.to_owned(), sec.to_owned())) 11767c85b88Sbjorn3 } 11867c85b88Sbjorn3 11967c85b88Sbjorn3 /// Set the alignment for data. The alignment must be a power of two. set_align(&mut self, align: u64)12067c85b88Sbjorn3 pub fn set_align(&mut self, align: u64) { 12167c85b88Sbjorn3 assert!(align.is_power_of_two()); 12267c85b88Sbjorn3 self.align = Some(align); 12367c85b88Sbjorn3 } 12467c85b88Sbjorn3 125*9c3d1028Sbjorn3 /// Set whether or not the linker should preserve this data object even if 126*9c3d1028Sbjorn3 /// not referenced. set_used(&mut self, used: bool)127*9c3d1028Sbjorn3 pub fn set_used(&mut self, used: bool) { 128*9c3d1028Sbjorn3 self.used = used; 129*9c3d1028Sbjorn3 } 130*9c3d1028Sbjorn3 13167c85b88Sbjorn3 /// Declare an external function import. 13267c85b88Sbjorn3 /// 13367c85b88Sbjorn3 /// Users of the `Module` API generally should call 13467c85b88Sbjorn3 /// `Module::declare_func_in_data` instead, as it takes care of generating 13567c85b88Sbjorn3 /// the appropriate `ExternalName`. import_function(&mut self, name: ModuleRelocTarget) -> ir::FuncRef136b23f534cSAfonso Bordado pub fn import_function(&mut self, name: ModuleRelocTarget) -> ir::FuncRef { 13767c85b88Sbjorn3 self.function_decls.push(name) 13867c85b88Sbjorn3 } 13967c85b88Sbjorn3 14067c85b88Sbjorn3 /// Declares a global value import. 14167c85b88Sbjorn3 /// 14267c85b88Sbjorn3 /// TODO: Rename to import_data? 14367c85b88Sbjorn3 /// 14467c85b88Sbjorn3 /// Users of the `Module` API generally should call 14567c85b88Sbjorn3 /// `Module::declare_data_in_data` instead, as it takes care of generating 14667c85b88Sbjorn3 /// the appropriate `ExternalName`. import_global_value(&mut self, name: ModuleRelocTarget) -> ir::GlobalValue147b23f534cSAfonso Bordado pub fn import_global_value(&mut self, name: ModuleRelocTarget) -> ir::GlobalValue { 14867c85b88Sbjorn3 self.data_decls.push(name) 14967c85b88Sbjorn3 } 15067c85b88Sbjorn3 15167c85b88Sbjorn3 /// Write the address of `func` into the data at offset `offset`. write_function_addr(&mut self, offset: CodeOffset, func: ir::FuncRef)15267c85b88Sbjorn3 pub fn write_function_addr(&mut self, offset: CodeOffset, func: ir::FuncRef) { 15367c85b88Sbjorn3 self.function_relocs.push((offset, func)) 15467c85b88Sbjorn3 } 15567c85b88Sbjorn3 15667c85b88Sbjorn3 /// Write the address of `data` into the data at offset `offset`. write_data_addr(&mut self, offset: CodeOffset, data: ir::GlobalValue, addend: Addend)15767c85b88Sbjorn3 pub fn write_data_addr(&mut self, offset: CodeOffset, data: ir::GlobalValue, addend: Addend) { 15867c85b88Sbjorn3 self.data_relocs.push((offset, data, addend)) 15967c85b88Sbjorn3 } 16067c85b88Sbjorn3 1611dc27c93Sbjorn3 /// An iterator over all relocations of the data object. all_relocs<'a>( &'a self, pointer_reloc: Reloc, ) -> impl Iterator<Item = ModuleReloc> + 'a1628a9b1a90SBenjamin Bouvier pub fn all_relocs<'a>( 1638a9b1a90SBenjamin Bouvier &'a self, 1648a9b1a90SBenjamin Bouvier pointer_reloc: Reloc, 1658a9b1a90SBenjamin Bouvier ) -> impl Iterator<Item = ModuleReloc> + 'a { 1661dc27c93Sbjorn3 let func_relocs = self 1671dc27c93Sbjorn3 .function_relocs 1681dc27c93Sbjorn3 .iter() 1698a9b1a90SBenjamin Bouvier .map(move |&(offset, id)| ModuleReloc { 170f0e821b9Sbjorn3 kind: pointer_reloc, 1711dc27c93Sbjorn3 offset, 1721dc27c93Sbjorn3 name: self.function_decls[id].clone(), 1731dc27c93Sbjorn3 addend: 0, 1741dc27c93Sbjorn3 }); 1751dc27c93Sbjorn3 let data_relocs = self 1761dc27c93Sbjorn3 .data_relocs 1771dc27c93Sbjorn3 .iter() 1788a9b1a90SBenjamin Bouvier .map(move |&(offset, id, addend)| ModuleReloc { 179f0e821b9Sbjorn3 kind: pointer_reloc, 1801dc27c93Sbjorn3 offset, 1811dc27c93Sbjorn3 name: self.data_decls[id].clone(), 1821dc27c93Sbjorn3 addend, 1831dc27c93Sbjorn3 }); 1841dc27c93Sbjorn3 func_relocs.chain(data_relocs) 1851dc27c93Sbjorn3 } 1861dc27c93Sbjorn3 } 1871dc27c93Sbjorn3 188747ad3c4Slazypassion #[cfg(test)] 189747ad3c4Slazypassion mod tests { 190b23f534cSAfonso Bordado use crate::ModuleRelocTarget; 1918a9b1a90SBenjamin Bouvier 19267c85b88Sbjorn3 use super::{DataDescription, Init}; 193747ad3c4Slazypassion 194747ad3c4Slazypassion #[test] basic_data_context()195747ad3c4Slazypassion fn basic_data_context() { 19667c85b88Sbjorn3 let mut data = DataDescription::new(); 19767c85b88Sbjorn3 assert_eq!(data.init, Init::Uninitialized); 19867c85b88Sbjorn3 assert!(data.function_decls.is_empty()); 19967c85b88Sbjorn3 assert!(data.data_decls.is_empty()); 20067c85b88Sbjorn3 assert!(data.function_relocs.is_empty()); 20167c85b88Sbjorn3 assert!(data.data_relocs.is_empty()); 202747ad3c4Slazypassion 20367c85b88Sbjorn3 data.define_zeroinit(256); 204747ad3c4Slazypassion 205b23f534cSAfonso Bordado let _func_a = data.import_function(ModuleRelocTarget::user(0, 0)); 206b23f534cSAfonso Bordado let func_b = data.import_function(ModuleRelocTarget::user(0, 1)); 207b23f534cSAfonso Bordado let func_c = data.import_function(ModuleRelocTarget::user(0, 2)); 208b23f534cSAfonso Bordado let _data_a = data.import_global_value(ModuleRelocTarget::user(0, 3)); 209b23f534cSAfonso Bordado let data_b = data.import_global_value(ModuleRelocTarget::user(0, 4)); 210747ad3c4Slazypassion 21167c85b88Sbjorn3 data.write_function_addr(8, func_b); 21267c85b88Sbjorn3 data.write_function_addr(16, func_c); 21367c85b88Sbjorn3 data.write_data_addr(32, data_b, 27); 214747ad3c4Slazypassion 21567c85b88Sbjorn3 assert_eq!(data.init, Init::Zeros { size: 256 }); 21667c85b88Sbjorn3 assert_eq!(data.function_decls.len(), 3); 21767c85b88Sbjorn3 assert_eq!(data.data_decls.len(), 2); 21867c85b88Sbjorn3 assert_eq!(data.function_relocs.len(), 2); 21967c85b88Sbjorn3 assert_eq!(data.data_relocs.len(), 1); 220747ad3c4Slazypassion 22167c85b88Sbjorn3 data.clear(); 22267c85b88Sbjorn3 22367c85b88Sbjorn3 assert_eq!(data.init, Init::Uninitialized); 22467c85b88Sbjorn3 assert!(data.function_decls.is_empty()); 22567c85b88Sbjorn3 assert!(data.data_decls.is_empty()); 22667c85b88Sbjorn3 assert!(data.function_relocs.is_empty()); 22767c85b88Sbjorn3 assert!(data.data_relocs.is_empty()); 228747ad3c4Slazypassion 229747ad3c4Slazypassion let contents = vec![33, 34, 35, 36]; 230747ad3c4Slazypassion let contents_clone = contents.clone(); 23167c85b88Sbjorn3 data.define(contents.into_boxed_slice()); 23267c85b88Sbjorn3 233747ad3c4Slazypassion assert_eq!( 23467c85b88Sbjorn3 data.init, 235747ad3c4Slazypassion Init::Bytes { 236747ad3c4Slazypassion contents: contents_clone.into_boxed_slice() 237747ad3c4Slazypassion } 238747ad3c4Slazypassion ); 23967c85b88Sbjorn3 assert_eq!(data.function_decls.len(), 0); 24067c85b88Sbjorn3 assert_eq!(data.data_decls.len(), 0); 24167c85b88Sbjorn3 assert_eq!(data.function_relocs.len(), 0); 24267c85b88Sbjorn3 assert_eq!(data.data_relocs.len(), 0); 243747ad3c4Slazypassion } 244747ad3c4Slazypassion } 245