1 use super::write::CodegenContext; 2 use crate::traits::*; 3 use crate::ModuleCodegen; 4 5 use rustc_data_structures::memmap::Mmap; 6 use rustc_errors::FatalError; 7 8 use std::ffi::CString; 9 use std::sync::Arc; 10 11 pub struct ThinModule<B: WriteBackendMethods> { 12 pub shared: Arc<ThinShared<B>>, 13 pub idx: usize, 14 } 15 16 impl<B: WriteBackendMethods> ThinModule<B> { name(&self) -> &str17 pub fn name(&self) -> &str { 18 self.shared.module_names[self.idx].to_str().unwrap() 19 } 20 cost(&self) -> u6421 pub fn cost(&self) -> u64 { 22 // Yes, that's correct, we're using the size of the bytecode as an 23 // indicator for how costly this codegen unit is. 24 self.data().len() as u64 25 } 26 data(&self) -> &[u8]27 pub fn data(&self) -> &[u8] { 28 let a = self.shared.thin_buffers.get(self.idx).map(|b| b.data()); 29 a.unwrap_or_else(|| { 30 let len = self.shared.thin_buffers.len(); 31 self.shared.serialized_modules[self.idx - len].data() 32 }) 33 } 34 } 35 36 pub struct ThinShared<B: WriteBackendMethods> { 37 pub data: B::ThinData, 38 pub thin_buffers: Vec<B::ThinBuffer>, 39 pub serialized_modules: Vec<SerializedModule<B::ModuleBuffer>>, 40 pub module_names: Vec<CString>, 41 } 42 43 pub enum LtoModuleCodegen<B: WriteBackendMethods> { 44 Fat { 45 module: ModuleCodegen<B::Module>, 46 _serialized_bitcode: Vec<SerializedModule<B::ModuleBuffer>>, 47 }, 48 49 Thin(ThinModule<B>), 50 } 51 52 impl<B: WriteBackendMethods> LtoModuleCodegen<B> { name(&self) -> &str53 pub fn name(&self) -> &str { 54 match *self { 55 LtoModuleCodegen::Fat { .. } => "everything", 56 LtoModuleCodegen::Thin(ref m) => m.name(), 57 } 58 } 59 60 /// Optimize this module within the given codegen context. 61 /// 62 /// This function is unsafe as it'll return a `ModuleCodegen` still 63 /// points to LLVM data structures owned by this `LtoModuleCodegen`. 64 /// It's intended that the module returned is immediately code generated and 65 /// dropped, and then this LTO module is dropped. optimize( self, cgcx: &CodegenContext<B>, ) -> Result<ModuleCodegen<B::Module>, FatalError>66 pub unsafe fn optimize( 67 self, 68 cgcx: &CodegenContext<B>, 69 ) -> Result<ModuleCodegen<B::Module>, FatalError> { 70 match self { 71 LtoModuleCodegen::Fat { mut module, .. } => { 72 B::optimize_fat(cgcx, &mut module)?; 73 Ok(module) 74 } 75 LtoModuleCodegen::Thin(thin) => B::optimize_thin(cgcx, thin), 76 } 77 } 78 79 /// A "gauge" of how costly it is to optimize this module, used to sort 80 /// biggest modules first. cost(&self) -> u6481 pub fn cost(&self) -> u64 { 82 match *self { 83 // Only one module with fat LTO, so the cost doesn't matter. 84 LtoModuleCodegen::Fat { .. } => 0, 85 LtoModuleCodegen::Thin(ref m) => m.cost(), 86 } 87 } 88 } 89 90 pub enum SerializedModule<M: ModuleBufferMethods> { 91 Local(M), 92 FromRlib(Vec<u8>), 93 FromUncompressedFile(Mmap), 94 } 95 96 impl<M: ModuleBufferMethods> SerializedModule<M> { data(&self) -> &[u8]97 pub fn data(&self) -> &[u8] { 98 match *self { 99 SerializedModule::Local(ref m) => m.data(), 100 SerializedModule::FromRlib(ref m) => m, 101 SerializedModule::FromUncompressedFile(ref m) => m, 102 } 103 } 104 } 105