Skip to content

Commit eedd680

Browse files
committed
Allow targets to override default codegen backend
1 parent d9bde93 commit eedd680

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;
@@ -943,7 +943,13 @@ pub fn version_at_macro_invocation(
943943

944944
let debug_flags = matches.opt_strs("Z");
945945
let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend="));
946-
get_codegen_backend(handler, &None, backend_name).print_version();
946+
let sopts = config::Options::default();
947+
let sysroot = sopts.maybe_sysroot.clone().unwrap_or_else(|| {
948+
filesearch::get_or_default_sysroot().expect("Failed finding sysroot")
949+
});
950+
let target = config::build_target_config(handler, &sopts, None, &sysroot);
951+
952+
get_codegen_backend(handler, &sysroot, backend_name, &target).print_version();
947953
}
948954
}
949955

@@ -1147,7 +1153,13 @@ pub fn describe_flag_categories(handler: &EarlyErrorHandler, matches: &Matches)
11471153

11481154
if cg_flags.iter().any(|x| *x == "passes=list") {
11491155
let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend="));
1150-
get_codegen_backend(handler, &None, backend_name).print_passes();
1156+
let sopts = config::Options::default();
1157+
let sysroot = sopts.maybe_sysroot.clone().unwrap_or_else(|| {
1158+
filesearch::get_or_default_sysroot().expect("Failed finding sysroot")
1159+
});
1160+
let target = config::build_target_config(handler, &sopts, None, &sysroot);
1161+
1162+
get_codegen_backend(handler, &sysroot, backend_name, &target).print_passes();
11511163
return true;
11521164
}
11531165

compiler/rustc_interface/src/util.rs

+40-18
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,16 @@ use rustc_span::edit_distance::find_best_match_for_name;
1919
use rustc_span::edition::Edition;
2020
use rustc_span::source_map::FileLoader;
2121
use rustc_span::symbol::{sym, Symbol};
22+
use rustc_target::spec::Target;
2223
use session::{CompilerIO, EarlyErrorHandler};
23-
use std::env;
2424
use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
2525
use std::mem;
26+
use std::ops::Deref;
2627
use std::path::{Path, PathBuf};
2728
use std::sync::atomic::{AtomicBool, Ordering};
2829
use std::sync::{Arc, OnceLock};
2930
use std::thread;
31+
use std::{env, iter};
3032

3133
/// Function pointer type that constructs a new CodegenBackend.
3234
pub type MakeBackendFn = fn() -> Box<dyn CodegenBackend>;
@@ -75,24 +77,41 @@ pub fn create_session(
7577
};
7678

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

8191
// target_override is documented to be called before init(), so this is okay
8292
let target_override = backend.target_override(&sopts);
8393

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

86108
(backend, target)
87109
}
88-
None => {
89-
let _target = config::build_target_config(handler, &sopts, None, &sysroot);
110+
Some(make_codegen_backend) => {
111+
// N.B. `make_codegen_backend` takes precedence over `target.default_codegen_backend`,
112+
// which is ignored in this case.
90113

91-
let backend = get_codegen_backend(
92-
handler,
93-
&sopts.maybe_sysroot,
94-
sopts.unstable_opts.codegen_backend.as_deref(),
95-
);
114+
let backend = make_codegen_backend(&sopts);
96115

97116
// target_override is documented to be called before init(), so this is okay
98117
let target_override = backend.target_override(&sopts);
@@ -292,21 +311,25 @@ fn load_backend_from_dylib(handler: &EarlyErrorHandler, path: &Path) -> MakeBack
292311
/// A name of `None` indicates that the default backend should be used.
293312
pub fn get_codegen_backend(
294313
handler: &EarlyErrorHandler,
295-
maybe_sysroot: &Option<PathBuf>,
314+
sysroot: &Path,
296315
backend_name: Option<&str>,
316+
target: &Target,
297317
) -> Box<dyn CodegenBackend> {
298318
static LOAD: OnceLock<unsafe fn() -> Box<dyn CodegenBackend>> = OnceLock::new();
299319

300320
let load = LOAD.get_or_init(|| {
301-
let default_codegen_backend = option_env!("CFG_DEFAULT_CODEGEN_BACKEND").unwrap_or("llvm");
321+
let backend = backend_name
322+
.or(target.default_codegen_backend.as_deref())
323+
.or(option_env!("CFG_DEFAULT_CODEGEN_BACKEND"))
324+
.unwrap_or("llvm");
302325

303-
match backend_name.unwrap_or(default_codegen_backend) {
326+
match backend {
304327
filename if filename.contains('.') => {
305328
load_backend_from_dylib(handler, filename.as_ref())
306329
}
307330
#[cfg(feature = "llvm")]
308331
"llvm" => rustc_codegen_llvm::LlvmCodegenBackend::new,
309-
backend_name => get_codegen_sysroot(handler, maybe_sysroot, backend_name),
332+
backend_name => get_codegen_sysroot(handler, sysroot, backend_name),
310333
}
311334
});
312335

@@ -340,7 +363,7 @@ fn get_rustc_path_inner(bin_path: &str) -> Option<PathBuf> {
340363

341364
fn get_codegen_sysroot(
342365
handler: &EarlyErrorHandler,
343-
maybe_sysroot: &Option<PathBuf>,
366+
sysroot: &Path,
344367
backend_name: &str,
345368
) -> MakeBackendFn {
346369
// For now we only allow this function to be called once as it'll dlopen a
@@ -357,9 +380,8 @@ fn get_codegen_sysroot(
357380
let target = session::config::host_triple();
358381
let sysroot_candidates = sysroot_candidates();
359382

360-
let sysroot = maybe_sysroot
361-
.iter()
362-
.chain(sysroot_candidates.iter())
383+
let sysroot = iter::once(sysroot)
384+
.chain(sysroot_candidates.iter().map(<_>::deref))
363385
.map(|sysroot| {
364386
filesearch::make_target_lib_path(sysroot, target).with_file_name("codegen-backends")
365387
})

compiler/rustc_target/src/spec/mod.rs

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

2113+
/// Default codegen backend used for this target. Defaults to `None`.
2114+
///
2115+
/// If `None`, then `CFG_DEFAULT_CODEGEN_BACKEND` environmental variable captured when
2116+
/// compiling `rustc` will be used instead (or llvm if it is not set).
2117+
///
2118+
/// N.B. when *using* the compiler, backend can always be overriden with `-Zcodegen-backend`.
2119+
pub default_codegen_backend: Option<StaticCow<str>>,
2120+
21132121
/// Whether to generate trap instructions in places where optimization would
21142122
/// otherwise produce control flow that falls through into unrelated memory.
21152123
pub trap_unreachable: bool,
@@ -2418,6 +2426,7 @@ impl Default for TargetOptions {
24182426
stack_probes: StackProbeType::None,
24192427
min_global_align: None,
24202428
default_codegen_units: None,
2429+
default_codegen_backend: None,
24212430
trap_unreachable: true,
24222431
requires_lto: false,
24232432
singlethread: false,

0 commit comments

Comments
 (0)