diff --git a/compiler/rustc_codegen_gcc/src/back/lto.rs b/compiler/rustc_codegen_gcc/src/back/lto.rs index 347a15a392af9..46f097a4bcd16 100644 --- a/compiler/rustc_codegen_gcc/src/back/lto.rs +++ b/compiler/rustc_codegen_gcc/src/back/lto.rs @@ -31,7 +31,6 @@ use rustc_data_structures::memmap::Mmap; use rustc_data_structures::profiling::SelfProfilerRef; use rustc_errors::{DiagCtxt, DiagCtxtHandle}; use rustc_log::tracing::info; -use rustc_session::config::Lto; use tempfile::{TempDir, tempdir}; use crate::back::write::{codegen, save_temp_bitcode}; @@ -45,11 +44,7 @@ struct LtoData { tmp_path: TempDir, } -fn prepare_lto( - cgcx: &CodegenContext, - each_linked_rlib_for_lto: &[PathBuf], - dcx: DiagCtxtHandle<'_>, -) -> LtoData { +fn prepare_lto(each_linked_rlib_for_lto: &[PathBuf], dcx: DiagCtxtHandle<'_>) -> LtoData { let tmp_path = match tempdir() { Ok(tmp_path) => tmp_path, Err(error) => { @@ -64,32 +59,30 @@ fn prepare_lto( // We save off all the bytecode and GCC module file path for later processing // with either fat or thin LTO let mut upstream_modules = Vec::new(); - if cgcx.lto != Lto::ThinLocal { - for path in each_linked_rlib_for_lto { - let archive_data = unsafe { - Mmap::map(File::open(path).expect("couldn't open rlib")).expect("couldn't map rlib") - }; - let archive = ArchiveFile::parse(&*archive_data).expect("wanted an rlib"); - let obj_files = archive - .members() - .filter_map(|child| { - child.ok().and_then(|c| { - std::str::from_utf8(c.name()).ok().map(|name| (name.trim(), c)) - }) - }) - .filter(|&(name, _)| looks_like_rust_object_file(name)); - for (name, child) in obj_files { - info!("adding bitcode from {}", name); - let path = tmp_path.path().join(name); - match save_as_file(child.data(&*archive_data).expect("corrupt rlib"), &path) { - Ok(()) => { - let buffer = ModuleBuffer::new(path); - let module = SerializedModule::Local(buffer); - upstream_modules.push((module, CString::new(name).unwrap())); - } - Err(e) => { - dcx.emit_fatal(e); - } + for path in each_linked_rlib_for_lto { + let archive_data = unsafe { + Mmap::map(File::open(path).expect("couldn't open rlib")).expect("couldn't map rlib") + }; + let archive = ArchiveFile::parse(&*archive_data).expect("wanted an rlib"); + let obj_files = archive + .members() + .filter_map(|child| { + child + .ok() + .and_then(|c| std::str::from_utf8(c.name()).ok().map(|name| (name.trim(), c))) + }) + .filter(|&(name, _)| looks_like_rust_object_file(name)); + for (name, child) in obj_files { + info!("adding bitcode from {}", name); + let path = tmp_path.path().join(name); + match save_as_file(child.data(&*archive_data).expect("corrupt rlib"), &path) { + Ok(()) => { + let buffer = ModuleBuffer::new(path); + let module = SerializedModule::Local(buffer); + upstream_modules.push((module, CString::new(name).unwrap())); + } + Err(e) => { + dcx.emit_fatal(e); } } } @@ -115,7 +108,7 @@ pub(crate) fn run_fat( ) -> CompiledModule { let dcx = DiagCtxt::new(Box::new(shared_emitter.clone())); let dcx = dcx.handle(); - let lto_data = prepare_lto(cgcx, each_linked_rlib_for_lto, dcx); + let lto_data = prepare_lto(each_linked_rlib_for_lto, dcx); /*let symbols_below_threshold = lto_data.symbols_below_threshold.iter().map(|c| c.as_ptr()).collect::>();*/ fat_lto( diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index 592eb68ce2750..b6c0ecff9f9d8 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -81,9 +81,9 @@ use gccjit::{CType, Context, OptimizationLevel}; #[cfg(feature = "master")] use gccjit::{TargetInfo, Version}; use rustc_ast::expand::allocator::AllocatorMethod; -use rustc_codegen_ssa::back::lto::{SerializedModule, ThinModule}; +use rustc_codegen_ssa::back::lto::ThinModule; use rustc_codegen_ssa::back::write::{ - CodegenContext, FatLtoInput, ModuleConfig, SharedEmitter, TargetMachineFactoryFn, + CodegenContext, FatLtoInput, ModuleConfig, SharedEmitter, TargetMachineFactoryFn, ThinLtoInput, }; use rustc_codegen_ssa::base::codegen_crate; use rustc_codegen_ssa::target_features::cfg_target_feature; @@ -449,8 +449,7 @@ impl WriteBackendMethods for GccCodegenBackend { // FIXME(bjorn3): Limit LTO exports to these symbols _exported_symbols_for_lto: &[String], _each_linked_rlib_for_lto: &[PathBuf], - _modules: Vec<(String, Self::ModuleBuffer)>, - _cached_modules: Vec<(SerializedModule, WorkProduct)>, + _modules: Vec>, ) -> (Vec>, Vec) { unreachable!() } diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index f6cd229cb106d..09863961c9d69 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -9,7 +9,7 @@ use object::read::archive::ArchiveFile; use object::{Object, ObjectSection}; use rustc_codegen_ssa::back::lto::{SerializedModule, ThinModule, ThinShared}; use rustc_codegen_ssa::back::write::{ - CodegenContext, FatLtoInput, SharedEmitter, TargetMachineFactoryFn, + CodegenContext, FatLtoInput, SharedEmitter, TargetMachineFactoryFn, ThinLtoInput, }; use rustc_codegen_ssa::traits::*; use rustc_codegen_ssa::{CompiledModule, ModuleCodegen, ModuleKind, looks_like_rust_object_file}; @@ -20,7 +20,7 @@ use rustc_errors::{DiagCtxt, DiagCtxtHandle}; use rustc_hir::attrs::SanitizerSet; use rustc_middle::bug; use rustc_middle::dep_graph::WorkProduct; -use rustc_session::config::{self, Lto}; +use rustc_session::config; use tracing::{debug, info}; use crate::back::write::{ @@ -90,33 +90,31 @@ fn prepare_lto( // We save off all the bytecode and LLVM module ids for later processing // with either fat or thin LTO let mut upstream_modules = Vec::new(); - if cgcx.lto != Lto::ThinLocal { - for path in each_linked_rlib_for_lto { - let archive_data = unsafe { - Mmap::map(std::fs::File::open(&path).expect("couldn't open rlib")) - .expect("couldn't map rlib") - }; - let archive = ArchiveFile::parse(&*archive_data).expect("wanted an rlib"); - let obj_files = archive - .members() - .filter_map(|child| { - child.ok().and_then(|c| { - std::str::from_utf8(c.name()).ok().map(|name| (name.trim(), c)) - }) - }) - .filter(|&(name, _)| looks_like_rust_object_file(name)); - for (name, child) in obj_files { - info!("adding bitcode from {}", name); - match get_bitcode_slice_from_object_data( - child.data(&*archive_data).expect("corrupt rlib"), - cgcx, - ) { - Ok(data) => { - let module = SerializedModule::FromRlib(data.to_vec()); - upstream_modules.push((module, CString::new(name).unwrap())); - } - Err(e) => dcx.emit_fatal(e), + for path in each_linked_rlib_for_lto { + let archive_data = unsafe { + Mmap::map(std::fs::File::open(&path).expect("couldn't open rlib")) + .expect("couldn't map rlib") + }; + let archive = ArchiveFile::parse(&*archive_data).expect("wanted an rlib"); + let obj_files = archive + .members() + .filter_map(|child| { + child + .ok() + .and_then(|c| std::str::from_utf8(c.name()).ok().map(|name| (name.trim(), c))) + }) + .filter(|&(name, _)| looks_like_rust_object_file(name)); + for (name, child) in obj_files { + info!("adding bitcode from {}", name); + match get_bitcode_slice_from_object_data( + child.data(&*archive_data).expect("corrupt rlib"), + cgcx, + ) { + Ok(data) => { + let module = SerializedModule::FromRlib(data.to_vec()); + upstream_modules.push((module, CString::new(name).unwrap())); } + Err(e) => dcx.emit_fatal(e), } } } @@ -187,8 +185,7 @@ pub(crate) fn run_thin( dcx: DiagCtxtHandle<'_>, exported_symbols_for_lto: &[String], each_linked_rlib_for_lto: &[PathBuf], - modules: Vec<(String, ModuleBuffer)>, - cached_modules: Vec<(SerializedModule, WorkProduct)>, + modules: Vec>, ) -> (Vec>, Vec) { let (symbols_below_threshold, upstream_modules) = prepare_lto(cgcx, exported_symbols_for_lto, each_linked_rlib_for_lto, dcx); @@ -200,7 +197,7 @@ pub(crate) fn run_thin( is deferred to the linker" ); } - thin_lto(cgcx, prof, dcx, modules, upstream_modules, cached_modules, &symbols_below_threshold) + thin_lto(cgcx, prof, dcx, modules, upstream_modules, &symbols_below_threshold) } fn fat_lto( @@ -300,7 +297,7 @@ fn fat_lto( // For all serialized bitcode files we parse them and link them in as we did // above, this is all mostly handled in C++. - let mut linker = Linker::new(llmod); + let linker = unsafe { llvm::LLVMRustLinkerNew(llmod) }; for (bc_decoded, name) in serialized_modules { let _timer = prof .generic_activity_with_arg_recorder("LLVM_fat_lto_link_module", |recorder| { @@ -308,11 +305,19 @@ fn fat_lto( }); info!("linking {:?}", name); let data = bc_decoded.data(); - linker - .add(data) - .unwrap_or_else(|()| write::llvm_err(dcx, LlvmError::LoadBitcode { name })); + + unsafe { + if !llvm::LLVMRustLinkerAdd( + linker, + data.as_ptr() as *const libc::c_char, + data.len(), + ) { + llvm::LLVMRustLinkerFree(linker); + write::llvm_err(dcx, LlvmError::LoadBitcode { name }) + } + } } - drop(linker); + unsafe { llvm::LLVMRustLinkerFree(linker) }; save_temp_bitcode(cgcx, &module, "lto.input"); // Internalize everything below threshold to help strip out more modules and such. @@ -330,36 +335,6 @@ fn fat_lto( module } -pub(crate) struct Linker<'a>(&'a mut llvm::Linker<'a>); - -impl<'a> Linker<'a> { - pub(crate) fn new(llmod: &'a llvm::Module) -> Self { - unsafe { Linker(llvm::LLVMRustLinkerNew(llmod)) } - } - - pub(crate) fn add(&mut self, bytecode: &[u8]) -> Result<(), ()> { - unsafe { - if llvm::LLVMRustLinkerAdd( - self.0, - bytecode.as_ptr() as *const libc::c_char, - bytecode.len(), - ) { - Ok(()) - } else { - Err(()) - } - } - } -} - -impl Drop for Linker<'_> { - fn drop(&mut self) { - unsafe { - llvm::LLVMRustLinkerFree(&mut *(self.0 as *mut _)); - } - } -} - /// Prepare "thin" LTO to get run on these modules. /// /// The general structure of ThinLTO is quite different from the structure of @@ -394,24 +369,35 @@ fn thin_lto( cgcx: &CodegenContext, prof: &SelfProfilerRef, dcx: DiagCtxtHandle<'_>, - modules: Vec<(String, ModuleBuffer)>, + modules: Vec>, serialized_modules: Vec<(SerializedModule, CString)>, - cached_modules: Vec<(SerializedModule, WorkProduct)>, symbols_below_threshold: &[*const libc::c_char], ) -> (Vec>, Vec) { let _timer = prof.generic_activity("LLVM_thin_lto_global_analysis"); unsafe { info!("going for that thin, thin LTO"); - let green_modules: FxHashMap<_, _> = - cached_modules.iter().map(|(_, wp)| (wp.cgu_name.clone(), wp.clone())).collect(); + let green_modules: FxHashMap<_, _> = modules + .iter() + .filter_map(|module| { + if let ThinLtoInput::Green { wp, .. } = module { + Some((wp.cgu_name.clone(), wp.clone())) + } else { + None + } + }) + .collect(); - let full_scope_len = modules.len() + serialized_modules.len() + cached_modules.len(); + let full_scope_len = modules.len(); let mut thin_buffers = Vec::with_capacity(modules.len()); let mut module_names = Vec::with_capacity(full_scope_len); let mut thin_modules = Vec::with_capacity(full_scope_len); - for (i, (name, buffer)) in modules.into_iter().enumerate() { + for (i, module) in modules.into_iter().enumerate() { + let (name, buffer) = match module { + ThinLtoInput::Red { name, buffer } => (name, buffer), + ThinLtoInput::Green { wp, buffer } => (wp.cgu_name, buffer), + }; info!("local module: {} - {}", i, name); let cname = CString::new(name.as_bytes()).unwrap(); thin_modules.push(llvm::ThinLTOModule { @@ -439,19 +425,15 @@ fn thin_lto( // incremental ThinLTO first where we could actually avoid // looking at upstream modules entirely sometimes (the contents, // we must always unconditionally look at the index). - let mut serialized = Vec::with_capacity(serialized_modules.len() + cached_modules.len()); - - let cached_modules = - cached_modules.into_iter().map(|(sm, wp)| (sm, CString::new(wp.cgu_name).unwrap())); - for (module, name) in serialized_modules.into_iter().chain(cached_modules) { - info!("upstream or cached module {:?}", name); + for (module, name) in serialized_modules { + info!("upstream module {:?}", name); thin_modules.push(llvm::ThinLTOModule { identifier: name.as_ptr(), data: module.data().as_ptr(), len: module.data().len(), }); - serialized.push(module); + thin_buffers.push(module); module_names.push(name); } @@ -500,12 +482,7 @@ fn thin_lto( // also put all memory referenced by the C++ data (buffers, ids, etc) // into the arc as well. After this we'll create a thin module // codegen per module in this data. - let shared = Arc::new(ThinShared { - data, - thin_buffers, - serialized_modules: serialized, - module_names, - }); + let shared = Arc::new(ThinShared { data, modules: thin_buffers, module_names }); let mut copy_jobs = vec![]; let mut opt_jobs = vec![]; diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 62bba6c9bfc21..41b10c92e5c02 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -27,10 +27,10 @@ use back::write::{create_informational_target_machine, create_target_machine}; use context::SimpleCx; use llvm_util::target_config; use rustc_ast::expand::allocator::AllocatorMethod; -use rustc_codegen_ssa::back::lto::{SerializedModule, ThinModule}; +use rustc_codegen_ssa::back::lto::ThinModule; use rustc_codegen_ssa::back::write::{ CodegenContext, FatLtoInput, ModuleConfig, SharedEmitter, TargetMachineFactoryConfig, - TargetMachineFactoryFn, + TargetMachineFactoryFn, ThinLtoInput, }; use rustc_codegen_ssa::traits::*; use rustc_codegen_ssa::{CompiledModule, CompiledModules, CrateInfo, ModuleCodegen, TargetConfig}; @@ -165,8 +165,7 @@ impl WriteBackendMethods for LlvmCodegenBackend { dcx: DiagCtxtHandle<'_>, exported_symbols_for_lto: &[String], each_linked_rlib_for_lto: &[PathBuf], - modules: Vec<(String, Self::ModuleBuffer)>, - cached_modules: Vec<(SerializedModule, WorkProduct)>, + modules: Vec>, ) -> (Vec>, Vec) { back::lto::run_thin( cgcx, @@ -175,7 +174,6 @@ impl WriteBackendMethods for LlvmCodegenBackend { exported_symbols_for_lto, each_linked_rlib_for_lto, modules, - cached_modules, ) } fn optimize( diff --git a/compiler/rustc_codegen_ssa/src/back/lto.rs b/compiler/rustc_codegen_ssa/src/back/lto.rs index a2c951c16d28d..cd380abb75e0e 100644 --- a/compiler/rustc_codegen_ssa/src/back/lto.rs +++ b/compiler/rustc_codegen_ssa/src/back/lto.rs @@ -32,18 +32,13 @@ impl ThinModule { } 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() - }) + self.shared.modules[self.idx].data() } } pub struct ThinShared { pub data: B::ThinData, - pub thin_buffers: Vec, - pub serialized_modules: Vec>, + pub modules: Vec>, pub module_names: Vec, } @@ -110,11 +105,9 @@ pub(super) fn exported_symbols_for_lto( // If we're performing LTO for the entire crate graph, then for each of our // upstream dependencies, include their exported symbols. - if tcx.sess.lto() != Lto::ThinLocal { - for &cnum in each_linked_rlib_for_lto { - let _timer = tcx.prof.generic_activity("lto_generate_symbols_below_threshold"); - symbols_below_threshold.extend(copy_symbols(cnum)); - } + for &cnum in each_linked_rlib_for_lto { + let _timer = tcx.prof.generic_activity("lto_generate_symbols_below_threshold"); + symbols_below_threshold.extend(copy_symbols(cnum)); } // Mark allocator shim symbols as exported only if they were generated. diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 3734e273e0b5d..ac716179d2c70 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -360,8 +360,7 @@ fn generate_thin_lto_work( dcx: DiagCtxtHandle<'_>, exported_symbols_for_lto: &[String], each_linked_rlib_for_lto: &[PathBuf], - needs_thin_lto: Vec<(String, B::ModuleBuffer)>, - import_only_modules: Vec<(SerializedModule, WorkProduct)>, + needs_thin_lto: Vec>, ) -> Vec<(ThinLtoWorkItem, u64)> { let _prof_timer = prof.generic_activity("codegen_thin_generate_lto_work"); @@ -372,7 +371,6 @@ fn generate_thin_lto_work( exported_symbols_for_lto, each_linked_rlib_for_lto, needs_thin_lto, - import_only_modules, ); lto_modules .into_iter() @@ -399,16 +397,12 @@ enum MaybeLtoModules { exported_symbols_for_lto: Arc>, each_linked_rlib_file_for_lto: Vec, needs_fat_lto: Vec>, - lto_import_only_modules: - Vec<(SerializedModule<::ModuleBuffer>, WorkProduct)>, }, ThinLto { cgcx: CodegenContext, exported_symbols_for_lto: Arc>, each_linked_rlib_file_for_lto: Vec, - needs_thin_lto: Vec<(String, ::ModuleBuffer)>, - lto_import_only_modules: - Vec<(SerializedModule<::ModuleBuffer>, WorkProduct)>, + needs_thin_lto: Vec>, }, } @@ -604,30 +598,28 @@ pub fn produce_final_output_artifacts( // Clean up unwanted temporary files. // We create the following files by default: - // - #crate#.#module-name#.bc - // - #crate#.#module-name#.o - // - #crate#.crate.metadata.bc - // - #crate#.crate.metadata.o - // - #crate#.o (linked from crate.##.o) - // - #crate#.bc (copied from crate.##.bc) + // - #crate#.#module-name#.rcgu.bc + // - #crate#.#module-name#.rcgu.o + // - #crate#.o (linked from crate.##.rcgu.o) + // - #crate#.bc (copied from crate.##.rcgu.bc) // We may create additional files if requested by the user (through // `-C save-temps` or `--emit=` flags). if !sess.opts.cg.save_temps { - // Remove the temporary .#module-name#.o objects. If the user didn't + // Remove the temporary .#module-name#.rcgu.o objects. If the user didn't // explicitly request bitcode (with --emit=bc), and the bitcode is not // needed for building an rlib, then we must remove .#module-name#.bc as // well. - // Specific rules for keeping .#module-name#.bc: + // Specific rules for keeping .#module-name#.rcgu.bc: // - If the user requested bitcode (`user_wants_bitcode`), and // codegen_units > 1, then keep it. // - If the user requested bitcode but codegen_units == 1, then we - // can toss .#module-name#.bc because we copied it to .bc earlier. + // can toss .#module-name#.rcgu.bc because we copied it to .bc earlier. // - If we're not building an rlib and the user didn't request - // bitcode, then delete .#module-name#.bc. + // bitcode, then delete .#module-name#.rcgu.bc. // If you change how this works, also update back::link::link_rlib, - // where .#module-name#.bc files are (maybe) deleted after making an + // where .#module-name#.rcgu.bc files are (maybe) deleted after making an // rlib. let needs_crate_object = crate_output.outputs.contains_key(&OutputType::Exe); @@ -687,7 +679,6 @@ pub fn produce_final_output_artifacts( // We leave the following files around by default: // - #crate#.o - // - #crate#.crate.metadata.o // - #crate#.bc // These are used in linking steps and will be cleaned up afterward. } @@ -788,6 +779,11 @@ pub enum FatLtoInput { InMemory(ModuleCodegen), } +pub enum ThinLtoInput { + Red { name: String, buffer: SerializedModule }, + Green { wp: WorkProduct, buffer: SerializedModule }, +} + /// Actual LTO type we end up choosing based on multiple factors. pub(crate) enum ComputedLtoType { No, @@ -974,8 +970,7 @@ fn do_fat_lto( tm_factory: TargetMachineFactoryFn, exported_symbols_for_lto: &[String], each_linked_rlib_for_lto: &[PathBuf], - mut needs_fat_lto: Vec>, - import_only_modules: Vec<(SerializedModule, WorkProduct)>, + needs_fat_lto: Vec>, ) -> CompiledModule { let _timer = prof.verbose_generic_activity("LLVM_fatlto"); @@ -984,10 +979,6 @@ fn do_fat_lto( check_lto_allowed(&cgcx, dcx); - for (module, wp) in import_only_modules { - needs_fat_lto.push(FatLtoInput::Serialized { name: wp.cgu_name, buffer: module }) - } - B::optimize_and_codegen_fat_lto( cgcx, prof, @@ -1006,11 +997,7 @@ fn do_thin_lto( tm_factory: TargetMachineFactoryFn, exported_symbols_for_lto: Arc>, each_linked_rlib_for_lto: Vec, - needs_thin_lto: Vec<(String, ::ModuleBuffer)>, - lto_import_only_modules: Vec<( - SerializedModule<::ModuleBuffer>, - WorkProduct, - )>, + needs_thin_lto: Vec>, ) -> Vec { let _timer = prof.verbose_generic_activity("LLVM_thinlto"); @@ -1047,7 +1034,6 @@ fn do_thin_lto( &exported_symbols_for_lto, &each_linked_rlib_for_lto, needs_thin_lto, - lto_import_only_modules, ) { let insertion_index = work_items.binary_search_by_key(&cost, |&(_, cost)| cost).unwrap_or_else(|e| e); @@ -1265,13 +1251,16 @@ fn start_executing_work( let mut each_linked_rlib_for_lto = Vec::new(); let mut each_linked_rlib_file_for_lto = Vec::new(); - drop(link::each_linked_rlib(crate_info, None, &mut |cnum, path| { - if link::ignored_for_lto(sess, crate_info, cnum) { - return; - } - each_linked_rlib_for_lto.push(cnum); - each_linked_rlib_file_for_lto.push(path.to_path_buf()); - })); + if sess.lto() != Lto::No && sess.lto() != Lto::ThinLocal { + drop(link::each_linked_rlib(crate_info, None, &mut |cnum, path| { + if link::ignored_for_lto(sess, crate_info, cnum) { + return; + } + + each_linked_rlib_for_lto.push(cnum); + each_linked_rlib_file_for_lto.push(path.to_path_buf()); + })); + } // Compute the set of symbols we need to retain when doing LTO (if we need to) let exported_symbols_for_lto = @@ -1724,7 +1713,10 @@ fn start_executing_work( } Ok(WorkItemResult::NeedsThinLto(name, thin_buffer)) => { assert!(needs_fat_lto.is_empty()); - needs_thin_lto.push((name, thin_buffer)); + needs_thin_lto.push(ThinLtoInput::Red { + name, + buffer: SerializedModule::Local(thin_buffer), + }); } Err(Some(WorkerFatalError)) => { // Like `CodegenAborted`, wait for remaining work to finish. @@ -1767,17 +1759,24 @@ fn start_executing_work( needs_fat_lto.push(FatLtoInput::InMemory(allocator_module)); } + for (module, wp) in lto_import_only_modules { + needs_fat_lto.push(FatLtoInput::Serialized { name: wp.cgu_name, buffer: module }) + } + return Ok(MaybeLtoModules::FatLto { cgcx, exported_symbols_for_lto, each_linked_rlib_file_for_lto, needs_fat_lto, - lto_import_only_modules, }); } else if !needs_thin_lto.is_empty() || !lto_import_only_modules.is_empty() { assert!(compiled_modules.is_empty()); assert!(needs_fat_lto.is_empty()); + for (buffer, wp) in lto_import_only_modules { + needs_thin_lto.push(ThinLtoInput::Green { wp, buffer }) + } + if cgcx.lto == Lto::ThinLocal { compiled_modules.extend(do_thin_lto::( &cgcx, @@ -1787,12 +1786,14 @@ fn start_executing_work( exported_symbols_for_lto, each_linked_rlib_file_for_lto, needs_thin_lto, - lto_import_only_modules, )); } else { if let Some(allocator_module) = allocator_module.take() { let thin_buffer = B::serialize_module(allocator_module.module_llvm, true); - needs_thin_lto.push((allocator_module.name, thin_buffer)); + needs_thin_lto.push(ThinLtoInput::Red { + name: allocator_module.name, + buffer: SerializedModule::Local(thin_buffer), + }); } return Ok(MaybeLtoModules::ThinLto { @@ -1800,7 +1801,6 @@ fn start_executing_work( exported_symbols_for_lto, each_linked_rlib_file_for_lto, needs_thin_lto, - lto_import_only_modules, }); } } @@ -2174,7 +2174,6 @@ impl OngoingCodegen { exported_symbols_for_lto, each_linked_rlib_file_for_lto, needs_fat_lto, - lto_import_only_modules, } => { let tm_factory = self.backend.target_machine_factory( sess, @@ -2191,7 +2190,6 @@ impl OngoingCodegen { &exported_symbols_for_lto, &each_linked_rlib_file_for_lto, needs_fat_lto, - lto_import_only_modules, )], allocator_module: None, } @@ -2201,7 +2199,6 @@ impl OngoingCodegen { exported_symbols_for_lto, each_linked_rlib_file_for_lto, needs_thin_lto, - lto_import_only_modules, } => { let tm_factory = self.backend.target_machine_factory( sess, @@ -2218,7 +2215,6 @@ impl OngoingCodegen { exported_symbols_for_lto, each_linked_rlib_file_for_lto, needs_thin_lto, - lto_import_only_modules, ), allocator_module: None, } diff --git a/compiler/rustc_codegen_ssa/src/traits/write.rs b/compiler/rustc_codegen_ssa/src/traits/write.rs index 5d2313092fa84..cca6db78e381e 100644 --- a/compiler/rustc_codegen_ssa/src/traits/write.rs +++ b/compiler/rustc_codegen_ssa/src/traits/write.rs @@ -6,9 +6,9 @@ use rustc_errors::DiagCtxtHandle; use rustc_middle::dep_graph::WorkProduct; use rustc_session::{Session, config}; -use crate::back::lto::{SerializedModule, ThinModule}; +use crate::back::lto::ThinModule; use crate::back::write::{ - CodegenContext, FatLtoInput, ModuleConfig, SharedEmitter, TargetMachineFactoryFn, + CodegenContext, FatLtoInput, ModuleConfig, SharedEmitter, TargetMachineFactoryFn, ThinLtoInput, }; use crate::{CompiledModule, ModuleCodegen}; @@ -47,8 +47,7 @@ pub trait WriteBackendMethods: Clone + 'static { dcx: DiagCtxtHandle<'_>, exported_symbols_for_lto: &[String], each_linked_rlib_for_lto: &[PathBuf], - modules: Vec<(String, Self::ModuleBuffer)>, - cached_modules: Vec<(SerializedModule, WorkProduct)>, + modules: Vec>, ) -> (Vec>, Vec); fn optimize( cgcx: &CodegenContext,