Remove tm_factory field from CodegenContext

This is necessary to support serializing the CodegenContext to a .rlink
file in the future for moving LTO to the -Zlink-only step.
This commit is contained in:
bjorn3 2026-02-11 11:31:51 +00:00
parent 2d07e81a5c
commit f49223c443
9 changed files with 157 additions and 119 deletions

View file

@ -50,7 +50,7 @@ struct LtoData {
}
fn prepare_lto(
cgcx: &CodegenContext<GccCodegenBackend>,
cgcx: &CodegenContext,
each_linked_rlib_for_lto: &[PathBuf],
dcx: DiagCtxtHandle<'_>,
) -> LtoData {
@ -111,7 +111,7 @@ fn save_as_file(obj: &[u8], path: &Path) -> Result<(), LtoBitcodeFromRlib> {
/// Performs fat LTO by merging all modules into a single one and returning it
/// for further optimization.
pub(crate) fn run_fat(
cgcx: &CodegenContext<GccCodegenBackend>,
cgcx: &CodegenContext,
shared_emitter: &SharedEmitter,
each_linked_rlib_for_lto: &[PathBuf],
modules: Vec<FatLtoInput<GccCodegenBackend>>,
@ -132,7 +132,7 @@ pub(crate) fn run_fat(
}
fn fat_lto(
cgcx: &CodegenContext<GccCodegenBackend>,
cgcx: &CodegenContext,
_dcx: DiagCtxtHandle<'_>,
modules: Vec<FatLtoInput<GccCodegenBackend>>,
mut serialized_modules: Vec<(SerializedModule<ModuleBuffer>, CString)>,
@ -283,7 +283,7 @@ impl ModuleBufferMethods for ModuleBuffer {
/// 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<GccCodegenBackend>,
cgcx: &CodegenContext,
dcx: DiagCtxtHandle<'_>,
each_linked_rlib_for_lto: &[PathBuf],
modules: Vec<(String, ThinBuffer)>,
@ -345,7 +345,7 @@ pub(crate) fn prepare_thin(module: ModuleCodegen<GccContext>) -> (String, ThinBu
/// all of the `LtoModuleCodegen` units returned below and destroyed once
/// they all go out of scope.
fn thin_lto(
cgcx: &CodegenContext<GccCodegenBackend>,
cgcx: &CodegenContext,
_dcx: DiagCtxtHandle<'_>,
modules: Vec<(String, ThinBuffer)>,
serialized_modules: Vec<(SerializedModule<ModuleBuffer>, CString)>,
@ -520,11 +520,9 @@ fn thin_lto(
pub fn optimize_thin_module(
thin_module: ThinModule<GccCodegenBackend>,
_cgcx: &CodegenContext<GccCodegenBackend>,
_cgcx: &CodegenContext,
) -> ModuleCodegen<GccContext> {
//let module_name = &thin_module.shared.module_names[thin_module.idx];
/*let tm_factory_config = TargetMachineFactoryConfig::new(cgcx, module_name.to_str().unwrap());
let tm = (cgcx.tm_factory)(tm_factory_config).map_err(|e| write::llvm_err(&dcx, e))?;*/
// Right now the implementation we've got only works over serialized
// modules, so we create a fresh new LLVM context and parse the module

View file

@ -14,10 +14,10 @@ use rustc_target::spec::SplitDebuginfo;
use crate::base::add_pic_option;
use crate::errors::CopyBitcode;
use crate::{GccCodegenBackend, GccContext, LtoMode};
use crate::{GccContext, LtoMode};
pub(crate) fn codegen(
cgcx: &CodegenContext<GccCodegenBackend>,
cgcx: &CodegenContext,
shared_emitter: &SharedEmitter,
module: ModuleCodegen<GccContext>,
config: &ModuleConfig,
@ -227,7 +227,7 @@ pub(crate) fn codegen(
}
pub(crate) fn save_temp_bitcode(
cgcx: &CodegenContext<GccCodegenBackend>,
cgcx: &CodegenContext,
_module: &ModuleCodegen<GccContext>,
_name: &str,
) {

View file

@ -426,8 +426,9 @@ impl WriteBackendMethods for GccCodegenBackend {
type ThinBuffer = ThinBuffer;
fn run_and_optimize_fat_lto(
cgcx: &CodegenContext<Self>,
cgcx: &CodegenContext,
shared_emitter: &SharedEmitter,
_tm_factory: TargetMachineFactoryFn<Self>,
// FIXME(bjorn3): Limit LTO exports to these symbols
_exported_symbols_for_lto: &[String],
each_linked_rlib_for_lto: &[PathBuf],
@ -437,7 +438,7 @@ impl WriteBackendMethods for GccCodegenBackend {
}
fn run_thin_lto(
cgcx: &CodegenContext<Self>,
cgcx: &CodegenContext,
dcx: DiagCtxtHandle<'_>,
// FIXME(bjorn3): Limit LTO exports to these symbols
_exported_symbols_for_lto: &[String],
@ -457,7 +458,7 @@ impl WriteBackendMethods for GccCodegenBackend {
}
fn optimize(
_cgcx: &CodegenContext<Self>,
_cgcx: &CodegenContext,
_shared_emitter: &SharedEmitter,
module: &mut ModuleCodegen<Self::Module>,
config: &ModuleConfig,
@ -466,15 +467,16 @@ impl WriteBackendMethods for GccCodegenBackend {
}
fn optimize_thin(
cgcx: &CodegenContext<Self>,
cgcx: &CodegenContext,
_shared_emitter: &SharedEmitter,
_tm_factory: TargetMachineFactoryFn<Self>,
thin: ThinModule<Self>,
) -> ModuleCodegen<Self::Module> {
back::lto::optimize_thin_module(thin, cgcx)
}
fn codegen(
cgcx: &CodegenContext<Self>,
cgcx: &CodegenContext,
shared_emitter: &SharedEmitter,
module: ModuleCodegen<Self::Module>,
config: &ModuleConfig,

View file

@ -9,7 +9,9 @@ use std::{io, iter, slice};
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};
use rustc_codegen_ssa::back::write::{
CodegenContext, FatLtoInput, SharedEmitter, TargetMachineFactoryFn,
};
use rustc_codegen_ssa::traits::*;
use rustc_codegen_ssa::{ModuleCodegen, ModuleKind, looks_like_rust_object_file};
use rustc_data_structures::fx::FxHashMap;
@ -33,7 +35,7 @@ use crate::{LlvmCodegenBackend, ModuleLlvm};
const THIN_LTO_KEYS_INCR_COMP_FILE_NAME: &str = "thin-lto-past-keys.bin";
fn prepare_lto(
cgcx: &CodegenContext<LlvmCodegenBackend>,
cgcx: &CodegenContext,
exported_symbols_for_lto: &[String],
each_linked_rlib_for_lto: &[PathBuf],
dcx: DiagCtxtHandle<'_>,
@ -123,7 +125,7 @@ fn prepare_lto(
fn get_bitcode_slice_from_object_data<'a>(
obj: &'a [u8],
cgcx: &CodegenContext<LlvmCodegenBackend>,
cgcx: &CodegenContext,
) -> Result<&'a [u8], LtoBitcodeFromRlib> {
// We're about to assume the data here is an object file with sections, but if it's raw LLVM IR
// that won't work. Fortunately, if that's what we have we can just return the object directly,
@ -149,8 +151,9 @@ fn get_bitcode_slice_from_object_data<'a>(
/// Performs fat LTO by merging all modules into a single one and returning it
/// for further optimization.
pub(crate) fn run_fat(
cgcx: &CodegenContext<LlvmCodegenBackend>,
cgcx: &CodegenContext,
shared_emitter: &SharedEmitter,
tm_factory: TargetMachineFactoryFn<LlvmCodegenBackend>,
exported_symbols_for_lto: &[String],
each_linked_rlib_for_lto: &[PathBuf],
modules: Vec<FatLtoInput<LlvmCodegenBackend>>,
@ -161,14 +164,22 @@ pub(crate) fn run_fat(
prepare_lto(cgcx, exported_symbols_for_lto, each_linked_rlib_for_lto, dcx);
let symbols_below_threshold =
symbols_below_threshold.iter().map(|c| c.as_ptr()).collect::<Vec<_>>();
fat_lto(cgcx, dcx, shared_emitter, modules, upstream_modules, &symbols_below_threshold)
fat_lto(
cgcx,
dcx,
shared_emitter,
tm_factory,
modules,
upstream_modules,
&symbols_below_threshold,
)
}
/// 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<LlvmCodegenBackend>,
cgcx: &CodegenContext,
dcx: DiagCtxtHandle<'_>,
exported_symbols_for_lto: &[String],
each_linked_rlib_for_lto: &[PathBuf],
@ -195,9 +206,10 @@ pub(crate) fn prepare_thin(module: ModuleCodegen<ModuleLlvm>) -> (String, ThinBu
}
fn fat_lto(
cgcx: &CodegenContext<LlvmCodegenBackend>,
cgcx: &CodegenContext,
dcx: DiagCtxtHandle<'_>,
shared_emitter: &SharedEmitter,
tm_factory: TargetMachineFactoryFn<LlvmCodegenBackend>,
modules: Vec<FatLtoInput<LlvmCodegenBackend>>,
mut serialized_modules: Vec<(SerializedModule<ModuleBuffer>, CString)>,
symbols_below_threshold: &[*const libc::c_char],
@ -252,7 +264,7 @@ fn fat_lto(
assert!(!serialized_modules.is_empty(), "must have at least one serialized module");
let (buffer, name) = serialized_modules.remove(0);
info!("no in-memory regular modules to choose from, parsing {:?}", name);
let llvm_module = ModuleLlvm::parse(cgcx, &name, buffer.data(), dcx);
let llvm_module = ModuleLlvm::parse(cgcx, tm_factory, &name, buffer.data(), dcx);
ModuleCodegen::new_regular(name.into_string().unwrap(), llvm_module)
}
};
@ -381,7 +393,7 @@ impl Drop for Linker<'_> {
/// all of the `LtoModuleCodegen` units returned below and destroyed once
/// they all go out of scope.
fn thin_lto(
cgcx: &CodegenContext<LlvmCodegenBackend>,
cgcx: &CodegenContext,
dcx: DiagCtxtHandle<'_>,
modules: Vec<(String, ThinBuffer)>,
serialized_modules: Vec<(SerializedModule<ModuleBuffer>, CString)>,
@ -585,7 +597,7 @@ pub(crate) fn enable_autodiff_settings(ad: &[config::AutoDiff]) {
}
pub(crate) fn run_pass_manager(
cgcx: &CodegenContext<LlvmCodegenBackend>,
cgcx: &CodegenContext,
dcx: DiagCtxtHandle<'_>,
module: &mut ModuleCodegen<ModuleLlvm>,
thin: bool,
@ -726,8 +738,9 @@ impl Drop for ThinBuffer {
}
pub(crate) fn optimize_thin_module(
cgcx: &CodegenContext<LlvmCodegenBackend>,
cgcx: &CodegenContext,
shared_emitter: &SharedEmitter,
tm_factory: TargetMachineFactoryFn<LlvmCodegenBackend>,
thin_module: ThinModule<LlvmCodegenBackend>,
) -> ModuleCodegen<ModuleLlvm> {
let dcx = DiagCtxt::new(Box::new(shared_emitter.clone()));
@ -740,7 +753,7 @@ pub(crate) fn optimize_thin_module(
// into that context. One day, however, we may do this for upstream
// crates but for locally codegened modules we may be able to reuse
// that LLVM Context and Module.
let module_llvm = ModuleLlvm::parse(cgcx, module_name, thin_module.data(), dcx);
let module_llvm = ModuleLlvm::parse(cgcx, tm_factory, module_name, thin_module.data(), dcx);
let mut module = ModuleCodegen::new_regular(thin_module.name(), module_llvm);
// Given that the newly created module lacks a thinlto buffer for embedding, we need to re-add it here.
if cgcx.module_config.embed_bitcode() {

View file

@ -323,7 +323,7 @@ pub(crate) fn target_machine_factory(
}
pub(crate) fn save_temp_bitcode(
cgcx: &CodegenContext<LlvmCodegenBackend>,
cgcx: &CodegenContext,
module: &ModuleCodegen<ModuleLlvm>,
name: &str,
) {
@ -358,14 +358,14 @@ pub(crate) enum CodegenDiagnosticsStage {
}
pub(crate) struct DiagnosticHandlers<'a> {
data: *mut (&'a CodegenContext<LlvmCodegenBackend>, &'a SharedEmitter),
data: *mut (&'a CodegenContext, &'a SharedEmitter),
llcx: &'a llvm::Context,
old_handler: Option<&'a llvm::DiagnosticHandler>,
}
impl<'a> DiagnosticHandlers<'a> {
pub(crate) fn new(
cgcx: &'a CodegenContext<LlvmCodegenBackend>,
cgcx: &'a CodegenContext,
shared_emitter: &'a SharedEmitter,
llcx: &'a llvm::Context,
module: &ModuleCodegen<ModuleLlvm>,
@ -431,7 +431,7 @@ impl<'a> Drop for DiagnosticHandlers<'a> {
}
fn report_inline_asm(
cgcx: &CodegenContext<LlvmCodegenBackend>,
cgcx: &CodegenContext,
msg: String,
level: llvm::DiagnosticLevel,
cookie: u64,
@ -463,8 +463,7 @@ unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void
if user.is_null() {
return;
}
let (cgcx, shared_emitter) =
unsafe { *(user as *const (&CodegenContext<LlvmCodegenBackend>, &SharedEmitter)) };
let (cgcx, shared_emitter) = unsafe { *(user as *const (&CodegenContext, &SharedEmitter)) };
let dcx = DiagCtxt::new(Box::new(shared_emitter.clone()));
let dcx = dcx.handle();
@ -560,7 +559,7 @@ pub(crate) enum AutodiffStage {
}
pub(crate) unsafe fn llvm_optimize(
cgcx: &CodegenContext<LlvmCodegenBackend>,
cgcx: &CodegenContext,
dcx: DiagCtxtHandle<'_>,
module: &ModuleCodegen<ModuleLlvm>,
thin_lto_buffer: Option<&mut *mut llvm::ThinLTOBuffer>,
@ -892,7 +891,7 @@ pub(crate) unsafe fn llvm_optimize(
// Unsafe due to LLVM calls.
pub(crate) fn optimize(
cgcx: &CodegenContext<LlvmCodegenBackend>,
cgcx: &CodegenContext,
shared_emitter: &SharedEmitter,
module: &mut ModuleCodegen<ModuleLlvm>,
config: &ModuleConfig,
@ -983,7 +982,7 @@ pub(crate) fn optimize(
}
pub(crate) fn codegen(
cgcx: &CodegenContext<LlvmCodegenBackend>,
cgcx: &CodegenContext,
shared_emitter: &SharedEmitter,
module: ModuleCodegen<ModuleLlvm>,
config: &ModuleConfig,
@ -1238,7 +1237,7 @@ fn create_section_with_flags_asm(section_name: &str, section_flags: &str, data:
asm
}
pub(crate) fn bitcode_section_name(cgcx: &CodegenContext<LlvmCodegenBackend>) -> &'static CStr {
pub(crate) fn bitcode_section_name(cgcx: &CodegenContext) -> &'static CStr {
if cgcx.target_is_like_darwin {
c"__LLVM,__bitcode"
} else if cgcx.target_is_like_aix {
@ -1250,7 +1249,7 @@ pub(crate) fn bitcode_section_name(cgcx: &CodegenContext<LlvmCodegenBackend>) ->
/// Embed the bitcode of an LLVM module for LTO in the LLVM module itself.
fn embed_bitcode(
cgcx: &CodegenContext<LlvmCodegenBackend>,
cgcx: &CodegenContext,
llcx: &llvm::Context,
llmod: &llvm::Module,
bitcode: &[u8],
@ -1334,11 +1333,7 @@ fn embed_bitcode(
// when using MSVC linker. We do this only for data, as linker can fix up
// code references on its own.
// See #26591, #27438
fn create_msvc_imps(
cgcx: &CodegenContext<LlvmCodegenBackend>,
llcx: &llvm::Context,
llmod: &llvm::Module,
) {
fn create_msvc_imps(cgcx: &CodegenContext, llcx: &llvm::Context, llmod: &llvm::Module) {
if !cgcx.msvc_imps_needed {
return;
}

View file

@ -162,8 +162,9 @@ impl WriteBackendMethods for LlvmCodegenBackend {
print!("{stats}");
}
fn run_and_optimize_fat_lto(
cgcx: &CodegenContext<Self>,
cgcx: &CodegenContext,
shared_emitter: &SharedEmitter,
tm_factory: TargetMachineFactoryFn<LlvmCodegenBackend>,
exported_symbols_for_lto: &[String],
each_linked_rlib_for_lto: &[PathBuf],
modules: Vec<FatLtoInput<Self>>,
@ -171,6 +172,7 @@ impl WriteBackendMethods for LlvmCodegenBackend {
let mut module = back::lto::run_fat(
cgcx,
shared_emitter,
tm_factory,
exported_symbols_for_lto,
each_linked_rlib_for_lto,
modules,
@ -183,7 +185,7 @@ impl WriteBackendMethods for LlvmCodegenBackend {
module
}
fn run_thin_lto(
cgcx: &CodegenContext<Self>,
cgcx: &CodegenContext,
dcx: DiagCtxtHandle<'_>,
exported_symbols_for_lto: &[String],
each_linked_rlib_for_lto: &[PathBuf],
@ -200,7 +202,7 @@ impl WriteBackendMethods for LlvmCodegenBackend {
)
}
fn optimize(
cgcx: &CodegenContext<Self>,
cgcx: &CodegenContext,
shared_emitter: &SharedEmitter,
module: &mut ModuleCodegen<Self::Module>,
config: &ModuleConfig,
@ -208,14 +210,15 @@ impl WriteBackendMethods for LlvmCodegenBackend {
back::write::optimize(cgcx, shared_emitter, module, config)
}
fn optimize_thin(
cgcx: &CodegenContext<Self>,
cgcx: &CodegenContext,
shared_emitter: &SharedEmitter,
tm_factory: TargetMachineFactoryFn<LlvmCodegenBackend>,
thin: ThinModule<Self>,
) -> ModuleCodegen<Self::Module> {
back::lto::optimize_thin_module(cgcx, shared_emitter, thin)
back::lto::optimize_thin_module(cgcx, shared_emitter, tm_factory, thin)
}
fn codegen(
cgcx: &CodegenContext<Self>,
cgcx: &CodegenContext,
shared_emitter: &SharedEmitter,
module: ModuleCodegen<Self::Module>,
config: &ModuleConfig,
@ -438,16 +441,9 @@ impl ModuleLlvm {
}
}
fn tm_from_cgcx(
cgcx: &CodegenContext<LlvmCodegenBackend>,
name: &str,
dcx: DiagCtxtHandle<'_>,
) -> OwnedTargetMachine {
(cgcx.tm_factory)(dcx, TargetMachineFactoryConfig::new(cgcx, name))
}
fn parse(
cgcx: &CodegenContext<LlvmCodegenBackend>,
cgcx: &CodegenContext,
tm_factory: TargetMachineFactoryFn<LlvmCodegenBackend>,
name: &CStr,
buffer: &[u8],
dcx: DiagCtxtHandle<'_>,
@ -456,7 +452,7 @@ impl ModuleLlvm {
let llcx = llvm::LLVMContextCreate();
llvm::LLVMContextSetDiscardValueNames(llcx, cgcx.fewer_names.to_llvm_bool());
let llmod_raw = back::lto::parse_module(llcx, name, buffer, dcx);
let tm = ModuleLlvm::tm_from_cgcx(cgcx, name.to_str().unwrap(), dcx);
let tm = tm_factory(dcx, TargetMachineFactoryConfig::new(cgcx, name.to_str().unwrap()));
ModuleLlvm { llmod_raw, llcx, tm: ManuallyDrop::new(tm) }
}

View file

@ -127,10 +127,7 @@ pub(super) fn exported_symbols_for_lto(
symbols_below_threshold
}
pub(super) fn check_lto_allowed<B: WriteBackendMethods>(
cgcx: &CodegenContext<B>,
dcx: DiagCtxtHandle<'_>,
) {
pub(super) fn check_lto_allowed(cgcx: &CodegenContext, dcx: DiagCtxtHandle<'_>) {
if cgcx.lto == Lto::ThinLocal {
// Crate local LTO is always allowed
return;

View file

@ -29,7 +29,8 @@ use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
use rustc_middle::ty::TyCtxt;
use rustc_session::Session;
use rustc_session::config::{
self, CrateType, Lto, OutFileName, OutputFilenames, OutputType, Passes, SwitchWithOptPath,
self, CrateType, Lto, OptLevel, OutFileName, OutputFilenames, OutputType, Passes,
SwitchWithOptPath,
};
use rustc_span::source_map::SourceMap;
use rustc_span::{FileName, InnerSpan, Span, SpanData};
@ -287,10 +288,7 @@ pub struct TargetMachineFactoryConfig {
}
impl TargetMachineFactoryConfig {
pub fn new(
cgcx: &CodegenContext<impl WriteBackendMethods>,
module_name: &str,
) -> TargetMachineFactoryConfig {
pub fn new(cgcx: &CodegenContext, module_name: &str) -> TargetMachineFactoryConfig {
let split_dwarf_file = if cgcx.target_can_use_split_dwarf {
cgcx.output_filenames.split_dwarf_path(
cgcx.split_debuginfo,
@ -322,7 +320,7 @@ pub type TargetMachineFactoryFn<B> = Arc<
/// Additional resources used by optimize_and_codegen (not module specific)
#[derive(Clone)]
pub struct CodegenContext<B: WriteBackendMethods> {
pub struct CodegenContext {
// Resources needed when running LTO
pub prof: SelfProfilerRef,
pub lto: Lto,
@ -336,7 +334,8 @@ pub struct CodegenContext<B: WriteBackendMethods> {
pub output_filenames: Arc<OutputFilenames>,
pub invocation_temp: Option<String>,
pub module_config: Arc<ModuleConfig>,
pub tm_factory: TargetMachineFactoryFn<B>,
pub opt_level: OptLevel,
pub backend_features: Vec<String>,
pub msvc_imps_needed: bool,
pub is_pe_coff: bool,
pub target_can_use_split_dwarf: bool,
@ -363,7 +362,7 @@ pub struct CodegenContext<B: WriteBackendMethods> {
}
fn generate_thin_lto_work<B: ExtraBackendMethods>(
cgcx: &CodegenContext<B>,
cgcx: &CodegenContext,
dcx: DiagCtxtHandle<'_>,
exported_symbols_for_lto: &[String],
each_linked_rlib_for_lto: &[PathBuf],
@ -409,7 +408,7 @@ enum MaybeLtoModules<B: WriteBackendMethods> {
allocator_module: Option<CompiledModule>,
},
FatLto {
cgcx: CodegenContext<B>,
cgcx: CodegenContext,
exported_symbols_for_lto: Arc<Vec<String>>,
each_linked_rlib_file_for_lto: Vec<PathBuf>,
needs_fat_lto: Vec<FatLtoInput<B>>,
@ -417,7 +416,7 @@ enum MaybeLtoModules<B: WriteBackendMethods> {
Vec<(SerializedModule<<B as WriteBackendMethods>::ModuleBuffer>, WorkProduct)>,
},
ThinLto {
cgcx: CodegenContext<B>,
cgcx: CodegenContext,
exported_symbols_for_lto: Arc<Vec<String>>,
each_linked_rlib_file_for_lto: Vec<PathBuf>,
needs_thin_lto: Vec<(String, <B as WriteBackendMethods>::ThinBuffer)>,
@ -841,7 +840,7 @@ pub(crate) fn compute_per_cgu_lto_type(
}
fn execute_optimize_work_item<B: ExtraBackendMethods>(
cgcx: &CodegenContext<B>,
cgcx: &CodegenContext,
shared_emitter: SharedEmitter,
mut module: ModuleCodegen<B::Module>,
) -> WorkItemResult<B> {
@ -896,8 +895,8 @@ fn execute_optimize_work_item<B: ExtraBackendMethods>(
}
}
fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>(
cgcx: &CodegenContext<B>,
fn execute_copy_from_cache_work_item(
cgcx: &CodegenContext,
shared_emitter: SharedEmitter,
module: CachedModuleCodegen,
) -> CompiledModule {
@ -985,8 +984,9 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>(
}
fn do_fat_lto<B: ExtraBackendMethods>(
cgcx: &CodegenContext<B>,
cgcx: &CodegenContext,
shared_emitter: SharedEmitter,
tm_factory: TargetMachineFactoryFn<B>,
exported_symbols_for_lto: &[String],
each_linked_rlib_for_lto: &[PathBuf],
mut needs_fat_lto: Vec<FatLtoInput<B>>,
@ -1006,6 +1006,7 @@ fn do_fat_lto<B: ExtraBackendMethods>(
let module = B::run_and_optimize_fat_lto(
cgcx,
&shared_emitter,
tm_factory,
exported_symbols_for_lto,
each_linked_rlib_for_lto,
needs_fat_lto,
@ -1014,8 +1015,9 @@ fn do_fat_lto<B: ExtraBackendMethods>(
}
fn do_thin_lto<'a, B: ExtraBackendMethods>(
cgcx: &'a CodegenContext<B>,
cgcx: &'a CodegenContext,
shared_emitter: SharedEmitter,
tm_factory: TargetMachineFactoryFn<B>,
exported_symbols_for_lto: Arc<Vec<String>>,
each_linked_rlib_for_lto: Vec<PathBuf>,
needs_thin_lto: Vec<(String, <B as WriteBackendMethods>::ThinBuffer)>,
@ -1052,7 +1054,7 @@ fn do_thin_lto<'a, B: ExtraBackendMethods>(
// bunch of work items onto our queue to do LTO. This all
// happens on the coordinator thread but it's very quick so
// we don't worry about tokens.
for (work, cost) in generate_thin_lto_work(
for (work, cost) in generate_thin_lto_work::<B>(
cgcx,
dcx,
&exported_symbols_for_lto,
@ -1096,7 +1098,13 @@ fn do_thin_lto<'a, B: ExtraBackendMethods>(
while used_token_count < tokens.len() + 1
&& let Some((item, _)) = work_items.pop()
{
spawn_thin_lto_work(&cgcx, shared_emitter.clone(), coordinator_send.clone(), item);
spawn_thin_lto_work(
&cgcx,
shared_emitter.clone(),
Arc::clone(&tm_factory),
coordinator_send.clone(),
item,
);
used_token_count += 1;
}
} else {
@ -1157,13 +1165,14 @@ fn do_thin_lto<'a, B: ExtraBackendMethods>(
}
fn execute_thin_lto_work_item<B: ExtraBackendMethods>(
cgcx: &CodegenContext<B>,
cgcx: &CodegenContext,
shared_emitter: SharedEmitter,
tm_factory: TargetMachineFactoryFn<B>,
module: lto::ThinModule<B>,
) -> CompiledModule {
let _timer = cgcx.prof.generic_activity_with_arg("codegen_module_perform_lto", module.name());
let module = B::optimize_thin(cgcx, &shared_emitter, module);
let module = B::optimize_thin(cgcx, &shared_emitter, tm_factory, module);
B::codegen(cgcx, &shared_emitter, module, &cgcx.module_config)
}
@ -1291,8 +1300,9 @@ fn start_executing_work<B: ExtraBackendMethods>(
})
.expect("failed to spawn helper thread");
let ol = tcx.backend_optimization_level(());
let backend_features = tcx.global_backend_features(());
let opt_level = tcx.backend_optimization_level(());
let backend_features = tcx.global_backend_features(()).clone();
let tm_factory = backend.target_machine_factory(tcx.sess, opt_level, &backend_features);
let remark_dir = if let Some(ref dir) = sess.opts.unstable_opts.remark_dir {
let result = fs::create_dir_all(dir).and_then(|_| dir.canonicalize());
@ -1304,7 +1314,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
None
};
let cgcx = CodegenContext::<B> {
let cgcx = CodegenContext {
crate_types: tcx.crate_types().to_vec(),
lto: sess.lto(),
use_linker_plugin_lto: sess.opts.cg.linker_plugin_lto.enabled(),
@ -1319,7 +1329,8 @@ fn start_executing_work<B: ExtraBackendMethods>(
incr_comp_session_dir: sess.incr_comp_session_dir_opt().map(|r| r.clone()),
output_filenames: Arc::clone(tcx.output_filenames(())),
module_config: regular_config,
tm_factory: backend.target_machine_factory(tcx.sess, ol, backend_features),
opt_level,
backend_features,
msvc_imps_needed: msvc_imps_needed(tcx),
is_pe_coff: tcx.sess.target.is_like_windows,
target_can_use_split_dwarf: tcx.sess.target_can_use_split_dwarf(),
@ -1775,9 +1786,10 @@ fn start_executing_work<B: ExtraBackendMethods>(
assert!(needs_fat_lto.is_empty());
if cgcx.lto == Lto::ThinLocal {
compiled_modules.extend(do_thin_lto(
compiled_modules.extend(do_thin_lto::<B>(
&cgcx,
shared_emitter.clone(),
tm_factory,
exported_symbols_for_lto,
each_linked_rlib_file_for_lto,
needs_thin_lto,
@ -1871,7 +1883,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
pub(crate) struct WorkerFatalError;
fn spawn_work<'a, B: ExtraBackendMethods>(
cgcx: &'a CodegenContext<B>,
cgcx: &'a CodegenContext,
shared_emitter: SharedEmitter,
coordinator_send: Sender<Message<B>>,
llvm_start_time: &mut Option<VerboseTimingGuard<'a>>,
@ -1909,8 +1921,9 @@ fn spawn_work<'a, B: ExtraBackendMethods>(
}
fn spawn_thin_lto_work<'a, B: ExtraBackendMethods>(
cgcx: &'a CodegenContext<B>,
cgcx: &'a CodegenContext,
shared_emitter: SharedEmitter,
tm_factory: TargetMachineFactoryFn<B>,
coordinator_send: Sender<ThinLtoMessage>,
work: ThinLtoWorkItem<B>,
) {
@ -1921,7 +1934,9 @@ fn spawn_thin_lto_work<'a, B: ExtraBackendMethods>(
ThinLtoWorkItem::CopyPostLtoArtifacts(m) => {
execute_copy_from_cache_work_item(&cgcx, shared_emitter, m)
}
ThinLtoWorkItem::ThinLto(m) => execute_thin_lto_work_item(&cgcx, shared_emitter, m),
ThinLtoWorkItem::ThinLto(m) => {
execute_thin_lto_work_item(&cgcx, shared_emitter, tm_factory, m)
}
}));
let msg = match result {
@ -2158,34 +2173,52 @@ impl<B: ExtraBackendMethods> OngoingCodegen<B> {
each_linked_rlib_file_for_lto,
needs_fat_lto,
lto_import_only_modules,
} => CompiledModules {
modules: vec![do_fat_lto(
&cgcx,
shared_emitter,
&exported_symbols_for_lto,
&each_linked_rlib_file_for_lto,
needs_fat_lto,
lto_import_only_modules,
)],
allocator_module: None,
},
} => {
let tm_factory = self.backend.target_machine_factory(
sess,
cgcx.opt_level,
&cgcx.backend_features,
);
CompiledModules {
modules: vec![do_fat_lto(
&cgcx,
shared_emitter,
tm_factory,
&exported_symbols_for_lto,
&each_linked_rlib_file_for_lto,
needs_fat_lto,
lto_import_only_modules,
)],
allocator_module: None,
}
}
MaybeLtoModules::ThinLto {
cgcx,
exported_symbols_for_lto,
each_linked_rlib_file_for_lto,
needs_thin_lto,
lto_import_only_modules,
} => CompiledModules {
modules: do_thin_lto(
&cgcx,
shared_emitter,
exported_symbols_for_lto,
each_linked_rlib_file_for_lto,
needs_thin_lto,
lto_import_only_modules,
),
allocator_module: None,
},
} => {
let tm_factory = self.backend.target_machine_factory(
sess,
cgcx.opt_level,
&cgcx.backend_features,
);
CompiledModules {
modules: do_thin_lto::<B>(
&cgcx,
shared_emitter,
tm_factory,
exported_symbols_for_lto,
each_linked_rlib_file_for_lto,
needs_thin_lto,
lto_import_only_modules,
),
allocator_module: None,
}
}
});
shared_emitter_main.check(sess, true);

View file

@ -4,7 +4,9 @@ use rustc_errors::DiagCtxtHandle;
use rustc_middle::dep_graph::WorkProduct;
use crate::back::lto::{SerializedModule, ThinModule};
use crate::back::write::{CodegenContext, FatLtoInput, ModuleConfig, SharedEmitter};
use crate::back::write::{
CodegenContext, FatLtoInput, ModuleConfig, SharedEmitter, TargetMachineFactoryFn,
};
use crate::{CompiledModule, ModuleCodegen};
pub trait WriteBackendMethods: Clone + 'static {
@ -17,8 +19,9 @@ pub trait WriteBackendMethods: Clone + 'static {
/// Performs fat LTO by merging all modules into a single one, running autodiff
/// if necessary and running any further optimizations
fn run_and_optimize_fat_lto(
cgcx: &CodegenContext<Self>,
cgcx: &CodegenContext,
shared_emitter: &SharedEmitter,
tm_factory: TargetMachineFactoryFn<Self>,
exported_symbols_for_lto: &[String],
each_linked_rlib_for_lto: &[PathBuf],
modules: Vec<FatLtoInput<Self>>,
@ -27,7 +30,7 @@ pub trait WriteBackendMethods: Clone + 'static {
/// 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<Self>,
cgcx: &CodegenContext,
dcx: DiagCtxtHandle<'_>,
exported_symbols_for_lto: &[String],
each_linked_rlib_for_lto: &[PathBuf],
@ -37,18 +40,19 @@ pub trait WriteBackendMethods: Clone + 'static {
fn print_pass_timings(&self);
fn print_statistics(&self);
fn optimize(
cgcx: &CodegenContext<Self>,
cgcx: &CodegenContext,
shared_emitter: &SharedEmitter,
module: &mut ModuleCodegen<Self::Module>,
config: &ModuleConfig,
);
fn optimize_thin(
cgcx: &CodegenContext<Self>,
cgcx: &CodegenContext,
shared_emitter: &SharedEmitter,
tm_factory: TargetMachineFactoryFn<Self>,
thin: ThinModule<Self>,
) -> ModuleCodegen<Self::Module>;
fn codegen(
cgcx: &CodegenContext<Self>,
cgcx: &CodegenContext,
shared_emitter: &SharedEmitter,
module: ModuleCodegen<Self::Module>,
config: &ModuleConfig,