Skip to content

Commit 27fcb13

Browse files
author
Paul Murphy
committed
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.
1 parent 25cf7d1 commit 27fcb13

File tree

5 files changed

+81
-32
lines changed

5 files changed

+81
-32
lines changed

bootstrap.example.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1029,7 +1029,9 @@
10291029
# sources are available.
10301030
#
10311031
# Setting this to `false` generates slower code, but removes the requirement for a C toolchain in
1032-
# order to run `x check`.
1032+
# order to run `x check`. This may also be given a path to an existing build of the builtins
1033+
# runtime library from LLVM's compiler-rt. This option will override the same option under [build]
1034+
# section.
10331035
#optimized-compiler-builtins = build.optimized-compiler-builtins (bool)
10341036

10351037
# Link the compiler and LLVM against `jemalloc` instead of the default libc allocator.

library/compiler-builtins/compiler-builtins/build.rs

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -548,20 +548,28 @@ mod c {
548548
sources.extend(&[("__emutls_get_address", "emutls.c")]);
549549
}
550550

551+
// Optionally, link against a prebuilt compiler-rt library to supply
552+
// optimized intrinsics instead of compiling a subset of compiler-rt
553+
// from source.
554+
let link_against_prebuilt_rt = env::var_os("LLVM_BUILTIN_RT_LIB").is_some();
555+
551556
// When compiling the C code we require the user to tell us where the
552557
// source code is, and this is largely done so when we're compiling as
553558
// part of rust-lang/rust we can use the same llvm-project repository as
554559
// rust-lang/rust.
555560
let root = match env::var_os("RUST_COMPILER_RT_ROOT") {
556561
Some(s) => PathBuf::from(s),
562+
// If a prebuild libcompiler-rt is provided, set a valid
563+
// path to simplify later logic. Nothing should be compiled.
564+
None if link_against_prebuilt_rt => PathBuf::new(),
557565
None => {
558566
panic!(
559567
"RUST_COMPILER_RT_ROOT is not set. You may need to run \
560568
`ci/download-compiler-rt.sh`."
561569
);
562570
}
563571
};
564-
if !root.exists() {
572+
if !link_against_prebuilt_rt && !root.exists() {
565573
panic!("RUST_COMPILER_RT_ROOT={} does not exist", root.display());
566574
}
567575

@@ -577,7 +585,7 @@ mod c {
577585
let src_dir = root.join("lib/builtins");
578586
if target.arch == "aarch64" && target.env != "msvc" && target.os != "uefi" {
579587
// See below for why we're building these as separate libraries.
580-
build_aarch64_out_of_line_atomics_libraries(&src_dir, cfg);
588+
build_aarch64_out_of_line_atomics_libraries(&src_dir, cfg, link_against_prebuilt_rt);
581589

582590
// Some run-time CPU feature detection is necessary, as well.
583591
let cpu_model_src = if src_dir.join("cpu_model.c").exists() {
@@ -591,20 +599,43 @@ mod c {
591599
let mut added_sources = HashSet::new();
592600
for (sym, src) in sources.map.iter() {
593601
let src = src_dir.join(src);
594-
if added_sources.insert(src.clone()) {
602+
if !link_against_prebuilt_rt && added_sources.insert(src.clone()) {
595603
cfg.file(&src);
596604
println!("cargo:rerun-if-changed={}", src.display());
597605
}
598606
println!("cargo:rustc-cfg={}=\"optimized-c\"", sym);
599607
}
600608

601-
cfg.compile("libcompiler-rt.a");
609+
if link_against_prebuilt_rt {
610+
let rt_builtins_ext = PathBuf::from(env::var_os("LLVM_BUILTIN_RT_LIB").unwrap());
611+
if !rt_builtins_ext.exists() {
612+
panic!(
613+
"LLVM_BUILTIN_RT_LIB={} does not exist",
614+
rt_builtins_ext.display()
615+
);
616+
}
617+
if let Some(dir) = rt_builtins_ext.parent() {
618+
println!("cargo::rustc-link-search=native={}", dir.display());
619+
}
620+
println!(
621+
"cargo::rustc-link-lib=static:+verbatim={}",
622+
rt_builtins_ext.to_str().unwrap()
623+
);
624+
} else {
625+
cfg.compile("libcompiler-rt.a");
626+
}
602627
}
603628

604-
fn build_aarch64_out_of_line_atomics_libraries(builtins_dir: &Path, cfg: &mut cc::Build) {
629+
fn build_aarch64_out_of_line_atomics_libraries(
630+
builtins_dir: &Path,
631+
cfg: &mut cc::Build,
632+
link_against_prebuilt_rt: bool,
633+
) {
605634
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
606635
let outlined_atomics_file = builtins_dir.join("aarch64").join("lse.S");
607-
println!("cargo:rerun-if-changed={}", outlined_atomics_file.display());
636+
if !link_against_prebuilt_rt {
637+
println!("cargo:rerun-if-changed={}", outlined_atomics_file.display());
638+
}
608639

609640
cfg.include(&builtins_dir);
610641

@@ -617,6 +648,13 @@ mod c {
617648
for (model_number, model_name) in
618649
&[(1, "relax"), (2, "acq"), (3, "rel"), (4, "acq_rel")]
619650
{
651+
let sym = format!("__aarch64_{}{}_{}", instruction_type, size, model_name);
652+
println!("cargo:rustc-cfg={}=\"optimized-c\"", sym);
653+
654+
if link_against_prebuilt_rt {
655+
continue;
656+
}
657+
620658
// The original compiler-rt build system compiles the same
621659
// source file multiple times with different compiler
622660
// options. Here we do something slightly different: we
@@ -640,9 +678,6 @@ mod c {
640678
.unwrap();
641679
drop(file);
642680
cfg.file(path);
643-
644-
let sym = format!("__aarch64_{}{}_{}", instruction_type, size, model_name);
645-
println!("cargo:rustc-cfg={}=\"optimized-c\"", sym);
646681
}
647682
}
648683
}

src/bootstrap/src/core/build_steps/compile.rs

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -567,25 +567,29 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car
567567
// `compiler-builtins` crate is enabled and it's configured to learn where
568568
// `compiler-rt` is located.
569569
let compiler_builtins_c_feature = if builder.config.optimized_compiler_builtins(target) {
570-
// NOTE: this interacts strangely with `llvm-has-rust-patches`. In that case, we enforce `submodules = false`, so this is a no-op.
571-
// But, the user could still decide to manually use an in-tree submodule.
572-
//
573-
// 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.
574-
// That's probably ok? At least, the difference wasn't enforced before. There's a comment in
575-
// the compiler_builtins build script that makes me nervous, though:
576-
// https://github.com/rust-lang/compiler-builtins/blob/31ee4544dbe47903ce771270d6e3bea8654e9e50/build.rs#L575-L579
577-
builder.require_submodule(
578-
"src/llvm-project",
579-
Some(
580-
"The `build.optimized-compiler-builtins` config option \
581-
requires `compiler-rt` sources from LLVM.",
582-
),
583-
);
584-
let compiler_builtins_root = builder.src.join("src/llvm-project/compiler-rt");
585-
assert!(compiler_builtins_root.exists());
586-
// The path to `compiler-rt` is also used by `profiler_builtins` (above),
587-
// so if you're changing something here please also change that as appropriate.
588-
cargo.env("RUST_COMPILER_RT_ROOT", &compiler_builtins_root);
570+
if let Some(path) = builder.config.optimized_compiler_builtins_path(target) {
571+
cargo.env("LLVM_BUILTIN_RT_LIB", path);
572+
} else {
573+
// NOTE: this interacts strangely with `llvm-has-rust-patches`. In that case, we enforce `submodules = false`, so this is a no-op.
574+
// But, the user could still decide to manually use an in-tree submodule.
575+
//
576+
// 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.
577+
// That's probably ok? At least, the difference wasn't enforced before. There's a comment in
578+
// the compiler_builtins build script that makes me nervous, though:
579+
// https://github.com/rust-lang/compiler-builtins/blob/31ee4544dbe47903ce771270d6e3bea8654e9e50/build.rs#L575-L579
580+
builder.require_submodule(
581+
"src/llvm-project",
582+
Some(
583+
"The `build.optimized-compiler-builtins` config option \
584+
requires `compiler-rt` sources from LLVM.",
585+
),
586+
);
587+
let compiler_builtins_root = builder.src.join("src/llvm-project/compiler-rt");
588+
assert!(compiler_builtins_root.exists());
589+
// The path to `compiler-rt` is also used by `profiler_builtins` (above),
590+
// so if you're changing something here please also change that as appropriate.
591+
cargo.env("RUST_COMPILER_RT_ROOT", &compiler_builtins_root);
592+
}
589593
" compiler-builtins-c"
590594
} else {
591595
""

src/bootstrap/src/core/config/config.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1741,10 +1741,18 @@ impl Config {
17411741
pub fn optimized_compiler_builtins(&self, target: TargetSelection) -> bool {
17421742
self.target_config
17431743
.get(&target)
1744-
.and_then(|t| t.optimized_compiler_builtins)
1744+
.and_then(|t| t.optimized_compiler_builtins.as_ref())
1745+
.map(StringOrBool::is_string_or_true)
17451746
.unwrap_or(self.optimized_compiler_builtins)
17461747
}
17471748

1749+
pub fn optimized_compiler_builtins_path(&self, target: TargetSelection) -> Option<&str> {
1750+
match self.target_config.get(&target)?.optimized_compiler_builtins.as_ref()? {
1751+
StringOrBool::String(s) => Some(s),
1752+
StringOrBool::Bool(_) => None,
1753+
}
1754+
}
1755+
17481756
pub fn llvm_enabled(&self, target: TargetSelection) -> bool {
17491757
self.codegen_backends(target).contains(&"llvm".to_owned())
17501758
}

src/bootstrap/src/core/config/toml/target.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ define_config! {
4545
no_std: Option<bool> = "no-std",
4646
codegen_backends: Option<Vec<String>> = "codegen-backends",
4747
runner: Option<String> = "runner",
48-
optimized_compiler_builtins: Option<bool> = "optimized-compiler-builtins",
48+
optimized_compiler_builtins: Option<StringOrBool> = "optimized-compiler-builtins",
4949
jemalloc: Option<bool> = "jemalloc",
5050
}
5151
}
@@ -77,7 +77,7 @@ pub struct Target {
7777
pub runner: Option<String>,
7878
pub no_std: bool,
7979
pub codegen_backends: Option<Vec<String>>,
80-
pub optimized_compiler_builtins: Option<bool>,
80+
pub optimized_compiler_builtins: Option<StringOrBool>,
8181
pub jemalloc: Option<bool>,
8282
}
8383

0 commit comments

Comments
 (0)