diff options
Diffstat (limited to 'compiler/rustc_codegen_ssa/src/back/lto.rs')
-rw-r--r-- | compiler/rustc_codegen_ssa/src/back/lto.rs | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/compiler/rustc_codegen_ssa/src/back/lto.rs b/compiler/rustc_codegen_ssa/src/back/lto.rs new file mode 100644 index 000000000..cb6244050 --- /dev/null +++ b/compiler/rustc_codegen_ssa/src/back/lto.rs @@ -0,0 +1,104 @@ +use super::write::CodegenContext; +use crate::traits::*; +use crate::ModuleCodegen; + +use rustc_data_structures::memmap::Mmap; +use rustc_errors::FatalError; + +use std::ffi::CString; +use std::sync::Arc; + +pub struct ThinModule<B: WriteBackendMethods> { + pub shared: Arc<ThinShared<B>>, + pub idx: usize, +} + +impl<B: WriteBackendMethods> ThinModule<B> { + pub fn name(&self) -> &str { + self.shared.module_names[self.idx].to_str().unwrap() + } + + pub fn cost(&self) -> u64 { + // Yes, that's correct, we're using the size of the bytecode as an + // indicator for how costly this codegen unit is. + self.data().len() as u64 + } + + pub fn data(&self) -> &[u8] { + let a = self.shared.thin_buffers.get(self.idx).map(|b| b.data()); + a.unwrap_or_else(|| { + let len = self.shared.thin_buffers.len(); + self.shared.serialized_modules[self.idx - len].data() + }) + } +} + +pub struct ThinShared<B: WriteBackendMethods> { + pub data: B::ThinData, + pub thin_buffers: Vec<B::ThinBuffer>, + pub serialized_modules: Vec<SerializedModule<B::ModuleBuffer>>, + pub module_names: Vec<CString>, +} + +pub enum LtoModuleCodegen<B: WriteBackendMethods> { + Fat { + module: ModuleCodegen<B::Module>, + _serialized_bitcode: Vec<SerializedModule<B::ModuleBuffer>>, + }, + + Thin(ThinModule<B>), +} + +impl<B: WriteBackendMethods> LtoModuleCodegen<B> { + pub fn name(&self) -> &str { + match *self { + LtoModuleCodegen::Fat { .. } => "everything", + LtoModuleCodegen::Thin(ref m) => m.name(), + } + } + + /// Optimize this module within the given codegen context. + /// + /// This function is unsafe as it'll return a `ModuleCodegen` still + /// points to LLVM data structures owned by this `LtoModuleCodegen`. + /// It's intended that the module returned is immediately code generated and + /// dropped, and then this LTO module is dropped. + pub unsafe fn optimize( + self, + cgcx: &CodegenContext<B>, + ) -> Result<ModuleCodegen<B::Module>, FatalError> { + match self { + LtoModuleCodegen::Fat { mut module, .. } => { + B::optimize_fat(cgcx, &mut module)?; + Ok(module) + } + LtoModuleCodegen::Thin(thin) => B::optimize_thin(cgcx, thin), + } + } + + /// A "gauge" of how costly it is to optimize this module, used to sort + /// biggest modules first. + pub fn cost(&self) -> u64 { + match *self { + // Only one module with fat LTO, so the cost doesn't matter. + LtoModuleCodegen::Fat { .. } => 0, + LtoModuleCodegen::Thin(ref m) => m.cost(), + } + } +} + +pub enum SerializedModule<M: ModuleBufferMethods> { + Local(M), + FromRlib(Vec<u8>), + FromUncompressedFile(Mmap), +} + +impl<M: ModuleBufferMethods> SerializedModule<M> { + pub fn data(&self) -> &[u8] { + match *self { + SerializedModule::Local(ref m) => m.data(), + SerializedModule::FromRlib(ref m) => m, + SerializedModule::FromUncompressedFile(ref m) => m, + } + } +} |