diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs index 99828e5b7fbb..c88f5993889d 100644 --- a/src/librustc_codegen_llvm/back/lto.rs +++ b/src/librustc_codegen_llvm/back/lto.rs @@ -48,18 +48,11 @@ pub fn crate_type_allows_lto(crate_type: config::CrateType) -> bool { } } -/// Performs LTO, which in the case of full LTO means merging all modules into -/// a single one and returning it for further optimizing. For ThinLTO, it will -/// do the global analysis necessary and return two lists, one of the modules -/// the need optimization and another for modules that can simply be copied over -/// from the incr. comp. cache. -pub(crate) fn run(cgcx: &CodegenContext, - modules: Vec>, - cached_modules: Vec<(SerializedModule, WorkProduct)>, - timeline: &mut Timeline) - -> Result<(Vec>, Vec), FatalError> +fn prepare_lto(cgcx: &CodegenContext, + timeline: &mut Timeline, + diag_handler: &Handler) + -> Result<(Vec, Vec<(SerializedModule, CString)>), FatalError> { - let diag_handler = cgcx.create_diag_handler(); let export_threshold = match cgcx.lto { // We're just doing LTO for our one crate Lto::ThinLocal => SymbolExportLevel::Rust, @@ -144,36 +137,56 @@ pub(crate) fn run(cgcx: &CodegenContext, } } + Ok((symbol_white_list, upstream_modules)) +} + +/// Performs fat LTO by merging all modules into a single one and returning it +/// for further optimization. +pub(crate) fn run_fat(cgcx: &CodegenContext, + modules: Vec>, + _cached_modules: Vec<(SerializedModule, WorkProduct)>, + timeline: &mut Timeline) + -> Result<(Vec>, Vec), FatalError> +{ + let diag_handler = cgcx.create_diag_handler(); + let (symbol_white_list, upstream_modules) = prepare_lto(cgcx, timeline, &diag_handler)?; let symbol_white_list = symbol_white_list.iter() .map(|c| c.as_ptr()) .collect::>(); - match cgcx.lto { - Lto::Fat => { - assert!(cached_modules.is_empty()); - let opt_jobs = fat_lto(cgcx, - &diag_handler, - modules, - upstream_modules, - &symbol_white_list, - timeline); - opt_jobs.map(|opt_jobs| (opt_jobs, vec![])) - } - Lto::Thin | - Lto::ThinLocal => { - if cgcx.opts.debugging_opts.cross_lang_lto.enabled() { - unreachable!("We should never reach this case if the LTO step \ - is deferred to the linker"); - } - thin_lto(cgcx, - &diag_handler, - modules, - upstream_modules, - cached_modules, - &symbol_white_list, - timeline) - } - Lto::No => unreachable!(), + let opt_jobs = fat_lto(cgcx, + &diag_handler, + modules, + upstream_modules, + &symbol_white_list, + timeline); + opt_jobs.map(|opt_jobs| (opt_jobs, vec![])) +} + +/// Performs thin LTO by performing necessary global analysis and returning two +/// lists, one of the modules that need optimization and another for modules that +/// can simply be copied over from the incr. comp. cache. +pub(crate) fn run_thin(cgcx: &CodegenContext, + modules: Vec>, + cached_modules: Vec<(SerializedModule, WorkProduct)>, + timeline: &mut Timeline) + -> Result<(Vec>, Vec), FatalError> +{ + let diag_handler = cgcx.create_diag_handler(); + let (symbol_white_list, upstream_modules) = prepare_lto(cgcx, timeline, &diag_handler)?; + let symbol_white_list = symbol_white_list.iter() + .map(|c| c.as_ptr()) + .collect::>(); + if cgcx.opts.debugging_opts.cross_lang_lto.enabled() { + unreachable!("We should never reach this case if the LTO step \ + is deferred to the linker"); } + thin_lto(cgcx, + &diag_handler, + modules, + upstream_modules, + cached_modules, + &symbol_white_list, + timeline) } fn fat_lto(cgcx: &CodegenContext, diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index 4f90cb793b6d..7d941a99e2f2 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -176,13 +176,21 @@ impl WriteBackendMethods for LlvmCodegenBackend { fn print_pass_timings(&self) { unsafe { llvm::LLVMRustPrintPassTimings(); } } - fn run_lto( + fn run_fat_lto( cgcx: &CodegenContext, modules: Vec>, cached_modules: Vec<(SerializedModule, WorkProduct)>, timeline: &mut Timeline ) -> Result<(Vec>, Vec), FatalError> { - back::lto::run(cgcx, modules, cached_modules, timeline) + back::lto::run_fat(cgcx, modules, cached_modules, timeline) + } + fn run_thin_lto( + cgcx: &CodegenContext, + modules: Vec>, + cached_modules: Vec<(SerializedModule, WorkProduct)>, + timeline: &mut Timeline + ) -> Result<(Vec>, Vec), FatalError> { + back::lto::run_thin(cgcx, modules, cached_modules, timeline) } unsafe fn optimize( cgcx: &CodegenContext, diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index aaaaf169f156..5e89265d56f2 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -264,11 +264,11 @@ fn generate_lto_work( let (lto_modules, copy_jobs) = if !needs_fat_lto.is_empty() { assert!(needs_thin_lto.is_empty()); - B::run_lto(cgcx, needs_fat_lto, import_only_modules, &mut timeline) + B::run_fat_lto(cgcx, needs_fat_lto, import_only_modules, &mut timeline) .unwrap_or_else(|e| e.raise()) } else { assert!(needs_fat_lto.is_empty()); - B::run_lto(cgcx, needs_thin_lto, import_only_modules, &mut timeline) + B::run_thin_lto(cgcx, needs_thin_lto, import_only_modules, &mut timeline) .unwrap_or_else(|e| e.raise()) }; diff --git a/src/librustc_codegen_ssa/traits/write.rs b/src/librustc_codegen_ssa/traits/write.rs index 72522e19af21..5bc44dfeeb32 100644 --- a/src/librustc_codegen_ssa/traits/write.rs +++ b/src/librustc_codegen_ssa/traits/write.rs @@ -24,12 +24,18 @@ pub trait WriteBackendMethods: 'static + Sized + Clone { type ThinData: Send + Sync; type ThinBuffer: ThinBufferMethods; - /// Performs LTO, which in the case of full LTO means merging all modules into - /// a single one and returning it for further optimizing. For ThinLTO, it will - /// do the global analysis necessary and return two lists, one of the modules - /// the need optimization and another for modules that can simply be copied over - /// from the incr. comp. cache. - fn run_lto( + /// Performs fat LTO by merging all modules into a single one and returning it + /// for further optimization. + fn run_fat_lto( + cgcx: &CodegenContext, + modules: Vec>, + cached_modules: Vec<(SerializedModule, WorkProduct)>, + timeline: &mut Timeline, + ) -> Result<(Vec>, Vec), FatalError>; + /// Performs thin LTO by performing necessary global analysis and returning two + /// lists, one of the modules that need optimization and another for modules that + /// can simply be copied over from the incr. comp. cache. + fn run_thin_lto( cgcx: &CodegenContext, modules: Vec>, cached_modules: Vec<(SerializedModule, WorkProduct)>,