Skip to content

Commit

Permalink
Rollup merge of rust-lang#76832 - khyperia:backend_target_override, r…
Browse files Browse the repository at this point in the history
…=eddyb

Let backends define custom targets

Add a target_override hook that takes priority over builtin targets.
  • Loading branch information
Dylan-DPC committed Sep 19, 2020
2 parents c20e2e2 + 48655c2 commit 0660bc0
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 11 deletions.
7 changes: 7 additions & 0 deletions compiler/rustc_codegen_ssa/src/traits/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -54,6 +55,12 @@ pub trait CodegenBackend {
fn print_passes(&self) {}
fn print_version(&self) {}

/// 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<Target> {
None
}

fn metadata_loader(&self) -> Box<MetadataLoaderDyn>;
fn provide(&self, _providers: &mut Providers);
fn provide_extern(&self, _providers: &mut Providers);
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_interface/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ fn mk_session(matches: getopts::Matches) -> (Session, CfgSpecs) {
DiagnosticOutput::Default,
Default::default(),
None,
None,
);
(sess, cfg)
}
Expand Down
15 changes: 9 additions & 6 deletions compiler/rustc_interface/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,16 +65,21 @@ pub fn create_session(
lint_caps: FxHashMap<lint::LintId, lint::Level>,
descriptions: Registry,
) -> (Lrc<Session>, Lrc<Box<dyn CodegenBackend>>) {
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);

let mut sess = session::build_session(
sopts,
input_path,
descriptions,
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);
Expand Down Expand Up @@ -219,13 +224,13 @@ fn load_backend_from_dylib(path: &Path) -> fn() -> Box<dyn CodegenBackend> {
}
}

pub fn get_codegen_backend(sess: &Session) -> Box<dyn CodegenBackend> {
pub fn get_codegen_backend(sopts: &config::Options) -> Box<dyn CodegenBackend> {
static INIT: Once = Once::new();

static mut LOAD: fn() -> Box<dyn CodegenBackend> = || unreachable!();

INIT.call_once(|| {
let codegen_name = sess.opts.debugging_opts.codegen_backend.as_deref().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),
Expand All @@ -235,9 +240,7 @@ pub fn get_codegen_backend(sess: &Session) -> Box<dyn CodegenBackend> {
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
Expand Down
9 changes: 5 additions & 4 deletions compiler/rustc_session/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Target>) -> 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",
Expand All @@ -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 {}",
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_session/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1234,6 +1234,7 @@ pub fn build_session(
diagnostics_output: DiagnosticOutput,
driver_lint_caps: FxHashMap<lint::LintId, lint::Level>,
file_loader: Option<Box<dyn FileLoader + Send + Sync + 'static>>,
target_override: Option<Target>,
) -> 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
Expand All @@ -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))
Expand Down

0 comments on commit 0660bc0

Please sign in to comment.