Auto merge of #85810 - bjorn3:further_driver_cleanup, r=varkor

Driver improvements

This PR contains a couple of cleanups for the driver and a few small improvements for the custom codegen backend interface. It also implements `--version` and `-Cpasses=list` support for custom codegen backends.
This commit is contained in:
bors 2021-06-07 02:30:24 +00:00
commit cc9610bf5a
13 changed files with 103 additions and 135 deletions

View File

@ -177,21 +177,6 @@ pub(crate) fn run_aot(
metadata: EncodedMetadata,
need_metadata_module: bool,
) -> Box<(CodegenResults, FxHashMap<WorkProductId, WorkProduct>)> {
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),
},

View File

@ -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<dyn MetadataLoader + Sync> {
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<rustc_span::Symbol> {
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(())

View File

@ -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<MetadataLoaderDyn> {
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(())

View File

@ -1957,7 +1957,7 @@ fn add_order_independent_options(
cmd.output_filename(out_filename);
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);
}
}

View File

@ -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 {

View File

@ -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<B: ExtraBackendMethods>(
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<B: ExtraBackendMethods>(
OngoingCodegen {
backend,
crate_name,
metadata,
windows_subsystem,
linker_info,
crate_info,
@ -1812,9 +1798,7 @@ impl SharedEmitterMain {
pub struct OngoingCodegen<B: ExtraBackendMethods> {
pub backend: B,
pub crate_name: Symbol,
pub metadata: EncodedMetadata,
pub windows_subsystem: Option<String>,
pub linker_info: LinkerInfo,
pub crate_info: CrateInfo,
pub coordinator_send: Sender<Box<dyn Any + Send>>,
@ -1857,9 +1841,7 @@ impl<B: ExtraBackendMethods> OngoingCodegen<B> {
(
CodegenResults {
crate_name: self.crate_name,
metadata: self.metadata,
windows_subsystem: self.windows_subsystem,
linker_info: self.linker_info,
crate_info: self.crate_info,

View File

@ -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<B: ExtraBackendMethods> Drop for AbortCodegenOnDrop<B> {
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();

View File

@ -135,6 +135,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<CrateNum>,
pub compiler_builtins: Option<CrateNum>,
pub profiler_runtime: Option<CrateNum>,
@ -148,16 +149,15 @@ pub struct CrateInfo {
pub lang_item_to_crate: FxHashMap<LangItem, CrateNum>,
pub missing_lang_items: FxHashMap<CrateNum, Vec<LangItem>>,
pub dependency_formats: Lrc<Dependencies>,
pub windows_subsystem: Option<String>,
}
#[derive(Encodable, Decodable)]
pub struct CodegenResults {
pub crate_name: Symbol,
pub modules: Vec<CompiledModule>,
pub allocator_module: Option<CompiledModule>,
pub metadata_module: Option<CompiledModule>,
pub metadata: rustc_middle::middle::cstore::EncodedMetadata,
pub windows_subsystem: Option<String>,
pub linker_info: back::linker::LinkerInfo,
pub crate_info: CrateInfo,
}

View File

@ -63,9 +63,16 @@ pub trait CodegenBackend {
None
}
fn metadata_loader(&self) -> Box<MetadataLoaderDyn>;
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<MetadataLoaderDyn> {
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>,

View File

@ -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<getopts::Matches> {
}
// 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<getopts::Matches> {
}
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;
}

View File

@ -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<Linker> {
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<Session>,
codegen_backend: Lrc<Box<dyn CodegenBackend>>,
// compilation outputs
dep_graph: DepGraph,
prepare_outputs: OutputFilenames,
crate_hash: Svh,
ongoing_codegen: Box<dyn Any>,
codegen_backend: Lrc<Box<dyn CodegenBackend>>,
}
impl Linker {

View File

@ -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<dyn CodegenBackend> {
}
}
pub fn get_codegen_backend(sopts: &config::Options) -> Box<dyn CodegenBackend> {
static INIT: Once = Once::new();
/// 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<PathBuf>,
backend_name: Option<&str>,
) -> Box<dyn CodegenBackend> {
static LOAD: SyncOnceCell<unsafe fn() -> Box<dyn CodegenBackend>> = SyncOnceCell::new();
static mut LOAD: fn() -> Box<dyn CodegenBackend> = || unreachable!();
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<PathBuf> {
}
}
pub fn get_builtin_codegen_backend(
maybe_sysroot: &Option<PathBuf>,
backend_name: &str,
) -> fn() -> Box<dyn CodegenBackend> {
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<PathBuf>,
backend_name: &str,

View File

@ -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<MetadataLoaderDyn> {
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<dyn Any> {
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));