Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit a03d19e

Browse files
committedFeb 14, 2024
Allow targets to override default codegen backend
1 parent ee9c7c9 commit a03d19e

File tree

7 files changed

+130
-46
lines changed

7 files changed

+130
-46
lines changed
 

‎compiler/rustc_driver_impl/src/lib.rs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ use rustc_session::config::{nightly_options, CG_OPTIONS, Z_OPTIONS};
3535
use rustc_session::config::{ErrorOutputType, Input, OutFileName, OutputType};
3636
use rustc_session::getopts::{self, Matches};
3737
use rustc_session::lint::{Lint, LintId};
38-
use rustc_session::{config, EarlyDiagCtxt, Session};
38+
use rustc_session::{config, filesearch, EarlyDiagCtxt, Session};
3939
use rustc_span::def_id::LOCAL_CRATE;
4040
use rustc_span::source_map::FileLoader;
4141
use rustc_span::symbol::sym;
@@ -887,7 +887,13 @@ pub fn version_at_macro_invocation(
887887

888888
let debug_flags = matches.opt_strs("Z");
889889
let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend="));
890-
get_codegen_backend(early_dcx, &None, backend_name).print_version();
890+
let opts = config::Options::default();
891+
let sysroot = opts.maybe_sysroot.clone().unwrap_or_else(|| {
892+
filesearch::get_or_default_sysroot().expect("Failed finding sysroot")
893+
});
894+
let target = config::build_target_config(early_dcx, &opts, None, &sysroot);
895+
896+
get_codegen_backend(early_dcx, &sysroot, backend_name, &target).print_version();
891897
}
892898
}
893899

@@ -1092,7 +1098,14 @@ pub fn describe_flag_categories(early_dcx: &EarlyDiagCtxt, matches: &Matches) ->
10921098

10931099
if cg_flags.iter().any(|x| *x == "passes=list") {
10941100
let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend="));
1095-
get_codegen_backend(early_dcx, &None, backend_name).print_passes();
1101+
1102+
let opts = config::Options::default();
1103+
let sysroot = opts.maybe_sysroot.clone().unwrap_or_else(|| {
1104+
filesearch::get_or_default_sysroot().expect("Failed finding sysroot")
1105+
});
1106+
let target = config::build_target_config(early_dcx, &opts, None, &sysroot);
1107+
1108+
get_codegen_backend(early_dcx, &sysroot, backend_name, &target).print_passes();
10961109
return true;
10971110
}
10981111

‎compiler/rustc_interface/src/interface.rs

Lines changed: 63 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use rustc_parse::maybe_new_parser_from_source_str;
1616
use rustc_query_impl::QueryCtxt;
1717
use rustc_query_system::query::print_query_stack;
1818
use rustc_session::config::{self, Cfg, CheckCfg, ExpectedValues, Input, OutFileName};
19-
use rustc_session::filesearch::sysroot_candidates;
19+
use rustc_session::filesearch::{self, sysroot_candidates};
2020
use rustc_session::parse::ParseSess;
2121
use rustc_session::{lint, CompilerIO, EarlyDiagCtxt, Session};
2222
use rustc_span::source_map::FileLoader;
@@ -336,14 +336,66 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
336336

337337
let early_dcx = EarlyDiagCtxt::new(config.opts.error_format);
338338

339-
let codegen_backend = if let Some(make_codegen_backend) = config.make_codegen_backend {
340-
make_codegen_backend(&config.opts)
341-
} else {
342-
util::get_codegen_backend(
343-
&early_dcx,
344-
&config.opts.maybe_sysroot,
345-
config.opts.unstable_opts.codegen_backend.as_deref(),
346-
)
339+
let sysroot = match &config.opts.maybe_sysroot {
340+
Some(sysroot) => sysroot.clone(),
341+
None => filesearch::get_or_default_sysroot().expect("Failed finding sysroot"),
342+
};
343+
344+
let (codegen_backend, target_cfg) = match config.make_codegen_backend {
345+
None => {
346+
// Build a target without override, so that it can override the backend if needed
347+
let target =
348+
config::build_target_config(&early_dcx, &config.opts, None, &sysroot);
349+
350+
let backend = util::get_codegen_backend(
351+
&early_dcx,
352+
&sysroot,
353+
config.opts.unstable_opts.codegen_backend.as_deref(),
354+
&target,
355+
);
356+
357+
// target_override is documented to be called before init(), so this is okay
358+
let target_override = backend.target_override(&config.opts);
359+
360+
// Assert that we don't use target's override of the backend and
361+
// backend's override of the target at the same time
362+
if config.opts.unstable_opts.codegen_backend.is_none()
363+
&& target.default_codegen_backend.is_some()
364+
&& target_override.is_some()
365+
{
366+
rustc_middle::bug!(
367+
"Codegen backend requested target override even though the target requested the backend"
368+
);
369+
}
370+
371+
// Re-build target with the (potential) override
372+
let target = config::build_target_config(
373+
&early_dcx,
374+
&config.opts,
375+
target_override,
376+
&sysroot,
377+
);
378+
379+
(backend, target)
380+
}
381+
Some(make_codegen_backend) => {
382+
// N.B. `make_codegen_backend` takes precedence over `target.default_codegen_backend`,
383+
// which is ignored in this case.
384+
385+
let backend = make_codegen_backend(&config.opts);
386+
387+
// target_override is documented to be called before init(), so this is okay
388+
let target_override = backend.target_override(&config.opts);
389+
390+
let target = config::build_target_config(
391+
&early_dcx,
392+
&config.opts,
393+
target_override,
394+
&sysroot,
395+
);
396+
397+
(backend, target)
398+
}
347399
};
348400

349401
let temps_dir = config.opts.unstable_opts.temps_dir.as_deref().map(PathBuf::from);
@@ -364,9 +416,6 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
364416
let mut locale_resources = Vec::from(config.locale_resources);
365417
locale_resources.push(codegen_backend.locale_resource());
366418

367-
// target_override is documented to be called before init(), so this is okay
368-
let target_override = codegen_backend.target_override(&config.opts);
369-
370419
let mut sess = rustc_session::build_session(
371420
early_dcx,
372421
config.opts,
@@ -381,7 +430,8 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
381430
locale_resources,
382431
config.lint_caps,
383432
config.file_loader,
384-
target_override,
433+
target_cfg,
434+
sysroot,
385435
util::rustc_version_str().unwrap_or("unknown"),
386436
config.ice_file,
387437
config.using_internal_features,

‎compiler/rustc_interface/src/tests.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,17 @@ fn mk_session(matches: getopts::Matches) -> (Session, Cfg) {
3737
output_file: None,
3838
temps_dir,
3939
};
40+
41+
let sysroot = match &sessopts.maybe_sysroot {
42+
Some(sysroot) => sysroot.clone(),
43+
None => {
44+
rustc_session::filesearch::get_or_default_sysroot().expect("Failed finding sysroot")
45+
}
46+
};
47+
48+
let target_cfg =
49+
rustc_session::config::build_target_config(&early_dcx, &sessopts, None, &sysroot);
50+
4051
let sess = build_session(
4152
early_dcx,
4253
sessopts,
@@ -46,7 +57,8 @@ fn mk_session(matches: getopts::Matches) -> (Session, Cfg) {
4657
vec![],
4758
Default::default(),
4859
None,
49-
None,
60+
target_cfg,
61+
sysroot,
5062
"",
5163
None,
5264
Arc::default(),

‎compiler/rustc_interface/src/util.rs

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,15 @@ use rustc_session::{filesearch, output, Session};
1414
use rustc_span::edit_distance::find_best_match_for_name;
1515
use rustc_span::edition::Edition;
1616
use rustc_span::symbol::{sym, Symbol};
17+
use rustc_target::spec::Target;
1718
use session::EarlyDiagCtxt;
18-
use std::env;
1919
use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
2020
use std::mem;
2121
use std::path::{Path, PathBuf};
2222
use std::sync::atomic::{AtomicBool, Ordering};
2323
use std::sync::OnceLock;
2424
use std::thread;
25+
use std::{env, iter};
2526

2627
/// Function pointer type that constructs a new CodegenBackend.
2728
pub type MakeBackendFn = fn() -> Box<dyn CodegenBackend>;
@@ -192,21 +193,25 @@ fn load_backend_from_dylib(early_dcx: &EarlyDiagCtxt, path: &Path) -> MakeBacken
192193
/// A name of `None` indicates that the default backend should be used.
193194
pub fn get_codegen_backend(
194195
early_dcx: &EarlyDiagCtxt,
195-
maybe_sysroot: &Option<PathBuf>,
196+
sysroot: &Path,
196197
backend_name: Option<&str>,
198+
target: &Target,
197199
) -> Box<dyn CodegenBackend> {
198200
static LOAD: OnceLock<unsafe fn() -> Box<dyn CodegenBackend>> = OnceLock::new();
199201

200202
let load = LOAD.get_or_init(|| {
201-
let default_codegen_backend = option_env!("CFG_DEFAULT_CODEGEN_BACKEND").unwrap_or("llvm");
203+
let backend = backend_name
204+
.or(target.default_codegen_backend.as_deref())
205+
.or(option_env!("CFG_DEFAULT_CODEGEN_BACKEND"))
206+
.unwrap_or("llvm");
202207

203-
match backend_name.unwrap_or(default_codegen_backend) {
208+
match backend {
204209
filename if filename.contains('.') => {
205210
load_backend_from_dylib(early_dcx, filename.as_ref())
206211
}
207212
#[cfg(feature = "llvm")]
208213
"llvm" => rustc_codegen_llvm::LlvmCodegenBackend::new,
209-
backend_name => get_codegen_sysroot(early_dcx, maybe_sysroot, backend_name),
214+
backend_name => get_codegen_sysroot(early_dcx, sysroot, backend_name),
210215
}
211216
});
212217

@@ -240,7 +245,7 @@ fn get_rustc_path_inner(bin_path: &str) -> Option<PathBuf> {
240245

241246
fn get_codegen_sysroot(
242247
early_dcx: &EarlyDiagCtxt,
243-
maybe_sysroot: &Option<PathBuf>,
248+
sysroot: &Path,
244249
backend_name: &str,
245250
) -> MakeBackendFn {
246251
// For now we only allow this function to be called once as it'll dlopen a
@@ -257,28 +262,28 @@ fn get_codegen_sysroot(
257262
let target = session::config::host_triple();
258263
let sysroot_candidates = sysroot_candidates();
259264

260-
let sysroot = maybe_sysroot
261-
.iter()
262-
.chain(sysroot_candidates.iter())
265+
let sysroot = iter::once(sysroot)
266+
.chain(sysroot_candidates.iter().map(<_>::as_ref))
263267
.map(|sysroot| {
264268
filesearch::make_target_lib_path(sysroot, target).with_file_name("codegen-backends")
265269
})
266270
.find(|f| {
267271
info!("codegen backend candidate: {}", f.display());
268272
f.exists()
269-
});
270-
let sysroot = sysroot.unwrap_or_else(|| {
271-
let candidates = sysroot_candidates
272-
.iter()
273-
.map(|p| p.display().to_string())
274-
.collect::<Vec<_>>()
275-
.join("\n* ");
276-
let err = format!(
277-
"failed to find a `codegen-backends` folder \
273+
})
274+
.unwrap_or_else(|| {
275+
let candidates = sysroot_candidates
276+
.iter()
277+
.map(|p| p.display().to_string())
278+
.collect::<Vec<_>>()
279+
.join("\n* ");
280+
let err = format!(
281+
"failed to find a `codegen-backends` folder \
278282
in the sysroot candidates:\n* {candidates}"
279-
);
280-
early_dcx.early_fatal(err);
281-
});
283+
);
284+
early_dcx.early_fatal(err);
285+
});
286+
282287
info!("probing {} for a codegen backend", sysroot.display());
283288

284289
let d = sysroot.read_dir().unwrap_or_else(|e| {

‎compiler/rustc_session/src/config.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1558,7 +1558,7 @@ pub fn build_configuration(sess: &Session, mut user_cfg: Cfg) -> Cfg {
15581558
user_cfg
15591559
}
15601560

1561-
pub(super) fn build_target_config(
1561+
pub fn build_target_config(
15621562
early_dcx: &EarlyDiagCtxt,
15631563
opts: &Options,
15641564
target_override: Option<Target>,

‎compiler/rustc_session/src/session.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1034,7 +1034,8 @@ pub fn build_session(
10341034
fluent_resources: Vec<&'static str>,
10351035
driver_lint_caps: FxHashMap<lint::LintId, lint::Level>,
10361036
file_loader: Option<Box<dyn FileLoader + Send + Sync + 'static>>,
1037-
target_override: Option<Target>,
1037+
target_cfg: Target,
1038+
sysroot: PathBuf,
10381039
cfg_version: &'static str,
10391040
ice_file: Option<PathBuf>,
10401041
using_internal_features: Arc<AtomicBool>,
@@ -1051,12 +1052,6 @@ pub fn build_session(
10511052
let cap_lints_allow = sopts.lint_cap.is_some_and(|cap| cap == lint::Allow);
10521053
let can_emit_warnings = !(warnings_allow || cap_lints_allow);
10531054

1054-
let sysroot = match &sopts.maybe_sysroot {
1055-
Some(sysroot) => sysroot.clone(),
1056-
None => filesearch::get_or_default_sysroot().expect("Failed finding sysroot"),
1057-
};
1058-
1059-
let target_cfg = config::build_target_config(&early_dcx, &sopts, target_override, &sysroot);
10601055
let host_triple = TargetTriple::from_triple(config::host_triple());
10611056
let (host, target_warnings) = Target::search(&host_triple, &sysroot).unwrap_or_else(|e| {
10621057
early_dcx.early_fatal(format!("Error loading host specification: {e}"))

‎compiler/rustc_target/src/spec/mod.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2044,6 +2044,14 @@ pub struct TargetOptions {
20442044
/// Default number of codegen units to use in debug mode
20452045
pub default_codegen_units: Option<u64>,
20462046

2047+
/// Default codegen backend used for this target. Defaults to `None`.
2048+
///
2049+
/// If `None`, then `CFG_DEFAULT_CODEGEN_BACKEND` environmental variable captured when
2050+
/// compiling `rustc` will be used instead (or llvm if it is not set).
2051+
///
2052+
/// N.B. when *using* the compiler, backend can always be overriden with `-Zcodegen-backend`.
2053+
pub default_codegen_backend: Option<StaticCow<str>>,
2054+
20472055
/// Whether to generate trap instructions in places where optimization would
20482056
/// otherwise produce control flow that falls through into unrelated memory.
20492057
pub trap_unreachable: bool,
@@ -2350,6 +2358,7 @@ impl Default for TargetOptions {
23502358
stack_probes: StackProbeType::None,
23512359
min_global_align: None,
23522360
default_codegen_units: None,
2361+
default_codegen_backend: None,
23532362
trap_unreachable: true,
23542363
requires_lto: false,
23552364
singlethread: false,

0 commit comments

Comments
 (0)
Please sign in to comment.