diff options
| author | Michael Woerister <michaelwoerister@posteo> | 2018-07-09 17:00:24 +0200 |
|---|---|---|
| committer | Michael Woerister <michaelwoerister@posteo> | 2018-07-11 17:52:57 +0200 |
| commit | 8dc7ddb9763f28b83de7bf3b3025f8042ea9e830 (patch) | |
| tree | b320cb3b1eaede7021c3bfc41504608f492dfc78 /src/librustc_codegen_llvm/back | |
| parent | 9df56ca0eea1a8f5af945df25ce23e276b1d48a7 (diff) | |
Persist ThinLTO import data in incr. comp. session directory.
Diffstat (limited to 'src/librustc_codegen_llvm/back')
| -rw-r--r-- | src/librustc_codegen_llvm/back/lto.rs | 83 |
1 files changed, 81 insertions, 2 deletions
diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs index 28b9d2e7afa..ef03e76f946 100644 --- a/src/librustc_codegen_llvm/back/lto.rs +++ b/src/librustc_codegen_llvm/back/lto.rs @@ -27,10 +27,16 @@ use {ModuleCodegen, ModuleLlvm, ModuleKind, ModuleSource}; use libc; use std::ffi::{CString, CStr}; +use std::fs::File; +use std::io; +use std::mem; +use std::path::Path; use std::ptr; use std::slice; use std::sync::Arc; +pub const THIN_LTO_IMPORTS_INCR_COMP_FILE_NAME: &str = "thin-lto-imports.bin"; + pub fn crate_type_allows_lto(crate_type: config::CrateType) -> bool { match crate_type { config::CrateTypeExecutable | @@ -194,7 +200,7 @@ pub(crate) fn run(cgcx: &CodegenContext, } Lto::Thin | Lto::ThinLocal => { - thin_lto(&diag_handler, modules, upstream_modules, &arr, timeline) + thin_lto(cgcx, &diag_handler, modules, upstream_modules, &arr, timeline) } Lto::No => unreachable!(), } @@ -347,7 +353,8 @@ impl Drop for Linker { /// calculating the *index* for ThinLTO. This index will then be shared amongst /// all of the `LtoModuleCodegen` units returned below and destroyed once /// they all go out of scope. -fn thin_lto(diag_handler: &Handler, +fn thin_lto(cgcx: &CodegenContext, + diag_handler: &Handler, modules: Vec<ModuleCodegen>, serialized_modules: Vec<(SerializedModule, CString)>, symbol_white_list: &[*const libc::c_char], @@ -425,6 +432,18 @@ fn thin_lto(diag_handler: &Handler, let msg = format!("failed to prepare thin LTO context"); return Err(write::llvm_err(&diag_handler, msg)) } + + // Save the ThinLTO import information for incremental compilation. + if let Some(ref incr_comp_session_dir) = cgcx.incr_comp_session_dir { + let path = incr_comp_session_dir.join(THIN_LTO_IMPORTS_INCR_COMP_FILE_NAME); + let imports = ThinLTOImports::from_thin_lto_data(data); + if let Err(err) = imports.save_to_file(&path) { + let msg = format!("Error while writing ThinLTO import data: {}", + err); + return Err(write::llvm_err(&diag_handler, msg)); + } + } + let data = ThinData(data); info!("thin LTO data created"); timeline.record("data"); @@ -787,6 +806,12 @@ pub struct ThinLTOImports { impl ThinLTOImports { + pub fn new_empty() -> ThinLTOImports { + ThinLTOImports { + imports: FxHashMap(), + } + } + /// Load the ThinLTO import map from ThinLTOData. unsafe fn from_thin_lto_data(data: *const llvm::ThinLTOData) -> ThinLTOImports { let raw_data: *const llvm::ThinLTOModuleImports = @@ -842,4 +867,58 @@ impl ThinLTOImports { imports } } + + pub fn save_to_file(&self, path: &Path) -> io::Result<()> { + use std::io::Write; + + let file = File::create(path)?; + let mut writer = io::BufWriter::new(file); + + for (importing_module_name, imported_modules) in &self.imports { + writeln!(writer, "{}", importing_module_name)?; + + for imported_module in imported_modules { + writeln!(writer, " {}", imported_module)?; + } + + writeln!(writer)?; + } + + Ok(()) + } + + pub fn load_from_file(path: &Path) -> io::Result<ThinLTOImports> { + use std::io::BufRead; + + let mut imports = FxHashMap(); + let mut current_module = None; + let mut current_imports = vec![]; + + let file = File::open(path)?; + + for line in io::BufReader::new(file).lines() { + let line = line?; + + if line.is_empty() { + let importing_module = current_module + .take() + .expect("Importing module not set"); + + imports.insert(importing_module, + mem::replace(&mut current_imports, vec![])); + } else if line.starts_with(" ") { + // This is an imported module + assert_ne!(current_module, None); + current_imports.push(line.trim().to_string()); + } else { + // This is the beginning of a new module + assert_eq!(current_module, None); + current_module = Some(line.trim().to_string()); + } + } + + Ok(ThinLTOImports { + imports + }) + } } |
