diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs index 9cf51d15c8ca0..6676d88602c45 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs @@ -177,21 +177,6 @@ pub(crate) fn run_aot( metadata: EncodedMetadata, need_metadata_module: bool, ) -> Box<(CodegenResults, FxHashMap)> { - use rustc_span::symbol::sym; - - let crate_attrs = tcx.hir().attrs(rustc_hir::CRATE_HIR_ID); - let subsystem = tcx.sess.first_attr_value_str_by_name(crate_attrs, sym::windows_subsystem); - let windows_subsystem = subsystem.map(|subsystem| { - if subsystem != sym::windows && subsystem != sym::console { - tcx.sess.fatal(&format!( - "invalid windows subsystem `{}`, only \ - `windows` and `console` are allowed", - subsystem - )); - } - subsystem.to_string() - }); - let mut work_products = FxHashMap::default(); let cgus = if tcx.sess.opts.output_types.should_codegen() { @@ -307,12 +292,10 @@ pub(crate) fn run_aot( Box::new(( CodegenResults { - crate_name: tcx.crate_name(LOCAL_CRATE), modules, allocator_module, metadata_module, metadata, - windows_subsystem, linker_info: LinkerInfo::new(tcx, crate::target_triple(tcx.sess).to_string()), crate_info: CrateInfo::new(tcx), }, diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index 4ee887cd5afae..904efed5bd98c 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -28,8 +28,7 @@ use rustc_codegen_ssa::traits::CodegenBackend; use rustc_codegen_ssa::CodegenResults; use rustc_errors::ErrorReported; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; -use rustc_middle::middle::cstore::{EncodedMetadata, MetadataLoader}; -use rustc_middle::ty::query::Providers; +use rustc_middle::middle::cstore::EncodedMetadata; use rustc_session::config::OutputFilenames; use rustc_session::Session; @@ -164,17 +163,14 @@ impl CodegenBackend for CraneliftCodegenBackend { } } - fn metadata_loader(&self) -> Box { - Box::new(rustc_codegen_ssa::back::metadata::DefaultMetadataLoader) - } - - fn provide(&self, _providers: &mut Providers) {} - fn provide_extern(&self, _providers: &mut Providers) {} - fn target_features(&self, _sess: &Session) -> Vec { vec![] } + fn print_version(&self) { + println!("Cranelift version: {}", cranelift_codegen::VERSION); + } + fn codegen_crate( &self, tcx: TyCtxt<'_>, @@ -222,7 +218,7 @@ impl CodegenBackend for CraneliftCodegenBackend { sess, &codegen_results, outputs, - &codegen_results.crate_name.as_str(), + &codegen_results.crate_info.local_crate_name.as_str(), ); Ok(()) diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 728f1224dd86e..776cb2ee99bcb 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -29,8 +29,8 @@ use rustc_codegen_ssa::{CodegenResults, CompiledModule}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{ErrorReported, FatalError, Handler}; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; -use rustc_middle::middle::cstore::{EncodedMetadata, MetadataLoaderDyn}; -use rustc_middle::ty::{self, TyCtxt}; +use rustc_middle::middle::cstore::EncodedMetadata; +use rustc_middle::ty::TyCtxt; use rustc_session::config::{OptLevel, OutputFilenames, PrintRequest}; use rustc_session::Session; use rustc_span::symbol::Symbol; @@ -248,13 +248,6 @@ impl CodegenBackend for LlvmCodegenBackend { target_features(sess) } - fn metadata_loader(&self) -> Box { - Box::new(rustc_codegen_ssa::back::metadata::DefaultMetadataLoader) - } - - fn provide(&self, _providers: &mut ty::query::Providers) {} - fn provide_extern(&self, _providers: &mut ty::query::Providers) {} - fn codegen_crate<'tcx>( &self, tcx: TyCtxt<'tcx>, @@ -304,7 +297,7 @@ impl CodegenBackend for LlvmCodegenBackend { sess, &codegen_results, outputs, - &codegen_results.crate_name.as_str(), + &codegen_results.crate_info.local_crate_name.as_str(), ); Ok(()) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 32275e9b07348..c056156109fdb 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1686,7 +1686,7 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>( // OBJECT-FILES-NO, AUDIT-ORDER if crate_type == CrateType::Executable && sess.target.is_like_windows { - if let Some(ref s) = codegen_results.windows_subsystem { + if let Some(ref s) = codegen_results.crate_info.windows_subsystem { cmd.subsystem(s); } } diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 14d6f0ba147b5..b2ecc3b0f3242 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -370,7 +370,6 @@ pub fn provide(providers: &mut Providers) { pub fn provide_extern(providers: &mut Providers) { providers.is_reachable_non_generic = is_reachable_non_generic_provider_extern; providers.upstream_monomorphizations_for = upstream_monomorphizations_for_provider; - providers.wasm_import_module_map = wasm_import_module_map; } fn symbol_export_level(tcx: TyCtxt<'_>, sym_def_id: DefId) -> SymbolExportLevel { diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 49774dc6d5c7d..ff4e640957140 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -31,7 +31,7 @@ use rustc_session::config::{self, CrateType, Lto, OutputFilenames, OutputType}; use rustc_session::config::{Passes, SwitchWithOptPath}; use rustc_session::Session; use rustc_span::source_map::SourceMap; -use rustc_span::symbol::{sym, Symbol}; +use rustc_span::symbol::sym; use rustc_span::{BytePos, FileName, InnerSpan, Pos, Span}; use rustc_target::spec::{MergeFunctions, PanicStrategy, SanitizerSet}; @@ -426,21 +426,9 @@ pub fn start_async_codegen( let (coordinator_send, coordinator_receive) = channel(); let sess = tcx.sess; - let crate_name = tcx.crate_name(LOCAL_CRATE); let crate_attrs = tcx.hir().attrs(rustc_hir::CRATE_HIR_ID); let no_builtins = tcx.sess.contains_name(crate_attrs, sym::no_builtins); let is_compiler_builtins = tcx.sess.contains_name(crate_attrs, sym::compiler_builtins); - let subsystem = tcx.sess.first_attr_value_str_by_name(crate_attrs, sym::windows_subsystem); - let windows_subsystem = subsystem.map(|subsystem| { - if subsystem != sym::windows && subsystem != sym::console { - tcx.sess.fatal(&format!( - "invalid windows subsystem `{}`, only \ - `windows` and `console` are allowed", - subsystem - )); - } - subsystem.to_string() - }); let linker_info = LinkerInfo::new(tcx, target_cpu); let crate_info = CrateInfo::new(tcx); @@ -472,9 +460,7 @@ pub fn start_async_codegen( OngoingCodegen { backend, - crate_name, metadata, - windows_subsystem, linker_info, crate_info, @@ -1812,9 +1798,7 @@ impl SharedEmitterMain { pub struct OngoingCodegen { pub backend: B, - pub crate_name: Symbol, pub metadata: EncodedMetadata, - pub windows_subsystem: Option, pub linker_info: LinkerInfo, pub crate_info: CrateInfo, pub coordinator_send: Sender>, @@ -1857,9 +1841,7 @@ impl OngoingCodegen { ( CodegenResults { - crate_name: self.crate_name, metadata: self.metadata, - windows_subsystem: self.windows_subsystem, linker_info: self.linker_info, crate_info: self.crate_info, diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index b44e74d5ae820..38ab39febe066 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -30,6 +30,7 @@ use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_session::cgu_reuse_tracker::CguReuse; use rustc_session::config::{self, EntryFnType}; use rustc_session::Session; +use rustc_span::symbol::sym; use rustc_target::abi::{Align, LayoutOf, VariantIdx}; use std::ops::{Deref, DerefMut}; @@ -755,7 +756,22 @@ impl Drop for AbortCodegenOnDrop { impl CrateInfo { pub fn new(tcx: TyCtxt<'_>) -> CrateInfo { + let local_crate_name = tcx.crate_name(LOCAL_CRATE); + let crate_attrs = tcx.hir().attrs(rustc_hir::CRATE_HIR_ID); + let subsystem = tcx.sess.first_attr_value_str_by_name(crate_attrs, sym::windows_subsystem); + let windows_subsystem = subsystem.map(|subsystem| { + if subsystem != sym::windows && subsystem != sym::console { + tcx.sess.fatal(&format!( + "invalid windows subsystem `{}`, only \ + `windows` and `console` are allowed", + subsystem + )); + } + subsystem.to_string() + }); + let mut info = CrateInfo { + local_crate_name, panic_runtime: None, compiler_builtins: None, profiler_runtime: None, @@ -769,6 +785,7 @@ impl CrateInfo { lang_item_to_crate: Default::default(), missing_lang_items: Default::default(), dependency_formats: tcx.dependency_formats(()), + windows_subsystem, }; let lang_items = tcx.lang_items(); diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 12da3d9e155e3..e757051e22b62 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -128,6 +128,7 @@ impl From<&cstore::NativeLib> for NativeLib { /// and the corresponding properties without referencing information outside of a `CrateInfo`. #[derive(Debug, Encodable, Decodable)] pub struct CrateInfo { + pub local_crate_name: Symbol, pub panic_runtime: Option, pub compiler_builtins: Option, pub profiler_runtime: Option, @@ -141,16 +142,15 @@ pub struct CrateInfo { pub lang_item_to_crate: FxHashMap, pub missing_lang_items: FxHashMap>, pub dependency_formats: Lrc, + pub windows_subsystem: Option, } #[derive(Encodable, Decodable)] pub struct CodegenResults { - pub crate_name: Symbol, pub modules: Vec, pub allocator_module: Option, pub metadata_module: Option, pub metadata: rustc_middle::middle::cstore::EncodedMetadata, - pub windows_subsystem: Option, pub linker_info: back::linker::LinkerInfo, pub crate_info: CrateInfo, } diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs index f28db2fe84b6b..dc4146ec7b58d 100644 --- a/compiler/rustc_codegen_ssa/src/traits/backend.rs +++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs @@ -63,9 +63,16 @@ pub trait CodegenBackend { None } - fn metadata_loader(&self) -> Box; - fn provide(&self, _providers: &mut Providers); - fn provide_extern(&self, _providers: &mut Providers); + /// The metadata loader used to load rlib and dylib metadata. + /// + /// Alternative codegen backends may want to use different rlib or dylib formats than the + /// default native static archives and dynamic libraries. + fn metadata_loader(&self) -> Box { + Box::new(crate::back::metadata::DefaultMetadataLoader) + } + + fn provide(&self, _providers: &mut Providers) {} + fn provide_extern(&self, _providers: &mut Providers) {} fn codegen_crate<'tcx>( &self, tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index c9b36dd0c24ca..b943977e4c2bb 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -21,7 +21,7 @@ use rustc_data_structures::sync::SeqCst; use rustc_errors::registry::{InvalidErrorCode, Registry}; use rustc_errors::{ErrorReported, PResult}; use rustc_feature::find_gated_cfg; -use rustc_interface::util::{self, collect_crate_types, get_builtin_codegen_backend}; +use rustc_interface::util::{self, collect_crate_types, get_codegen_backend}; use rustc_interface::{interface, Queries}; use rustc_lint::LintStore; use rustc_metadata::locator; @@ -499,7 +499,7 @@ fn make_input( } } -// Whether to stop or continue compilation. +/// Whether to stop or continue compilation. #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum Compilation { Stop, @@ -765,9 +765,16 @@ pub fn version(binary: &str, matches: &getopts::Matches) { println!("commit-date: {}", unw(util::commit_date_str())); println!("host: {}", config::host_triple()); println!("release: {}", unw(util::release_str())); - if cfg!(feature = "llvm") { - get_builtin_codegen_backend(&None, "llvm")().print_version(); - } + + let debug_flags = matches.opt_strs("Z"); + let backend_name = debug_flags.iter().find_map(|x| { + if x.starts_with("codegen-backend=") { + Some(&x["codegen-backends=".len()..]) + } else { + None + } + }); + get_codegen_backend(&None, backend_name).print_version(); } } @@ -1039,8 +1046,8 @@ pub fn handle_options(args: &[String]) -> Option { } // Don't handle -W help here, because we might first load plugins. - let r = matches.opt_strs("Z"); - if r.iter().any(|x| *x == "help") { + let debug_flags = matches.opt_strs("Z"); + if debug_flags.iter().any(|x| *x == "help") { describe_debug_flags(); return None; } @@ -1060,9 +1067,14 @@ pub fn handle_options(args: &[String]) -> Option { } if cg_flags.iter().any(|x| *x == "passes=list") { - if cfg!(feature = "llvm") { - get_builtin_codegen_backend(&None, "llvm")().print_passes(); - } + let backend_name = debug_flags.iter().find_map(|x| { + if x.starts_with("codegen-backend=") { + Some(&x["codegen-backends=".len()..]) + } else { + None + } + }); + get_codegen_backend(&None, backend_name).print_passes(); return None; } diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 969b526235bb2..2320f0b47d27d 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -245,8 +245,7 @@ impl<'tcx> Queries<'tcx> { self.prepare_outputs.compute(|| { let expansion_result = self.expansion()?; let (krate, boxed_resolver, _) = &*expansion_result.peek(); - let crate_name = self.crate_name()?; - let crate_name = crate_name.peek(); + let crate_name = self.crate_name()?.peek(); passes::prepare_outputs( self.session(), self.compiler, @@ -343,32 +342,36 @@ impl<'tcx> Queries<'tcx> { } pub fn linker(&'tcx self) -> Result { - let dep_graph = self.dep_graph()?; - let prepare_outputs = self.prepare_outputs()?; - let crate_hash = self.global_ctxt()?.peek_mut().enter(|tcx| tcx.crate_hash(LOCAL_CRATE)); - let ongoing_codegen = self.ongoing_codegen()?; - let sess = self.session().clone(); let codegen_backend = self.codegen_backend().clone(); + let dep_graph = self.dep_graph()?.peek().clone(); + let prepare_outputs = self.prepare_outputs()?.take(); + let crate_hash = self.global_ctxt()?.peek_mut().enter(|tcx| tcx.crate_hash(LOCAL_CRATE)); + let ongoing_codegen = self.ongoing_codegen()?.take(); + Ok(Linker { sess, - dep_graph: dep_graph.peek().clone(), - prepare_outputs: prepare_outputs.take(), - crate_hash, - ongoing_codegen: ongoing_codegen.take(), codegen_backend, + + dep_graph, + prepare_outputs, + crate_hash, + ongoing_codegen, }) } } pub struct Linker { + // compilation inputs sess: Lrc, + codegen_backend: Lrc>, + + // compilation outputs dep_graph: DepGraph, prepare_outputs: OutputFilenames, crate_hash: Svh, ongoing_codegen: Box, - codegen_backend: Lrc>, } impl Linker { diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 15cda2992088a..d1d0eee365d48 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -32,7 +32,7 @@ use std::ops::DerefMut; use std::panic; use std::path::{Path, PathBuf}; use std::sync::atomic::{AtomicBool, Ordering}; -use std::sync::{Arc, Mutex, Once}; +use std::sync::{Arc, Mutex}; use std::thread; use tracing::info; @@ -73,7 +73,10 @@ pub fn create_session( let codegen_backend = if let Some(make_codegen_backend) = make_codegen_backend { make_codegen_backend(&sopts) } else { - get_codegen_backend(&sopts) + get_codegen_backend( + &sopts.maybe_sysroot, + sopts.debugging_opts.codegen_backend.as_ref().map(|name| &name[..]), + ) }; // target_override is documented to be called before init(), so this is okay @@ -241,35 +244,34 @@ fn load_backend_from_dylib(path: &Path) -> fn() -> Box { } } -pub fn get_codegen_backend(sopts: &config::Options) -> Box { - static INIT: Once = Once::new(); - - static mut LOAD: fn() -> Box = || unreachable!(); +/// Get the codegen backend based on the name and specified sysroot. +/// +/// A name of `None` indicates that the default backend should be used. +pub fn get_codegen_backend( + maybe_sysroot: &Option, + backend_name: Option<&str>, +) -> Box { + static LOAD: SyncOnceCell Box> = SyncOnceCell::new(); - INIT.call_once(|| { + let load = LOAD.get_or_init(|| { #[cfg(feature = "llvm")] const DEFAULT_CODEGEN_BACKEND: &str = "llvm"; #[cfg(not(feature = "llvm"))] const DEFAULT_CODEGEN_BACKEND: &str = "cranelift"; - let codegen_name = sopts - .debugging_opts - .codegen_backend - .as_ref() - .map(|name| &name[..]) - .unwrap_or(DEFAULT_CODEGEN_BACKEND); - - let backend = match codegen_name { + match backend_name.unwrap_or(DEFAULT_CODEGEN_BACKEND) { filename if filename.contains('.') => load_backend_from_dylib(filename.as_ref()), - codegen_name => get_builtin_codegen_backend(&sopts.maybe_sysroot, codegen_name), - }; - - unsafe { - LOAD = backend; + #[cfg(feature = "llvm")] + "llvm" => rustc_codegen_llvm::LlvmCodegenBackend::new, + backend_name => get_codegen_sysroot(maybe_sysroot, backend_name), } }); - unsafe { LOAD() } + + // SAFETY: In case of a builtin codegen backend this is safe. In case of an external codegen + // backend we hope that the backend links against the same rustc_driver version. If this is not + // the case, we get UB. + unsafe { load() } } // This is used for rustdoc, but it uses similar machinery to codegen backend @@ -387,17 +389,6 @@ fn sysroot_candidates() -> Vec { } } -pub fn get_builtin_codegen_backend( - maybe_sysroot: &Option, - backend_name: &str, -) -> fn() -> Box { - match backend_name { - #[cfg(feature = "llvm")] - "llvm" => rustc_codegen_llvm::LlvmCodegenBackend::new, - _ => get_codegen_sysroot(maybe_sysroot, backend_name), - } -} - pub fn get_codegen_sysroot( maybe_sysroot: &Option, backend_name: &str, diff --git a/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs b/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs index a9e99d3c10ecc..443e2df357fb4 100644 --- a/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs +++ b/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs @@ -1,4 +1,5 @@ #![feature(rustc_private)] +#![deny(warnings)] extern crate rustc_codegen_ssa; extern crate rustc_errors; @@ -15,44 +16,28 @@ use rustc_codegen_ssa::back::linker::LinkerInfo; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_codegen_ssa::{CodegenResults, CrateInfo}; use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::sync::MetadataRef; use rustc_errors::ErrorReported; -use rustc_middle::dep_graph::DepGraph; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; -use rustc_middle::middle::cstore::{EncodedMetadata, MetadataLoader, MetadataLoaderDyn}; -use rustc_middle::ty::query::Providers; +use rustc_middle::middle::cstore::EncodedMetadata; use rustc_middle::ty::TyCtxt; use rustc_session::config::OutputFilenames; use rustc_session::Session; -use rustc_target::spec::Target; use std::any::Any; -use std::path::Path; struct TheBackend; impl CodegenBackend for TheBackend { - fn metadata_loader(&self) -> Box { - Box::new(rustc_codegen_ssa::back::metadata::DefaultMetadataLoader) - } - - fn provide(&self, providers: &mut Providers) {} - fn provide_extern(&self, providers: &mut Providers) {} - fn codegen_crate<'a, 'tcx>( &self, tcx: TyCtxt<'tcx>, metadata: EncodedMetadata, _need_metadata_module: bool, ) -> Box { - use rustc_hir::def_id::LOCAL_CRATE; - Box::new(CodegenResults { - crate_name: tcx.crate_name(LOCAL_CRATE), modules: vec![], allocator_module: None, metadata_module: None, metadata, - windows_subsystem: None, linker_info: LinkerInfo::new(tcx, "fake_target_cpu".to_string()), crate_info: CrateInfo::new(tcx), }) @@ -77,7 +62,7 @@ impl CodegenBackend for TheBackend { ) -> Result<(), ErrorReported> { use rustc_session::{config::CrateType, output::out_filename}; use std::io::Write; - let crate_name = codegen_results.crate_name; + let crate_name = codegen_results.crate_info.local_crate_name; for &crate_type in sess.opts.crate_types.iter() { if crate_type != CrateType::Rlib { sess.fatal(&format!("Crate type is {:?}", crate_type));