Skip to content

Commit a699d87

Browse files
committed
Allow targets to override default codegen backend
1 parent 0b0415f commit a699d87

File tree

3 files changed

+64
-21
lines changed

3 files changed

+64
-21
lines changed

compiler/rustc_driver_impl/src/lib.rs

+15-3
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ use rustc_session::config::{ErrorOutputType, Input, OutFileName, OutputType, Tri
4242
use rustc_session::cstore::MetadataLoader;
4343
use rustc_session::getopts::{self, Matches};
4444
use rustc_session::lint::{Lint, LintId};
45-
use rustc_session::{config, EarlyErrorHandler, Session};
45+
use rustc_session::{config, filesearch, EarlyErrorHandler, Session};
4646
use rustc_span::source_map::{FileLoader, FileName};
4747
use rustc_span::symbol::sym;
4848
use rustc_target::json::ToJson;
@@ -923,7 +923,13 @@ pub fn version_at_macro_invocation(
923923

924924
let debug_flags = matches.opt_strs("Z");
925925
let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend="));
926-
get_codegen_backend(handler, &None, backend_name).print_version();
926+
let sopts = config::Options::default();
927+
let sysroot = sopts.maybe_sysroot.clone().unwrap_or_else(|| {
928+
filesearch::get_or_default_sysroot().expect("Failed finding sysroot")
929+
});
930+
let target = config::build_target_config(handler, &sopts, None, &sysroot);
931+
932+
get_codegen_backend(handler, &sysroot, backend_name, &target).print_version();
927933
}
928934
}
929935

@@ -1127,7 +1133,13 @@ pub fn describe_flag_categories(handler: &EarlyErrorHandler, matches: &Matches)
11271133

11281134
if cg_flags.iter().any(|x| *x == "passes=list") {
11291135
let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend="));
1130-
get_codegen_backend(handler, &None, backend_name).print_passes();
1136+
let sopts = config::Options::default();
1137+
let sysroot = sopts.maybe_sysroot.clone().unwrap_or_else(|| {
1138+
filesearch::get_or_default_sysroot().expect("Failed finding sysroot")
1139+
});
1140+
let target = config::build_target_config(handler, &sopts, None, &sysroot);
1141+
1142+
get_codegen_backend(handler, &sysroot, backend_name, &target).print_passes();
11311143
return true;
11321144
}
11331145

compiler/rustc_interface/src/util.rs

+40-18
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,16 @@ use rustc_span::edit_distance::find_best_match_for_name;
2020
use rustc_span::edition::Edition;
2121
use rustc_span::source_map::FileLoader;
2222
use rustc_span::symbol::{sym, Symbol};
23+
use rustc_target::spec::Target;
2324
use session::{CompilerIO, EarlyErrorHandler};
24-
use std::env;
2525
use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
2626
use std::mem;
27+
use std::ops::Deref;
2728
use std::path::{Path, PathBuf};
2829
use std::sync::atomic::{AtomicBool, Ordering};
2930
use std::sync::OnceLock;
3031
use std::thread;
32+
use std::{env, iter};
3133

3234
/// Function pointer type that constructs a new CodegenBackend.
3335
pub type MakeBackendFn = fn() -> Box<dyn CodegenBackend>;
@@ -79,24 +81,41 @@ pub fn create_session(
7981
};
8082

8183
let (codegen_backend, target_cfg) = match make_codegen_backend {
82-
Some(make_codegen_backend) => {
83-
let backend = make_codegen_backend(&sopts);
84+
None => {
85+
// Build a target without override, so that it can override the backend if needed
86+
let target = config::build_target_config(handler, &sopts, None, &sysroot);
87+
88+
let backend = get_codegen_backend(
89+
handler,
90+
&sysroot,
91+
sopts.unstable_opts.codegen_backend.as_deref(),
92+
&target,
93+
);
8494

8595
// target_override is documented to be called before init(), so this is okay
8696
let target_override = backend.target_override(&sopts);
8797

98+
// Assert that we don't use target's override of the backend and
99+
// backend's override of the target at the same time
100+
if sopts.unstable_opts.codegen_backend.is_none()
101+
&& target.default_codegen_backend.is_some()
102+
&& target_override.is_some()
103+
{
104+
rustc_middle::bug!(
105+
"Codegen backend requested target override even though the target requested the backend"
106+
);
107+
}
108+
109+
// Re-build target with the (potential) override
88110
let target = config::build_target_config(handler, &sopts, target_override, &sysroot);
89111

90112
(backend, target)
91113
}
92-
None => {
93-
let _target = config::build_target_config(handler, &sopts, None, &sysroot);
114+
Some(make_codegen_backend) => {
115+
// N.B. `make_codegen_backend` takes precedence over `target.default_codegen_backend`,
116+
// which is ignored in this case.
94117

95-
let backend = get_codegen_backend(
96-
handler,
97-
&sopts.maybe_sysroot,
98-
sopts.unstable_opts.codegen_backend.as_deref(),
99-
);
118+
let backend = make_codegen_backend(&sopts);
100119

101120
// target_override is documented to be called before init(), so this is okay
102121
let target_override = backend.target_override(&sopts);
@@ -295,21 +314,25 @@ fn load_backend_from_dylib(handler: &EarlyErrorHandler, path: &Path) -> MakeBack
295314
/// A name of `None` indicates that the default backend should be used.
296315
pub fn get_codegen_backend(
297316
handler: &EarlyErrorHandler,
298-
maybe_sysroot: &Option<PathBuf>,
317+
sysroot: &Path,
299318
backend_name: Option<&str>,
319+
target: &Target,
300320
) -> Box<dyn CodegenBackend> {
301321
static LOAD: OnceLock<unsafe fn() -> Box<dyn CodegenBackend>> = OnceLock::new();
302322

303323
let load = LOAD.get_or_init(|| {
304-
let default_codegen_backend = option_env!("CFG_DEFAULT_CODEGEN_BACKEND").unwrap_or("llvm");
324+
let backend = backend_name
325+
.or(target.default_codegen_backend.as_deref())
326+
.or(option_env!("CFG_DEFAULT_CODEGEN_BACKEND"))
327+
.unwrap_or("llvm");
305328

306-
match backend_name.unwrap_or(default_codegen_backend) {
329+
match backend {
307330
filename if filename.contains('.') => {
308331
load_backend_from_dylib(handler, filename.as_ref())
309332
}
310333
#[cfg(feature = "llvm")]
311334
"llvm" => rustc_codegen_llvm::LlvmCodegenBackend::new,
312-
backend_name => get_codegen_sysroot(handler, maybe_sysroot, backend_name),
335+
backend_name => get_codegen_sysroot(handler, sysroot, backend_name),
313336
}
314337
});
315338

@@ -343,7 +366,7 @@ fn get_rustc_path_inner(bin_path: &str) -> Option<PathBuf> {
343366

344367
fn get_codegen_sysroot(
345368
handler: &EarlyErrorHandler,
346-
maybe_sysroot: &Option<PathBuf>,
369+
sysroot: &Path,
347370
backend_name: &str,
348371
) -> MakeBackendFn {
349372
// For now we only allow this function to be called once as it'll dlopen a
@@ -360,9 +383,8 @@ fn get_codegen_sysroot(
360383
let target = session::config::host_triple();
361384
let sysroot_candidates = sysroot_candidates();
362385

363-
let sysroot = maybe_sysroot
364-
.iter()
365-
.chain(sysroot_candidates.iter())
386+
let sysroot = iter::once(sysroot)
387+
.chain(sysroot_candidates.iter().map(<_>::deref))
366388
.map(|sysroot| {
367389
filesearch::make_target_lib_path(sysroot, target).with_file_name("codegen-backends")
368390
})

compiler/rustc_target/src/spec/mod.rs

+9
Original file line numberDiff line numberDiff line change
@@ -1966,6 +1966,14 @@ pub struct TargetOptions {
19661966
/// Default number of codegen units to use in debug mode
19671967
pub default_codegen_units: Option<u64>,
19681968

1969+
/// Default codegen backend used for this target. Defaults to `None`.
1970+
///
1971+
/// If `None`, then `CFG_DEFAULT_CODEGEN_BACKEND` environmental variable captured when
1972+
/// compiling `rustc` will be used instead (or llvm if it is not set).
1973+
///
1974+
/// N.B. when *using* the compiler, backend can always be overriden with `-Zcodegen-backend`.
1975+
pub default_codegen_backend: Option<StaticCow<str>>,
1976+
19691977
/// Whether to generate trap instructions in places where optimization would
19701978
/// otherwise produce control flow that falls through into unrelated memory.
19711979
pub trap_unreachable: bool,
@@ -2272,6 +2280,7 @@ impl Default for TargetOptions {
22722280
stack_probes: StackProbeType::None,
22732281
min_global_align: None,
22742282
default_codegen_units: None,
2283+
default_codegen_backend: None,
22752284
trap_unreachable: true,
22762285
requires_lto: false,
22772286
singlethread: false,

0 commit comments

Comments
 (0)