Enable optimized-compiler-builtins on the native compiler
With the exception of s390x which does not yet provide one. On aarch64, this adds runtime support for LSE in outline-atomic operations.
This commit is contained in:
parent
5a638152c0
commit
6c973e7ddf
2 changed files with 290 additions and 1 deletions
276
0001-Allow-linking-a-prebuilt-optimized-compiler-rt-built.patch
Normal file
276
0001-Allow-linking-a-prebuilt-optimized-compiler-rt-built.patch
Normal file
|
|
@ -0,0 +1,276 @@
|
|||
From b5cdd50a21e27bde3fbbff5fe67df79b88fadb05 Mon Sep 17 00:00:00 2001
|
||||
From: Paul Murphy <paumurph@redhat.com>
|
||||
Date: Tue, 24 Jun 2025 11:07:54 -0500
|
||||
Subject: [PATCH] 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.
|
||||
---
|
||||
bootstrap.example.toml | 4 +-
|
||||
.../compiler-builtins/build.rs | 55 ++++++++++++++++---
|
||||
src/bootstrap/src/core/build_steps/compile.rs | 44 ++++++++-------
|
||||
src/bootstrap/src/core/config/config.rs | 10 +++-
|
||||
src/bootstrap/src/core/config/tests.rs | 4 +-
|
||||
src/bootstrap/src/core/config/toml/target.rs | 4 +-
|
||||
6 files changed, 87 insertions(+), 34 deletions(-)
|
||||
|
||||
diff --git a/bootstrap.example.toml b/bootstrap.example.toml
|
||||
index 916bae8dc7d..cb80c9dd31e 100644
|
||||
--- a/bootstrap.example.toml
|
||||
+++ b/bootstrap.example.toml
|
||||
@@ -967,7 +967,9 @@
|
||||
# sources are available.
|
||||
#
|
||||
# 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`. This may also be given a path to an existing build of the builtins
|
||||
+# runtime library from LLVM's compiler-rt. This option will override the same option under [build]
|
||||
+# section.
|
||||
#optimized-compiler-builtins = build.optimized-compiler-builtins (bool)
|
||||
|
||||
# Link the compiler and LLVM against `jemalloc` instead of the default libc allocator.
|
||||
diff --git a/library/compiler-builtins/compiler-builtins/build.rs b/library/compiler-builtins/compiler-builtins/build.rs
|
||||
index 018899faf1d..3ad888ed26a 100644
|
||||
--- a/library/compiler-builtins/compiler-builtins/build.rs
|
||||
+++ b/library/compiler-builtins/compiler-builtins/build.rs
|
||||
@@ -548,12 +548,20 @@ pub fn compile(llvm_target: &[&str], target: &Target) {
|
||||
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
|
||||
// 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
|
||||
// rust-lang/rust.
|
||||
let root = match env::var_os("RUST_COMPILER_RT_ROOT") {
|
||||
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 => {
|
||||
panic!(
|
||||
"RUST_COMPILER_RT_ROOT is not set. You may need to run \
|
||||
@@ -561,7 +569,7 @@ pub fn compile(llvm_target: &[&str], target: &Target) {
|
||||
);
|
||||
}
|
||||
};
|
||||
- if !root.exists() {
|
||||
+ if !link_against_prebuilt_rt && !root.exists() {
|
||||
panic!("RUST_COMPILER_RT_ROOT={} does not exist", root.display());
|
||||
}
|
||||
|
||||
@@ -577,7 +585,7 @@ pub fn compile(llvm_target: &[&str], target: &Target) {
|
||||
let src_dir = root.join("lib/builtins");
|
||||
if target.arch == "aarch64" && target.env != "msvc" && target.os != "uefi" {
|
||||
// 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.
|
||||
let cpu_model_src = if src_dir.join("cpu_model.c").exists() {
|
||||
@@ -591,20 +599,45 @@ pub fn compile(llvm_target: &[&str], target: &Target) {
|
||||
let mut added_sources = HashSet::new();
|
||||
for (sym, src) in sources.map.iter() {
|
||||
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);
|
||||
println!("cargo:rerun-if-changed={}", src.display());
|
||||
}
|
||||
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 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);
|
||||
|
||||
@@ -617,6 +650,13 @@ fn build_aarch64_out_of_line_atomics_libraries(builtins_dir: &Path, cfg: &mut cc
|
||||
for (model_number, model_name) in
|
||||
&[(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
|
||||
// source file multiple times with different compiler
|
||||
// options. Here we do something slightly different: we
|
||||
@@ -640,9 +680,6 @@ fn build_aarch64_out_of_line_atomics_libraries(builtins_dir: &Path, cfg: &mut cc
|
||||
.unwrap();
|
||||
drop(file);
|
||||
cfg.file(path);
|
||||
-
|
||||
- let sym = format!("__aarch64_{}{}_{}", instruction_type, size, model_name);
|
||||
- println!("cargo:rustc-cfg={}=\"optimized-c\"", sym);
|
||||
}
|
||||
}
|
||||
}
|
||||
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
|
||||
index 4ef70dd9b97..e9393f7dcaa 100644
|
||||
--- a/src/bootstrap/src/core/build_steps/compile.rs
|
||||
+++ b/src/bootstrap/src/core/build_steps/compile.rs
|
||||
@@ -578,25 +578,31 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car
|
||||
// `compiler-builtins` crate is enabled and it's configured to learn where
|
||||
// `compiler-rt` is located.
|
||||
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.
|
||||
- // But, the user could still decide to manually use an in-tree submodule.
|
||||
- //
|
||||
- // 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.
|
||||
- // That's probably ok? At least, the difference wasn't enforced before. There's a comment in
|
||||
- // the compiler_builtins build script that makes me nervous, though:
|
||||
- // https://github.com/rust-lang/compiler-builtins/blob/31ee4544dbe47903ce771270d6e3bea8654e9e50/build.rs#L575-L579
|
||||
- builder.require_submodule(
|
||||
- "src/llvm-project",
|
||||
- Some(
|
||||
- "The `build.optimized-compiler-builtins` config option \
|
||||
- requires `compiler-rt` sources from LLVM.",
|
||||
- ),
|
||||
- );
|
||||
- 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);
|
||||
+ if let Some(path) = builder.config.optimized_compiler_builtins_path(target) {
|
||||
+ cargo.env("LLVM_COMPILER_RT_LIB", path);
|
||||
+ } else {
|
||||
+ // NOTE: this interacts strangely with `llvm-has-rust-patches`. In that case, we enforce
|
||||
+ // `submodules = false`, so this is a no-op. But, the user could still decide to
|
||||
+ // manually use an in-tree submodule.
|
||||
+ //
|
||||
+ // 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. That's probably ok? At least, the
|
||||
+ // difference wasn't enforced before. There's a comment in the compiler_builtins build
|
||||
+ // script that makes me nervous, though:
|
||||
+ // https://github.com/rust-lang/compiler-builtins/blob/31ee4544dbe47903ce771270d6e3bea8654e9e50/build.rs#L575-L579
|
||||
+ builder.require_submodule(
|
||||
+ "src/llvm-project",
|
||||
+ Some(
|
||||
+ "The `build.optimized-compiler-builtins` config option \
|
||||
+ requires `compiler-rt` sources from LLVM.",
|
||||
+ ),
|
||||
+ );
|
||||
+ 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"
|
||||
} else {
|
||||
""
|
||||
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
|
||||
index d3393afcae0..5834be7643c 100644
|
||||
--- a/src/bootstrap/src/core/config/config.rs
|
||||
+++ b/src/bootstrap/src/core/config/config.rs
|
||||
@@ -1728,10 +1728,18 @@ pub fn rpath_enabled(&self, target: TargetSelection) -> bool {
|
||||
pub fn optimized_compiler_builtins(&self, target: TargetSelection) -> bool {
|
||||
self.target_config
|
||||
.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)
|
||||
}
|
||||
|
||||
+ 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 {
|
||||
self.codegen_backends(target).contains(&"llvm".to_owned())
|
||||
}
|
||||
diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs
|
||||
index 50eba12aba7..c32e4384cf6 100644
|
||||
--- a/src/bootstrap/src/core/config/tests.rs
|
||||
+++ b/src/bootstrap/src/core/config/tests.rs
|
||||
@@ -17,7 +17,7 @@
|
||||
use crate::core::build_steps::llvm;
|
||||
use crate::core::build_steps::llvm::LLVM_INVALIDATION_PATHS;
|
||||
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;
|
||||
|
||||
pub(crate) fn parse(config: &str) -> Config {
|
||||
@@ -212,7 +212,7 @@ fn override_toml() {
|
||||
let darwin = TargetSelection::from_user("aarch64-apple-darwin");
|
||||
let darwin_values = Target {
|
||||
runner: Some("apple".into()),
|
||||
- optimized_compiler_builtins: Some(false),
|
||||
+ optimized_compiler_builtins: Some(StringOrBool::Bool(false)),
|
||||
..Default::default()
|
||||
};
|
||||
assert_eq!(
|
||||
diff --git a/src/bootstrap/src/core/config/toml/target.rs b/src/bootstrap/src/core/config/toml/target.rs
|
||||
index 41a4a815d31..022d042d271 100644
|
||||
--- a/src/bootstrap/src/core/config/toml/target.rs
|
||||
+++ b/src/bootstrap/src/core/config/toml/target.rs
|
||||
@@ -45,7 +45,7 @@ struct TomlTarget {
|
||||
no_std: Option<bool> = "no-std",
|
||||
codegen_backends: Option<Vec<String>> = "codegen-backends",
|
||||
runner: Option<String> = "runner",
|
||||
- optimized_compiler_builtins: Option<bool> = "optimized-compiler-builtins",
|
||||
+ optimized_compiler_builtins: Option<StringOrBool> = "optimized-compiler-builtins",
|
||||
jemalloc: Option<bool> = "jemalloc",
|
||||
self_contained: Option<bool> = "self-contained",
|
||||
}
|
||||
@@ -78,7 +78,7 @@ pub struct Target {
|
||||
pub runner: Option<String>,
|
||||
pub no_std: bool,
|
||||
pub codegen_backends: Option<Vec<String>>,
|
||||
- pub optimized_compiler_builtins: Option<bool>,
|
||||
+ pub optimized_compiler_builtins: Option<StringOrBool>,
|
||||
pub jemalloc: Option<bool>,
|
||||
pub self_contained: bool,
|
||||
}
|
||||
--
|
||||
2.50.1
|
||||
|
||||
15
rust.spec
15
rust.spec
|
|
@ -146,6 +146,9 @@ Patch7: 0001-only-copy-rustlib-into-stage0-sysroot.patch
|
|||
# PR #143752, fixed upstream.
|
||||
Patch8: 0001-Don-t-always-panic-if-WASI_SDK_PATH-is-not-set-when-.patch
|
||||
|
||||
# Support optimized-compiler-builtins via linking against compiler-rt builtins.
|
||||
Patch9: 0001-Allow-linking-a-prebuilt-optimized-compiler-rt-built.patch
|
||||
|
||||
### RHEL-specific patches below ###
|
||||
|
||||
# Simple rpm macros for rust-toolset (as opposed to full rust-packaging)
|
||||
|
|
@ -698,6 +701,7 @@ rm -rf %{wasi_libc_dir}/dlmalloc/
|
|||
%endif
|
||||
%patch -P7 -p1
|
||||
%patch -P8 -p1
|
||||
%patch -P9 -p1
|
||||
|
||||
%if %with disabled_libssh2
|
||||
%patch -P100 -p1
|
||||
|
|
@ -851,11 +855,19 @@ end}
|
|||
%endif
|
||||
%endif
|
||||
|
||||
# Find the compiler-rt library for the Rust profiler_builtins crate.
|
||||
# Find the compiler-rt library for the Rust profiler_builtins and optimized-builtins crates.
|
||||
%define clang_lib %{expand:%%clang%{?llvm_compat_version}_resource_dir}/lib
|
||||
%define profiler %{clang_lib}/%{_arch}-redhat-linux-gnu/libclang_rt.profile.a
|
||||
test -r "%{profiler}"
|
||||
|
||||
# llvm < 21 does not provide a builtins library for s390x.
|
||||
%ifnarch s390x
|
||||
%define optimized_builtins %{clang_lib}/%{_arch}-redhat-linux-gnu/libclang_rt.builtins.a
|
||||
%else
|
||||
%define optimized_builtins false
|
||||
%endif
|
||||
|
||||
|
||||
%configure --disable-option-checking \
|
||||
--docdir=%{_pkgdocdir} \
|
||||
--libdir=%{common_libdir} \
|
||||
|
|
@ -866,6 +878,7 @@ test -r "%{profiler}"
|
|||
--set target.%{rust_triple}.ar=%{__ar} \
|
||||
--set target.%{rust_triple}.ranlib=%{__ranlib} \
|
||||
--set target.%{rust_triple}.profiler="%{profiler}" \
|
||||
--set target.%{rust_triple}.optimized-compiler-builtins="%{optimized_builtins}" \
|
||||
%{?mingw_target_config} \
|
||||
%{?wasm_target_config} \
|
||||
--python=%{__python3} \
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue