Allow linking a prebuilt optimized compiler-rt builtins library
Extend the <target>.optimized-compiler-builtins bootstrap option to accept a path to a prebuilt compiler-rt builtins library, and update compiler-builtins to enable optimized builtins without building compiler-rt builtins.
This commit is contained in:
@@ -1041,13 +1041,15 @@
|
|||||||
#runner = <none> (string)
|
#runner = <none> (string)
|
||||||
|
|
||||||
# Use the optimized LLVM C intrinsics for `compiler_builtins`, rather than Rust intrinsics
|
# Use the optimized LLVM C intrinsics for `compiler_builtins`, rather than Rust intrinsics
|
||||||
# on this target.
|
# on this target. Choosing true requires the LLVM submodule to be managed by bootstrap
|
||||||
# Requires the LLVM submodule to be managed by bootstrap (i.e. not external) so that `compiler-rt`
|
# (i.e. not external) so that `compiler-rt` sources are available.
|
||||||
# sources are available.
|
#
|
||||||
|
# Setting this to a path removes the requirement for a C toolchain, but requires setting the
|
||||||
|
# path to an existing library containing the builtins library from LLVM's compiler-rt.
|
||||||
#
|
#
|
||||||
# Setting this to `false` generates slower code, but removes the requirement for a C toolchain in
|
# Setting this to `false` generates slower code, but removes the requirement for a C toolchain in
|
||||||
# order to run `x check`.
|
# order to run `x check`.
|
||||||
#optimized-compiler-builtins = build.optimized-compiler-builtins (bool)
|
#optimized-compiler-builtins = build.optimized-compiler-builtins (bool or path)
|
||||||
|
|
||||||
# Link the compiler and LLVM against `jemalloc` instead of the default libc allocator.
|
# Link the compiler and LLVM against `jemalloc` instead of the default libc allocator.
|
||||||
# This overrides the global `rust.jemalloc` option. See that option for more info.
|
# This overrides the global `rust.jemalloc` option. See that option for more info.
|
||||||
|
|||||||
@@ -10,6 +10,16 @@ to be added as an explicit dependency in `Cargo.toml`.
|
|||||||
|
|
||||||
[`compiler-rt`]: https://github.com/llvm/llvm-project/tree/1b1dc505057322f4fa1110ef4f53c44347f52986/compiler-rt
|
[`compiler-rt`]: https://github.com/llvm/llvm-project/tree/1b1dc505057322f4fa1110ef4f53c44347f52986/compiler-rt
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
`compiler-builtins` can be configured with the following environment variables when the `c` feature
|
||||||
|
is enabled:
|
||||||
|
|
||||||
|
- `LLVM_COMPILER_RT_LIB`
|
||||||
|
- `RUST_COMPILER_RT_ROOT`
|
||||||
|
|
||||||
|
See `build.rs` for details.
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
See [CONTRIBUTING.md](CONTRIBUTING.md).
|
See [CONTRIBUTING.md](CONTRIBUTING.md).
|
||||||
|
|||||||
@@ -540,12 +540,20 @@ mod c {
|
|||||||
sources.extend(&[("__emutls_get_address", "emutls.c")]);
|
sources.extend(&[("__emutls_get_address", "emutls.c")]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Optionally, link against a prebuilt llvm compiler-rt containing the builtins
|
||||||
|
// library. Only the builtins library is required. On many platforms, this is
|
||||||
|
// available as a library named libclang_rt.builtins.a.
|
||||||
|
let link_against_prebuilt_rt = env::var_os("LLVM_COMPILER_RT_LIB").is_some();
|
||||||
|
|
||||||
// When compiling the C code we require the user to tell us where the
|
// When compiling the C code we require the user to tell us where the
|
||||||
// source code is, and this is largely done so when we're compiling as
|
// source code is, and this is largely done so when we're compiling as
|
||||||
// part of rust-lang/rust we can use the same llvm-project repository as
|
// part of rust-lang/rust we can use the same llvm-project repository as
|
||||||
// rust-lang/rust.
|
// rust-lang/rust.
|
||||||
let root = match env::var_os("RUST_COMPILER_RT_ROOT") {
|
let root = match env::var_os("RUST_COMPILER_RT_ROOT") {
|
||||||
Some(s) => PathBuf::from(s),
|
Some(s) => PathBuf::from(s),
|
||||||
|
// If a prebuild libcompiler-rt is provided, set a valid
|
||||||
|
// path to simplify later logic. Nothing should be compiled.
|
||||||
|
None if link_against_prebuilt_rt => PathBuf::new(),
|
||||||
None => {
|
None => {
|
||||||
panic!(
|
panic!(
|
||||||
"RUST_COMPILER_RT_ROOT is not set. You may need to run \
|
"RUST_COMPILER_RT_ROOT is not set. You may need to run \
|
||||||
@@ -553,7 +561,7 @@ mod c {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if !root.exists() {
|
if !link_against_prebuilt_rt && !root.exists() {
|
||||||
panic!("RUST_COMPILER_RT_ROOT={} does not exist", root.display());
|
panic!("RUST_COMPILER_RT_ROOT={} does not exist", root.display());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -569,7 +577,7 @@ mod c {
|
|||||||
let src_dir = root.join("lib/builtins");
|
let src_dir = root.join("lib/builtins");
|
||||||
if target.arch == "aarch64" && target.env != "msvc" && target.os != "uefi" {
|
if target.arch == "aarch64" && target.env != "msvc" && target.os != "uefi" {
|
||||||
// See below for why we're building these as separate libraries.
|
// See below for why we're building these as separate libraries.
|
||||||
build_aarch64_out_of_line_atomics_libraries(&src_dir, cfg);
|
build_aarch64_out_of_line_atomics_libraries(&src_dir, cfg, link_against_prebuilt_rt);
|
||||||
|
|
||||||
// Some run-time CPU feature detection is necessary, as well.
|
// Some run-time CPU feature detection is necessary, as well.
|
||||||
let cpu_model_src = if src_dir.join("cpu_model.c").exists() {
|
let cpu_model_src = if src_dir.join("cpu_model.c").exists() {
|
||||||
@@ -583,20 +591,45 @@ mod c {
|
|||||||
let mut added_sources = HashSet::new();
|
let mut added_sources = HashSet::new();
|
||||||
for (sym, src) in sources.map.iter() {
|
for (sym, src) in sources.map.iter() {
|
||||||
let src = src_dir.join(src);
|
let src = src_dir.join(src);
|
||||||
if added_sources.insert(src.clone()) {
|
if !link_against_prebuilt_rt && added_sources.insert(src.clone()) {
|
||||||
cfg.file(&src);
|
cfg.file(&src);
|
||||||
println!("cargo:rerun-if-changed={}", src.display());
|
println!("cargo:rerun-if-changed={}", src.display());
|
||||||
}
|
}
|
||||||
println!("cargo:rustc-cfg={}=\"optimized-c\"", sym);
|
println!("cargo:rustc-cfg={}=\"optimized-c\"", sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg.compile("libcompiler-rt.a");
|
if link_against_prebuilt_rt {
|
||||||
|
let rt_builtins_ext = PathBuf::from(env::var_os("LLVM_COMPILER_RT_LIB").unwrap());
|
||||||
|
if !rt_builtins_ext.exists() {
|
||||||
|
panic!(
|
||||||
|
"LLVM_COMPILER_RT_LIB={} does not exist",
|
||||||
|
rt_builtins_ext.display()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if let Some(dir) = rt_builtins_ext.parent() {
|
||||||
|
println!("cargo::rustc-link-search=native={}", dir.display());
|
||||||
|
}
|
||||||
|
if let Some(lib) = rt_builtins_ext.file_name() {
|
||||||
|
println!(
|
||||||
|
"cargo::rustc-link-lib=static:+verbatim={}",
|
||||||
|
lib.to_str().unwrap()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cfg.compile("libcompiler-rt.a");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_aarch64_out_of_line_atomics_libraries(builtins_dir: &Path, cfg: &mut cc::Build) {
|
fn build_aarch64_out_of_line_atomics_libraries(
|
||||||
|
builtins_dir: &Path,
|
||||||
|
cfg: &mut cc::Build,
|
||||||
|
link_against_prebuilt_rt: bool,
|
||||||
|
) {
|
||||||
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
|
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
|
||||||
let outlined_atomics_file = builtins_dir.join("aarch64").join("lse.S");
|
let outlined_atomics_file = builtins_dir.join("aarch64").join("lse.S");
|
||||||
println!("cargo:rerun-if-changed={}", outlined_atomics_file.display());
|
if !link_against_prebuilt_rt {
|
||||||
|
println!("cargo:rerun-if-changed={}", outlined_atomics_file.display());
|
||||||
|
}
|
||||||
|
|
||||||
cfg.include(&builtins_dir);
|
cfg.include(&builtins_dir);
|
||||||
|
|
||||||
@@ -609,6 +642,13 @@ mod c {
|
|||||||
for (model_number, model_name) in
|
for (model_number, model_name) in
|
||||||
&[(1, "relax"), (2, "acq"), (3, "rel"), (4, "acq_rel")]
|
&[(1, "relax"), (2, "acq"), (3, "rel"), (4, "acq_rel")]
|
||||||
{
|
{
|
||||||
|
let sym = format!("__aarch64_{}{}_{}", instruction_type, size, model_name);
|
||||||
|
println!("cargo:rustc-cfg={}=\"optimized-c\"", sym);
|
||||||
|
|
||||||
|
if link_against_prebuilt_rt {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// The original compiler-rt build system compiles the same
|
// The original compiler-rt build system compiles the same
|
||||||
// source file multiple times with different compiler
|
// source file multiple times with different compiler
|
||||||
// options. Here we do something slightly different: we
|
// options. Here we do something slightly different: we
|
||||||
@@ -632,9 +672,6 @@ mod c {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
drop(file);
|
drop(file);
|
||||||
cfg.file(path);
|
cfg.file(path);
|
||||||
|
|
||||||
let sym = format!("__aarch64_{}{}_{}", instruction_type, size, model_name);
|
|
||||||
println!("cargo:rustc-cfg={}=\"optimized-c\"", sym);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -575,25 +575,31 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, cargo: &mut Car
|
|||||||
// `compiler-builtins` crate is enabled and it's configured to learn where
|
// `compiler-builtins` crate is enabled and it's configured to learn where
|
||||||
// `compiler-rt` is located.
|
// `compiler-rt` is located.
|
||||||
let compiler_builtins_c_feature = if builder.config.optimized_compiler_builtins(target) {
|
let compiler_builtins_c_feature = if builder.config.optimized_compiler_builtins(target) {
|
||||||
// NOTE: this interacts strangely with `llvm-has-rust-patches`. In that case, we enforce `submodules = false`, so this is a no-op.
|
if let Some(path) = builder.config.optimized_compiler_builtins_path(target) {
|
||||||
// But, the user could still decide to manually use an in-tree submodule.
|
cargo.env("LLVM_COMPILER_RT_LIB", path);
|
||||||
//
|
} else {
|
||||||
// NOTE: if we're using system llvm, we'll end up building a version of `compiler-rt` that doesn't match the LLVM we're linking to.
|
// NOTE: this interacts strangely with `llvm-has-rust-patches`. In that case, we enforce
|
||||||
// That's probably ok? At least, the difference wasn't enforced before. There's a comment in
|
// `submodules = false`, so this is a no-op. But, the user could still decide to
|
||||||
// the compiler_builtins build script that makes me nervous, though:
|
// manually use an in-tree submodule.
|
||||||
// https://github.com/rust-lang/compiler-builtins/blob/31ee4544dbe47903ce771270d6e3bea8654e9e50/build.rs#L575-L579
|
//
|
||||||
builder.require_submodule(
|
// NOTE: if we're using system llvm, we'll end up building a version of `compiler-rt`
|
||||||
"src/llvm-project",
|
// that doesn't match the LLVM we're linking to. That's probably ok? At least, the
|
||||||
Some(
|
// difference wasn't enforced before. There's a comment in the compiler_builtins build
|
||||||
"The `build.optimized-compiler-builtins` config option \
|
// script that makes me nervous, though:
|
||||||
requires `compiler-rt` sources from LLVM.",
|
// https://github.com/rust-lang/compiler-builtins/blob/31ee4544dbe47903ce771270d6e3bea8654e9e50/build.rs#L575-L579
|
||||||
),
|
builder.require_submodule(
|
||||||
);
|
"src/llvm-project",
|
||||||
let compiler_builtins_root = builder.src.join("src/llvm-project/compiler-rt");
|
Some(
|
||||||
assert!(compiler_builtins_root.exists());
|
"The `build.optimized-compiler-builtins` config option \
|
||||||
// The path to `compiler-rt` is also used by `profiler_builtins` (above),
|
requires `compiler-rt` sources from LLVM.",
|
||||||
// so if you're changing something here please also change that as appropriate.
|
),
|
||||||
cargo.env("RUST_COMPILER_RT_ROOT", &compiler_builtins_root);
|
);
|
||||||
|
let compiler_builtins_root = builder.src.join("src/llvm-project/compiler-rt");
|
||||||
|
assert!(compiler_builtins_root.exists());
|
||||||
|
// The path to `compiler-rt` is also used by `profiler_builtins` (above),
|
||||||
|
// so if you're changing something here please also change that as appropriate.
|
||||||
|
cargo.env("RUST_COMPILER_RT_ROOT", &compiler_builtins_root);
|
||||||
|
}
|
||||||
" compiler-builtins-c"
|
" compiler-builtins-c"
|
||||||
} else {
|
} else {
|
||||||
""
|
""
|
||||||
|
|||||||
@@ -1675,10 +1675,18 @@ impl Config {
|
|||||||
pub fn optimized_compiler_builtins(&self, target: TargetSelection) -> bool {
|
pub fn optimized_compiler_builtins(&self, target: TargetSelection) -> bool {
|
||||||
self.target_config
|
self.target_config
|
||||||
.get(&target)
|
.get(&target)
|
||||||
.and_then(|t| t.optimized_compiler_builtins)
|
.and_then(|t| t.optimized_compiler_builtins.as_ref())
|
||||||
|
.map(StringOrBool::is_string_or_true)
|
||||||
.unwrap_or(self.optimized_compiler_builtins)
|
.unwrap_or(self.optimized_compiler_builtins)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn optimized_compiler_builtins_path(&self, target: TargetSelection) -> Option<&str> {
|
||||||
|
match self.target_config.get(&target)?.optimized_compiler_builtins.as_ref()? {
|
||||||
|
StringOrBool::String(s) => Some(s),
|
||||||
|
StringOrBool::Bool(_) => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn llvm_enabled(&self, target: TargetSelection) -> bool {
|
pub fn llvm_enabled(&self, target: TargetSelection) -> bool {
|
||||||
self.enabled_codegen_backends(target).contains(&CodegenBackendKind::Llvm)
|
self.enabled_codegen_backends(target).contains(&CodegenBackendKind::Llvm)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ use crate::core::build_steps::clippy::{LintConfig, get_clippy_rules_in_order};
|
|||||||
use crate::core::build_steps::llvm;
|
use crate::core::build_steps::llvm;
|
||||||
use crate::core::build_steps::llvm::LLVM_INVALIDATION_PATHS;
|
use crate::core::build_steps::llvm::LLVM_INVALIDATION_PATHS;
|
||||||
use crate::core::config::toml::TomlConfig;
|
use crate::core::config::toml::TomlConfig;
|
||||||
use crate::core::config::{LldMode, Target, TargetSelection};
|
use crate::core::config::{LldMode, StringOrBool, Target, TargetSelection};
|
||||||
use crate::utils::tests::git::git_test;
|
use crate::utils::tests::git::git_test;
|
||||||
|
|
||||||
pub(crate) fn parse(config: &str) -> Config {
|
pub(crate) fn parse(config: &str) -> Config {
|
||||||
@@ -212,7 +212,7 @@ runner = "x86_64-runner"
|
|||||||
let darwin = TargetSelection::from_user("aarch64-apple-darwin");
|
let darwin = TargetSelection::from_user("aarch64-apple-darwin");
|
||||||
let darwin_values = Target {
|
let darwin_values = Target {
|
||||||
runner: Some("apple".into()),
|
runner: Some("apple".into()),
|
||||||
optimized_compiler_builtins: Some(false),
|
optimized_compiler_builtins: Some(StringOrBool::Bool(false)),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ define_config! {
|
|||||||
no_std: Option<bool> = "no-std",
|
no_std: Option<bool> = "no-std",
|
||||||
codegen_backends: Option<Vec<String>> = "codegen-backends",
|
codegen_backends: Option<Vec<String>> = "codegen-backends",
|
||||||
runner: Option<String> = "runner",
|
runner: Option<String> = "runner",
|
||||||
optimized_compiler_builtins: Option<bool> = "optimized-compiler-builtins",
|
optimized_compiler_builtins: Option<StringOrBool> = "optimized-compiler-builtins",
|
||||||
jemalloc: Option<bool> = "jemalloc",
|
jemalloc: Option<bool> = "jemalloc",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -71,7 +71,7 @@ pub struct Target {
|
|||||||
pub runner: Option<String>,
|
pub runner: Option<String>,
|
||||||
pub no_std: bool,
|
pub no_std: bool,
|
||||||
pub codegen_backends: Option<Vec<CodegenBackendKind>>,
|
pub codegen_backends: Option<Vec<CodegenBackendKind>>,
|
||||||
pub optimized_compiler_builtins: Option<bool>,
|
pub optimized_compiler_builtins: Option<StringOrBool>,
|
||||||
pub jemalloc: Option<bool>,
|
pub jemalloc: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -521,4 +521,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
|
|||||||
severity: ChangeSeverity::Warning,
|
severity: ChangeSeverity::Warning,
|
||||||
summary: "It is no longer possible to `x dist` or `x install` with stage 0. All dist and install commands have to be on stage 1+.",
|
summary: "It is no longer possible to `x dist` or `x install` with stage 0. All dist and install commands have to be on stage 1+.",
|
||||||
},
|
},
|
||||||
|
ChangeInfo {
|
||||||
|
change_id: 143689,
|
||||||
|
severity: ChangeSeverity::Info,
|
||||||
|
summary: "The `optimized-compiler-builtins` option now accepts a path to an existing compiler-rt builtins library.",
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
Reference in New Issue
Block a user