Skip to content

Commit

Permalink
Let backends define custom targets
Browse files Browse the repository at this point in the history
Add a target_override hook that takes priority over builtin targets.
  • Loading branch information
khyperia committed Sep 17, 2020
1 parent 95386b6 commit c946c40
Show file tree
Hide file tree
Showing 6 changed files with 27 additions and 11 deletions.
5 changes: 5 additions & 0 deletions compiler/rustc_codegen_llvm/src/lib.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -244,6 +245,10 @@ impl CodegenBackend for LlvmCodegenBackend {
target_features(sess)
}

fn target_override(&self, _opts: &config::Options) -> Option<Target> {
None
}

fn metadata_loader(&self) -> Box<MetadataLoaderDyn> {
Box::new(metadata::LlvmMetadataLoader)
}
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_codegen_ssa/src/traits/backend.rs
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,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<Target>;

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
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
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.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,
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(codegen_name: Option<&str>) -> 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 = 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),
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
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
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 c946c40

Please sign in to comment.