Skip to content

Commit cf798c1

Browse files
committed
Add support for using cg_clif to bootstrap rustc
1 parent 596b0d5 commit cf798c1

File tree

12 files changed

+432
-39
lines changed

12 files changed

+432
-39
lines changed

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ members = [
3131
]
3232
exclude = [
3333
"build",
34+
"compiler/rustc_codegen_cranelift",
3435
# HACK(eddyb) This hardcodes the fact that our CI uses `/checkout/obj`.
3536
"obj",
3637
]

compiler/rustc_driver/src/lib.rs

+12-23
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use rustc_errors::registry::{InvalidErrorCode, Registry};
2222
use rustc_errors::{ErrorReported, PResult};
2323
use rustc_feature::{find_gated_cfg, UnstableFeatures};
2424
use rustc_hir::def_id::LOCAL_CRATE;
25-
use rustc_interface::util::{collect_crate_types, get_builtin_codegen_backend};
25+
use rustc_interface::util::{self, collect_crate_types, get_builtin_codegen_backend};
2626
use rustc_interface::{interface, Queries};
2727
use rustc_lint::LintStore;
2828
use rustc_metadata::locator;
@@ -793,37 +793,24 @@ impl RustcDefaultCalls {
793793
}
794794
}
795795

796-
/// Returns a version string such as "0.12.0-dev".
797-
fn release_str() -> Option<&'static str> {
798-
option_env!("CFG_RELEASE")
799-
}
800-
801-
/// Returns the full SHA1 hash of HEAD of the Git repo from which rustc was built.
802-
fn commit_hash_str() -> Option<&'static str> {
803-
option_env!("CFG_VER_HASH")
804-
}
805-
806-
/// Returns the "commit date" of HEAD of the Git repo from which rustc was built as a static string.
807-
fn commit_date_str() -> Option<&'static str> {
808-
option_env!("CFG_VER_DATE")
809-
}
810-
811796
/// Prints version information
812797
pub fn version(binary: &str, matches: &getopts::Matches) {
813798
let verbose = matches.opt_present("verbose");
814799

815-
println!("{} {}", binary, option_env!("CFG_VERSION").unwrap_or("unknown version"));
800+
println!("{} {}", binary, util::version_str().unwrap_or("unknown version"));
816801

817802
if verbose {
818803
fn unw(x: Option<&str>) -> &str {
819804
x.unwrap_or("unknown")
820805
}
821806
println!("binary: {}", binary);
822-
println!("commit-hash: {}", unw(commit_hash_str()));
823-
println!("commit-date: {}", unw(commit_date_str()));
807+
println!("commit-hash: {}", unw(util::commit_hash_str()));
808+
println!("commit-date: {}", unw(util::commit_date_str()));
824809
println!("host: {}", config::host_triple());
825-
println!("release: {}", unw(release_str()));
826-
get_builtin_codegen_backend("llvm")().print_version();
810+
println!("release: {}", unw(util::release_str()));
811+
if cfg!(llvm) {
812+
get_builtin_codegen_backend("llvm")().print_version();
813+
}
827814
}
828815
}
829816

@@ -1109,7 +1096,9 @@ pub fn handle_options(args: &[String]) -> Option<getopts::Matches> {
11091096
}
11101097

11111098
if cg_flags.iter().any(|x| *x == "passes=list") {
1112-
get_builtin_codegen_backend("llvm")().print_passes();
1099+
if cfg!(llvm) {
1100+
get_builtin_codegen_backend("llvm")().print_passes();
1101+
}
11131102
return None;
11141103
}
11151104

@@ -1237,7 +1226,7 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
12371226
format!("we would appreciate a bug report: {}", bug_report_url).into(),
12381227
format!(
12391228
"rustc {} running on {}",
1240-
option_env!("CFG_VERSION").unwrap_or("unknown_version"),
1229+
util::version_str().unwrap_or("unknown_version"),
12411230
config::host_triple()
12421231
)
12431232
.into(),

compiler/rustc_interface/src/util.rs

+128-7
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,13 @@ use rustc_span::source_map::FileLoader;
2424
use rustc_span::symbol::{sym, Symbol};
2525
use smallvec::SmallVec;
2626
use std::env;
27+
use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
2728
use std::io::{self, Write};
2829
use std::lazy::SyncOnceCell;
2930
use std::mem;
3031
use std::ops::DerefMut;
3132
use std::path::{Path, PathBuf};
33+
use std::sync::atomic::{AtomicBool, Ordering};
3234
use std::sync::{Arc, Mutex, Once};
3335
#[cfg(not(parallel_compiler))]
3436
use std::{panic, thread};
@@ -238,7 +240,19 @@ pub fn get_codegen_backend(sopts: &config::Options) -> Box<dyn CodegenBackend> {
238240
static mut LOAD: fn() -> Box<dyn CodegenBackend> = || unreachable!();
239241

240242
INIT.call_once(|| {
241-
let codegen_name = sopts.debugging_opts.codegen_backend.as_deref().unwrap_or("llvm");
243+
#[cfg(feature = "llvm")]
244+
const DEFAULT_CODEGEN_BACKEND: &'static str = "llvm";
245+
246+
#[cfg(not(feature = "llvm"))]
247+
const DEFAULT_CODEGEN_BACKEND: &'static str = "cranelift";
248+
249+
let codegen_name = sopts
250+
.debugging_opts
251+
.codegen_backend
252+
.as_ref()
253+
.map(|name| &name[..])
254+
.unwrap_or(DEFAULT_CODEGEN_BACKEND);
255+
242256
let backend = match codegen_name {
243257
filename if filename.contains('.') => load_backend_from_dylib(filename.as_ref()),
244258
codegen_name => get_builtin_codegen_backend(codegen_name),
@@ -367,15 +381,102 @@ fn sysroot_candidates() -> Vec<PathBuf> {
367381
}
368382

369383
pub fn get_builtin_codegen_backend(backend_name: &str) -> fn() -> Box<dyn CodegenBackend> {
370-
#[cfg(feature = "llvm")]
371-
{
372-
if backend_name == "llvm" {
373-
return rustc_codegen_llvm::LlvmCodegenBackend::new;
384+
match backend_name {
385+
#[cfg(feature = "llvm")]
386+
"llvm" => rustc_codegen_llvm::LlvmCodegenBackend::new,
387+
_ => get_codegen_sysroot(backend_name),
388+
}
389+
}
390+
391+
pub fn get_codegen_sysroot(backend_name: &str) -> fn() -> Box<dyn CodegenBackend> {
392+
// For now we only allow this function to be called once as it'll dlopen a
393+
// few things, which seems to work best if we only do that once. In
394+
// general this assertion never trips due to the once guard in `get_codegen_backend`,
395+
// but there's a few manual calls to this function in this file we protect
396+
// against.
397+
static LOADED: AtomicBool = AtomicBool::new(false);
398+
assert!(
399+
!LOADED.fetch_or(true, Ordering::SeqCst),
400+
"cannot load the default codegen backend twice"
401+
);
402+
403+
let target = session::config::host_triple();
404+
let sysroot_candidates = sysroot_candidates();
405+
406+
let sysroot = sysroot_candidates
407+
.iter()
408+
.map(|sysroot| {
409+
let libdir = filesearch::relative_target_lib_path(&sysroot, &target);
410+
sysroot.join(libdir).with_file_name("codegen-backends")
411+
})
412+
.filter(|f| {
413+
info!("codegen backend candidate: {}", f.display());
414+
f.exists()
415+
})
416+
.next();
417+
let sysroot = sysroot.unwrap_or_else(|| {
418+
let candidates = sysroot_candidates
419+
.iter()
420+
.map(|p| p.display().to_string())
421+
.collect::<Vec<_>>()
422+
.join("\n* ");
423+
let err = format!(
424+
"failed to find a `codegen-backends` folder \
425+
in the sysroot candidates:\n* {}",
426+
candidates
427+
);
428+
early_error(ErrorOutputType::default(), &err);
429+
});
430+
info!("probing {} for a codegen backend", sysroot.display());
431+
432+
let d = sysroot.read_dir().unwrap_or_else(|e| {
433+
let err = format!(
434+
"failed to load default codegen backend, couldn't \
435+
read `{}`: {}",
436+
sysroot.display(),
437+
e
438+
);
439+
early_error(ErrorOutputType::default(), &err);
440+
});
441+
442+
let mut file: Option<PathBuf> = None;
443+
444+
let expected_name =
445+
format!("rustc_codegen_{}-{}", backend_name, release_str().expect("CFG_RELEASE"));
446+
for entry in d.filter_map(|e| e.ok()) {
447+
let path = entry.path();
448+
let filename = match path.file_name().and_then(|s| s.to_str()) {
449+
Some(s) => s,
450+
None => continue,
451+
};
452+
if !(filename.starts_with(DLL_PREFIX) && filename.ends_with(DLL_SUFFIX)) {
453+
continue;
374454
}
455+
let name = &filename[DLL_PREFIX.len()..filename.len() - DLL_SUFFIX.len()];
456+
if name != expected_name {
457+
continue;
458+
}
459+
if let Some(ref prev) = file {
460+
let err = format!(
461+
"duplicate codegen backends found\n\
462+
first: {}\n\
463+
second: {}\n\
464+
",
465+
prev.display(),
466+
path.display()
467+
);
468+
early_error(ErrorOutputType::default(), &err);
469+
}
470+
file = Some(path.clone());
375471
}
376472

377-
let err = format!("unsupported builtin codegen backend `{}`", backend_name);
378-
early_error(ErrorOutputType::default(), &err);
473+
match file {
474+
Some(ref s) => load_backend_from_dylib(s),
475+
None => {
476+
let err = format!("unsupported builtin codegen backend `{}`", backend_name);
477+
early_error(ErrorOutputType::default(), &err);
478+
}
479+
}
379480
}
380481

381482
pub(crate) fn compute_crate_disambiguator(session: &Session) -> CrateDisambiguator {
@@ -782,3 +883,23 @@ impl<'a> MutVisitor for ReplaceBodyWithLoop<'a, '_> {
782883
noop_visit_mac(mac, self)
783884
}
784885
}
886+
887+
/// Returns a version string such as "rustc 1.46.0 (04488afe3 2020-08-24)"
888+
pub fn version_str() -> Option<&'static str> {
889+
option_env!("CFG_VERSION")
890+
}
891+
892+
/// Returns a version string such as "0.12.0-dev".
893+
pub fn release_str() -> Option<&'static str> {
894+
option_env!("CFG_RELEASE")
895+
}
896+
897+
/// Returns the full SHA1 hash of HEAD of the Git repo from which rustc was built.
898+
pub fn commit_hash_str() -> Option<&'static str> {
899+
option_env!("CFG_VER_HASH")
900+
}
901+
902+
/// Returns the "commit date" of HEAD of the Git repo from which rustc was built as a static string.
903+
pub fn commit_date_str() -> Option<&'static str> {
904+
option_env!("CFG_VER_DATE")
905+
}

config.toml.example

+1-1
Original file line numberDiff line numberDiff line change
@@ -478,7 +478,7 @@ changelog-seen = 2
478478

479479
# This is an array of the codegen backends that will be compiled for the rustc
480480
# that's being compiled. The default is to only build the LLVM codegen backend,
481-
# and currently the only standard option supported is `"llvm"`
481+
# and currently the only standard options supported are `"llvm"` and `"cranelift"`.
482482
#codegen-backends = ["llvm"]
483483

484484
# Indicates whether LLD will be compiled and made available in the sysroot for

rustfmt.toml

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ ignore = [
1616
# do not format submodules
1717
"library/backtrace",
1818
"library/stdarch",
19+
"compiler/rustc_codegen_cranelift",
1920
"src/doc/book",
2021
"src/doc/edition-guide",
2122
"src/doc/embedded-book",

src/bootstrap/bootstrap.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -962,8 +962,12 @@ def ensure_vendored(self):
962962
# the rust git repository is updated. Normal development usually does
963963
# not use vendoring, so hopefully this isn't too much of a problem.
964964
if self.use_vendored_sources and not os.path.exists(vendor_dir):
965-
run([self.cargo(), "vendor", "--sync=./src/tools/rust-analyzer/Cargo.toml"],
966-
verbose=self.verbose, cwd=self.rust_root)
965+
run([
966+
self.cargo(),
967+
"vendor",
968+
"--sync=./src/tools/rust-analyzer/Cargo.toml",
969+
"--sync=./compiler/rustc_codegen_cranelift/Cargo.toml",
970+
], verbose=self.verbose, cwd=self.rust_root)
967971

968972

969973
def bootstrap(help_triggered):

src/bootstrap/builder.rs

+32-5
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,7 @@ impl<'a> Builder<'a> {
344344
Kind::Build => describe!(
345345
compile::Std,
346346
compile::Rustc,
347+
compile::CodegenBackend,
347348
compile::StartupObjects,
348349
tool::BuildManifest,
349350
tool::Rustbook,
@@ -370,9 +371,14 @@ impl<'a> Builder<'a> {
370371
tool::CargoMiri,
371372
native::Lld
372373
),
373-
Kind::Check | Kind::Clippy | Kind::Fix | Kind::Format => {
374-
describe!(check::Std, check::Rustc, check::Rustdoc, check::Clippy, check::Bootstrap)
375-
}
374+
Kind::Check | Kind::Clippy | Kind::Fix | Kind::Format => describe!(
375+
check::Std,
376+
check::Rustc,
377+
check::Rustdoc,
378+
check::CodegenBackend,
379+
check::Clippy,
380+
check::Bootstrap
381+
),
376382
Kind::Test => describe!(
377383
crate::toolstate::ToolStateCheck,
378384
test::ExpandYamlAnchors,
@@ -630,6 +636,10 @@ impl<'a> Builder<'a> {
630636
self.ensure(Libdir { compiler, target })
631637
}
632638

639+
pub fn sysroot_codegen_backends(&self, compiler: Compiler) -> PathBuf {
640+
self.sysroot_libdir(compiler, compiler.host).with_file_name("codegen-backends")
641+
}
642+
633643
/// Returns the compiler's libdir where it stores the dynamic libraries that
634644
/// it itself links against.
635645
///
@@ -698,6 +708,15 @@ impl<'a> Builder<'a> {
698708
}
699709
}
700710

711+
/// Gets the paths to all of the compiler's codegen backends.
712+
fn codegen_backends(&self, compiler: Compiler) -> impl Iterator<Item = PathBuf> {
713+
fs::read_dir(self.sysroot_codegen_backends(compiler))
714+
.into_iter()
715+
.flatten()
716+
.filter_map(Result::ok)
717+
.map(|entry| entry.path())
718+
}
719+
701720
pub fn rustdoc(&self, compiler: Compiler) -> PathBuf {
702721
self.ensure(tool::Rustdoc { compiler })
703722
}
@@ -762,6 +781,12 @@ impl<'a> Builder<'a> {
762781
let mut cargo = Command::new(&self.initial_cargo);
763782
let out_dir = self.stage_out(compiler, mode);
764783

784+
// Codegen backends are not yet tracked by -Zbinary-dep-depinfo,
785+
// so we need to explicitly clear out if they've been updated.
786+
for backend in self.codegen_backends(compiler) {
787+
self.clear_if_dirty(&out_dir, &backend);
788+
}
789+
765790
if cmd == "doc" || cmd == "rustdoc" {
766791
let my_out = match mode {
767792
// This is the intended out directory for compiler documentation.
@@ -843,7 +868,7 @@ impl<'a> Builder<'a> {
843868

844869
match mode {
845870
Mode::Std | Mode::ToolBootstrap | Mode::ToolStd => {}
846-
Mode::Rustc | Mode::ToolRustc => {
871+
Mode::Rustc | Mode::Codegen | Mode::ToolRustc => {
847872
// Build proc macros both for the host and the target
848873
if target != compiler.host && cmd != "check" {
849874
cargo.arg("-Zdual-proc-macros");
@@ -904,6 +929,8 @@ impl<'a> Builder<'a> {
904929
// problem, somehow -- not really clear why -- but we know that this
905930
// fixes things.
906931
Mode::ToolRustc => metadata.push_str("tool-rustc"),
932+
// Same for codegen backends.
933+
Mode::Codegen => metadata.push_str("codegen"),
907934
_ => {}
908935
}
909936
cargo.env("__CARGO_DEFAULT_LIB_METADATA", &metadata);
@@ -1030,7 +1057,7 @@ impl<'a> Builder<'a> {
10301057
}
10311058

10321059
let debuginfo_level = match mode {
1033-
Mode::Rustc => self.config.rust_debuginfo_level_rustc,
1060+
Mode::Rustc | Mode::Codegen => self.config.rust_debuginfo_level_rustc,
10341061
Mode::Std => self.config.rust_debuginfo_level_std,
10351062
Mode::ToolBootstrap | Mode::ToolStd | Mode::ToolRustc => {
10361063
self.config.rust_debuginfo_level_tools

0 commit comments

Comments
 (0)