Add support for using cg_clif to bootstrap rustc
This commit is contained in:
parent
596b0d5027
commit
cf798c1ec6
12 changed files with 432 additions and 39 deletions
|
@ -24,11 +24,13 @@ use rustc_span::source_map::FileLoader;
|
|||
use rustc_span::symbol::{sym, Symbol};
|
||||
use smallvec::SmallVec;
|
||||
use std::env;
|
||||
use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
|
||||
use std::io::{self, Write};
|
||||
use std::lazy::SyncOnceCell;
|
||||
use std::mem;
|
||||
use std::ops::DerefMut;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::{Arc, Mutex, Once};
|
||||
#[cfg(not(parallel_compiler))]
|
||||
use std::{panic, thread};
|
||||
|
@ -238,7 +240,19 @@ pub fn get_codegen_backend(sopts: &config::Options) -> Box<dyn CodegenBackend> {
|
|||
static mut LOAD: fn() -> Box<dyn CodegenBackend> = || unreachable!();
|
||||
|
||||
INIT.call_once(|| {
|
||||
let codegen_name = sopts.debugging_opts.codegen_backend.as_deref().unwrap_or("llvm");
|
||||
#[cfg(feature = "llvm")]
|
||||
const DEFAULT_CODEGEN_BACKEND: &'static str = "llvm";
|
||||
|
||||
#[cfg(not(feature = "llvm"))]
|
||||
const DEFAULT_CODEGEN_BACKEND: &'static str = "cranelift";
|
||||
|
||||
let codegen_name = sopts
|
||||
.debugging_opts
|
||||
.codegen_backend
|
||||
.as_ref()
|
||||
.map(|name| &name[..])
|
||||
.unwrap_or(DEFAULT_CODEGEN_BACKEND);
|
||||
|
||||
let backend = match codegen_name {
|
||||
filename if filename.contains('.') => load_backend_from_dylib(filename.as_ref()),
|
||||
codegen_name => get_builtin_codegen_backend(codegen_name),
|
||||
|
@ -367,15 +381,102 @@ fn sysroot_candidates() -> Vec<PathBuf> {
|
|||
}
|
||||
|
||||
pub fn get_builtin_codegen_backend(backend_name: &str) -> fn() -> Box<dyn CodegenBackend> {
|
||||
#[cfg(feature = "llvm")]
|
||||
{
|
||||
if backend_name == "llvm" {
|
||||
return rustc_codegen_llvm::LlvmCodegenBackend::new;
|
||||
match backend_name {
|
||||
#[cfg(feature = "llvm")]
|
||||
"llvm" => rustc_codegen_llvm::LlvmCodegenBackend::new,
|
||||
_ => get_codegen_sysroot(backend_name),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_codegen_sysroot(backend_name: &str) -> fn() -> Box<dyn CodegenBackend> {
|
||||
// For now we only allow this function to be called once as it'll dlopen a
|
||||
// few things, which seems to work best if we only do that once. In
|
||||
// general this assertion never trips due to the once guard in `get_codegen_backend`,
|
||||
// but there's a few manual calls to this function in this file we protect
|
||||
// against.
|
||||
static LOADED: AtomicBool = AtomicBool::new(false);
|
||||
assert!(
|
||||
!LOADED.fetch_or(true, Ordering::SeqCst),
|
||||
"cannot load the default codegen backend twice"
|
||||
);
|
||||
|
||||
let target = session::config::host_triple();
|
||||
let sysroot_candidates = sysroot_candidates();
|
||||
|
||||
let sysroot = sysroot_candidates
|
||||
.iter()
|
||||
.map(|sysroot| {
|
||||
let libdir = filesearch::relative_target_lib_path(&sysroot, &target);
|
||||
sysroot.join(libdir).with_file_name("codegen-backends")
|
||||
})
|
||||
.filter(|f| {
|
||||
info!("codegen backend candidate: {}", f.display());
|
||||
f.exists()
|
||||
})
|
||||
.next();
|
||||
let sysroot = sysroot.unwrap_or_else(|| {
|
||||
let candidates = sysroot_candidates
|
||||
.iter()
|
||||
.map(|p| p.display().to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n* ");
|
||||
let err = format!(
|
||||
"failed to find a `codegen-backends` folder \
|
||||
in the sysroot candidates:\n* {}",
|
||||
candidates
|
||||
);
|
||||
early_error(ErrorOutputType::default(), &err);
|
||||
});
|
||||
info!("probing {} for a codegen backend", sysroot.display());
|
||||
|
||||
let d = sysroot.read_dir().unwrap_or_else(|e| {
|
||||
let err = format!(
|
||||
"failed to load default codegen backend, couldn't \
|
||||
read `{}`: {}",
|
||||
sysroot.display(),
|
||||
e
|
||||
);
|
||||
early_error(ErrorOutputType::default(), &err);
|
||||
});
|
||||
|
||||
let mut file: Option<PathBuf> = None;
|
||||
|
||||
let expected_name =
|
||||
format!("rustc_codegen_{}-{}", backend_name, release_str().expect("CFG_RELEASE"));
|
||||
for entry in d.filter_map(|e| e.ok()) {
|
||||
let path = entry.path();
|
||||
let filename = match path.file_name().and_then(|s| s.to_str()) {
|
||||
Some(s) => s,
|
||||
None => continue,
|
||||
};
|
||||
if !(filename.starts_with(DLL_PREFIX) && filename.ends_with(DLL_SUFFIX)) {
|
||||
continue;
|
||||
}
|
||||
let name = &filename[DLL_PREFIX.len()..filename.len() - DLL_SUFFIX.len()];
|
||||
if name != expected_name {
|
||||
continue;
|
||||
}
|
||||
if let Some(ref prev) = file {
|
||||
let err = format!(
|
||||
"duplicate codegen backends found\n\
|
||||
first: {}\n\
|
||||
second: {}\n\
|
||||
",
|
||||
prev.display(),
|
||||
path.display()
|
||||
);
|
||||
early_error(ErrorOutputType::default(), &err);
|
||||
}
|
||||
file = Some(path.clone());
|
||||
}
|
||||
|
||||
let err = format!("unsupported builtin codegen backend `{}`", backend_name);
|
||||
early_error(ErrorOutputType::default(), &err);
|
||||
match file {
|
||||
Some(ref s) => load_backend_from_dylib(s),
|
||||
None => {
|
||||
let err = format!("unsupported builtin codegen backend `{}`", backend_name);
|
||||
early_error(ErrorOutputType::default(), &err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn compute_crate_disambiguator(session: &Session) -> CrateDisambiguator {
|
||||
|
@ -782,3 +883,23 @@ impl<'a> MutVisitor for ReplaceBodyWithLoop<'a, '_> {
|
|||
noop_visit_mac(mac, self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a version string such as "rustc 1.46.0 (04488afe3 2020-08-24)"
|
||||
pub fn version_str() -> Option<&'static str> {
|
||||
option_env!("CFG_VERSION")
|
||||
}
|
||||
|
||||
/// Returns a version string such as "0.12.0-dev".
|
||||
pub fn release_str() -> Option<&'static str> {
|
||||
option_env!("CFG_RELEASE")
|
||||
}
|
||||
|
||||
/// Returns the full SHA1 hash of HEAD of the Git repo from which rustc was built.
|
||||
pub fn commit_hash_str() -> Option<&'static str> {
|
||||
option_env!("CFG_VER_HASH")
|
||||
}
|
||||
|
||||
/// Returns the "commit date" of HEAD of the Git repo from which rustc was built as a static string.
|
||||
pub fn commit_date_str() -> Option<&'static str> {
|
||||
option_env!("CFG_VER_DATE")
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue