From c946c40d9d47328fc1a08919dec174a77c12fd6b Mon Sep 17 00:00:00 2001 From: khyperia Date: Thu, 17 Sep 2020 12:01:12 +0200 Subject: [PATCH 1/2] Let backends define custom targets Add a target_override hook that takes priority over builtin targets. --- compiler/rustc_codegen_llvm/src/lib.rs | 5 +++++ compiler/rustc_codegen_ssa/src/traits/backend.rs | 5 +++++ compiler/rustc_interface/src/tests.rs | 1 + compiler/rustc_interface/src/util.rs | 15 +++++++++------ compiler/rustc_session/src/config.rs | 9 +++++---- compiler/rustc_session/src/session.rs | 3 ++- 6 files changed, 27 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 2e2abe9fb30f8..21e19696fffc9 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -32,6 +32,7 @@ use rustc_serialize::json; use rustc_session::config::{self, OptLevel, OutputFilenames, PrintRequest}; use rustc_session::Session; use rustc_span::symbol::Symbol; +use rustc_target::spec::Target; use std::any::Any; use std::ffi::CStr; @@ -244,6 +245,10 @@ impl CodegenBackend for LlvmCodegenBackend { target_features(sess) } + fn target_override(&self, _opts: &config::Options) -> Option { + None + } + fn metadata_loader(&self) -> Box { Box::new(metadata::LlvmMetadataLoader) } diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs index 3522ea0115334..224c8c2350f1c 100644 --- a/compiler/rustc_codegen_ssa/src/traits/backend.rs +++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs @@ -15,6 +15,7 @@ use rustc_session::{ }; use rustc_span::symbol::Symbol; use rustc_target::abi::LayoutOf; +use rustc_target::spec::Target; pub use rustc_data_structures::sync::MetadataRef; @@ -54,6 +55,10 @@ pub trait CodegenBackend { fn print_passes(&self) {} fn print_version(&self) {} + /// If this plugin provides additional builtin targets, provide them here. + /// Be careful: this is called *before* init() is called. + fn target_override(&self, opts: &config::Options) -> Option; + fn metadata_loader(&self) -> Box; fn provide(&self, _providers: &mut Providers); fn provide_extern(&self, _providers: &mut Providers); diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index dc4fa807f7868..72e10bc4304d0 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -40,6 +40,7 @@ fn mk_session(matches: getopts::Matches) -> (Session, CfgSpecs) { DiagnosticOutput::Default, Default::default(), None, + None, ); (sess, cfg) } diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index f15eb413833ae..c4d89850dad50 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -65,6 +65,10 @@ pub fn create_session( lint_caps: FxHashMap, descriptions: Registry, ) -> (Lrc, Lrc>) { + let codegen_backend = get_codegen_backend(sopts.debugging_opts.codegen_backend.as_deref()); + // target_override is documented to be called before init(), so this is okay + let target_override = codegen_backend.target_override(&sopts); + let mut sess = session::build_session( sopts, input_path, @@ -72,9 +76,10 @@ pub fn create_session( diagnostic_output, lint_caps, file_loader, + target_override, ); - let codegen_backend = get_codegen_backend(&sess); + codegen_backend.init(&sess); let mut cfg = config::build_configuration(&sess, config::to_crate_config(cfg)); add_configuration(&mut cfg, &mut sess, &*codegen_backend); @@ -219,13 +224,13 @@ fn load_backend_from_dylib(path: &Path) -> fn() -> Box { } } -pub fn get_codegen_backend(sess: &Session) -> Box { +pub fn get_codegen_backend(codegen_name: Option<&str>) -> Box { static INIT: Once = Once::new(); static mut LOAD: fn() -> Box = || unreachable!(); INIT.call_once(|| { - let codegen_name = sess.opts.debugging_opts.codegen_backend.as_deref().unwrap_or("llvm"); + let codegen_name = codegen_name.unwrap_or("llvm"); let backend = match codegen_name { filename if filename.contains('.') => load_backend_from_dylib(filename.as_ref()), codegen_name => get_builtin_codegen_backend(codegen_name), @@ -235,9 +240,7 @@ pub fn get_codegen_backend(sess: &Session) -> Box { LOAD = backend; } }); - let backend = unsafe { LOAD() }; - backend.init(sess); - backend + unsafe { LOAD() } } // This is used for rustdoc, but it uses similar machinery to codegen backend diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 3f12596a236ab..8d004675d7f4d 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -818,10 +818,11 @@ pub fn build_configuration(sess: &Session, mut user_cfg: CrateConfig) -> CrateCo user_cfg } -pub fn build_target_config(opts: &Options, error_format: ErrorOutputType) -> Config { - let target = Target::search(&opts.target_triple).unwrap_or_else(|e| { +pub fn build_target_config(opts: &Options, target_override: Option) -> Config { + let target_result = target_override.map_or_else(|| Target::search(&opts.target_triple), Ok); + let target = target_result.unwrap_or_else(|e| { early_error( - error_format, + opts.error_format, &format!( "Error loading target specification: {}. \ Use `--print target-list` for a list of built-in targets", @@ -835,7 +836,7 @@ pub fn build_target_config(opts: &Options, error_format: ErrorOutputType) -> Con "32" => 32, "64" => 64, w => early_error( - error_format, + opts.error_format, &format!( "target specification was invalid: \ unrecognized target-pointer-width {}", diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 974f4c31bb6a4..ff67d3cb107d9 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1234,6 +1234,7 @@ pub fn build_session( diagnostics_output: DiagnosticOutput, driver_lint_caps: FxHashMap, file_loader: Option>, + target_override: Option, ) -> Session { // FIXME: This is not general enough to make the warning lint completely override // normal diagnostic warnings, since the warning lint can also be denied and changed @@ -1253,7 +1254,7 @@ pub fn build_session( DiagnosticOutput::Raw(write) => Some(write), }; - let target_cfg = config::build_target_config(&sopts, sopts.error_format); + let target_cfg = config::build_target_config(&sopts, target_override); let host_triple = TargetTriple::from_triple(config::host_triple()); let host = Target::search(&host_triple).unwrap_or_else(|e| { early_error(sopts.error_format, &format!("Error loading host specification: {}", e)) From 48655c2d2ca8590c7627f32839ba921297290a1a Mon Sep 17 00:00:00 2001 From: khyperia Date: Thu, 17 Sep 2020 12:14:18 +0200 Subject: [PATCH 2/2] PR feedback --- compiler/rustc_codegen_llvm/src/lib.rs | 5 ----- compiler/rustc_codegen_ssa/src/traits/backend.rs | 6 ++++-- compiler/rustc_interface/src/util.rs | 6 +++--- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 21e19696fffc9..2e2abe9fb30f8 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -32,7 +32,6 @@ use rustc_serialize::json; use rustc_session::config::{self, OptLevel, OutputFilenames, PrintRequest}; use rustc_session::Session; use rustc_span::symbol::Symbol; -use rustc_target::spec::Target; use std::any::Any; use std::ffi::CStr; @@ -245,10 +244,6 @@ impl CodegenBackend for LlvmCodegenBackend { target_features(sess) } - fn target_override(&self, _opts: &config::Options) -> Option { - None - } - fn metadata_loader(&self) -> Box { Box::new(metadata::LlvmMetadataLoader) } diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs index 224c8c2350f1c..90520f77e3c04 100644 --- a/compiler/rustc_codegen_ssa/src/traits/backend.rs +++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs @@ -55,9 +55,11 @@ pub trait CodegenBackend { fn print_passes(&self) {} fn print_version(&self) {} - /// If this plugin provides additional builtin targets, provide them here. + /// If this plugin provides additional builtin targets, provide the one enabled by the options here. /// Be careful: this is called *before* init() is called. - fn target_override(&self, opts: &config::Options) -> Option; + fn target_override(&self, _opts: &config::Options) -> Option { + None + } fn metadata_loader(&self) -> Box; fn provide(&self, _providers: &mut Providers); diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index c4d89850dad50..0eed6938c3169 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -65,7 +65,7 @@ pub fn create_session( lint_caps: FxHashMap, descriptions: Registry, ) -> (Lrc, Lrc>) { - let codegen_backend = get_codegen_backend(sopts.debugging_opts.codegen_backend.as_deref()); + let codegen_backend = get_codegen_backend(&sopts); // target_override is documented to be called before init(), so this is okay let target_override = codegen_backend.target_override(&sopts); @@ -224,13 +224,13 @@ fn load_backend_from_dylib(path: &Path) -> fn() -> Box { } } -pub fn get_codegen_backend(codegen_name: Option<&str>) -> Box { +pub fn get_codegen_backend(sopts: &config::Options) -> Box { static INIT: Once = Once::new(); static mut LOAD: fn() -> Box = || unreachable!(); INIT.call_once(|| { - let codegen_name = codegen_name.unwrap_or("llvm"); + let codegen_name = sopts.debugging_opts.codegen_backend.as_deref().unwrap_or("llvm"); let backend = match codegen_name { filename if filename.contains('.') => load_backend_from_dylib(filename.as_ref()), codegen_name => get_builtin_codegen_backend(codegen_name),