about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--bootstrap.example.toml7
-rw-r--r--src/bootstrap/src/core/build_steps/compile.rs17
-rw-r--r--src/bootstrap/src/core/config/config.rs25
-rw-r--r--src/bootstrap/src/core/config/mod.rs27
-rw-r--r--src/bootstrap/src/core/config/tests.rs10
-rw-r--r--src/bootstrap/src/core/config/toml/build.rs4
-rw-r--r--src/bootstrap/src/core/config/toml/rust.rs4
-rw-r--r--src/bootstrap/src/core/config/toml/target.rs8
-rw-r--r--src/bootstrap/src/core/sanity.rs5
9 files changed, 71 insertions, 36 deletions
diff --git a/bootstrap.example.toml b/bootstrap.example.toml
index ebab2e14828..16fd9241a17 100644
--- a/bootstrap.example.toml
+++ b/bootstrap.example.toml
@@ -407,8 +407,11 @@
 #build.profiler = false
 
 # Use the optimized LLVM C intrinsics for `compiler_builtins`, rather than Rust intrinsics.
-# Requires the LLVM submodule to be managed by bootstrap (i.e. not external) so that `compiler-rt`
-# sources are available.
+# Choosing true requires the LLVM submodule to be managed by bootstrap (i.e. not external)
+# so that `compiler-rt` 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
 # order to run `x check`.
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index 005c849c47a..f7a2dc14218 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -26,7 +26,9 @@ use crate::core::builder;
 use crate::core::builder::{
     Builder, Cargo, Kind, RunConfig, ShouldRun, Step, StepMetadata, crate_description,
 };
-use crate::core::config::{DebuginfoLevel, LlvmLibunwind, RustcLto, TargetSelection};
+use crate::core::config::{
+    CompilerBuiltins, DebuginfoLevel, LlvmLibunwind, RustcLto, TargetSelection,
+};
 use crate::utils::build_stamp;
 use crate::utils::build_stamp::BuildStamp;
 use crate::utils::exec::command;
@@ -574,10 +576,12 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, cargo: &mut Car
     // If `compiler-rt` is available ensure that the `c` feature of the
     // `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) {
-        if let Some(path) = builder.config.optimized_compiler_builtins_path(target) {
+    let compiler_builtins_c_feature = match builder.config.optimized_compiler_builtins(target) {
+        CompilerBuiltins::LinkLLVMBuiltinsLib(path) => {
             cargo.env("LLVM_COMPILER_RT_LIB", path);
-        } else {
+            " compiler-builtins-c"
+        }
+        CompilerBuiltins::BuildLLVMFuncs => {
             // 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.
@@ -599,10 +603,9 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, cargo: &mut Car
             // 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 {
-        ""
+        CompilerBuiltins::BuildRustOnly => "",
     };
 
     // `libtest` uses this to know whether or not to support
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index 09a1eb5b847..e5c2e3c64b8 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -46,8 +46,8 @@ use crate::core::config::toml::rust::{
 };
 use crate::core::config::toml::target::Target;
 use crate::core::config::{
-    DebuginfoLevel, DryRun, GccCiMode, LlvmLibunwind, Merge, ReplaceOpt, RustcLto, SplitDebuginfo,
-    StringOrBool, threads_from_config,
+    CompilerBuiltins, DebuginfoLevel, DryRun, GccCiMode, LlvmLibunwind, Merge, ReplaceOpt,
+    RustcLto, SplitDebuginfo, StringOrBool, threads_from_config,
 };
 use crate::core::download::{
     DownloadContext, download_beta_toolchain, is_download_ci_available, maybe_download_rustfmt,
@@ -121,8 +121,7 @@ pub struct Config {
     pub patch_binaries_for_nix: Option<bool>,
     pub stage0_metadata: build_helper::stage0_parser::Stage0,
     pub android_ndk: Option<PathBuf>,
-    /// Whether to use the `c` feature of the `compiler_builtins` crate.
-    pub optimized_compiler_builtins: bool,
+    pub optimized_compiler_builtins: CompilerBuiltins,
 
     pub stdout_is_tty: bool,
     pub stderr_is_tty: bool,
@@ -1109,7 +1108,11 @@ impl Config {
         let rustfmt_info = git_info(&exec_ctx, omit_git_hash, &src.join("src/tools/rustfmt"));
 
         let optimized_compiler_builtins =
-            build_optimized_compiler_builtins.unwrap_or(channel != "dev");
+            build_optimized_compiler_builtins.unwrap_or(if channel == "dev" {
+                CompilerBuiltins::BuildRustOnly
+            } else {
+                CompilerBuiltins::BuildLLVMFuncs
+            });
         let vendor = build_vendor.unwrap_or(
             rust_info.is_from_tarball()
                 && src.join("vendor").exists()
@@ -1672,19 +1675,11 @@ impl Config {
         self.target_config.get(&target).and_then(|t| t.rpath).unwrap_or(self.rust_rpath)
     }
 
-    pub fn optimized_compiler_builtins(&self, target: TargetSelection) -> bool {
+    pub fn optimized_compiler_builtins(&self, target: TargetSelection) -> &CompilerBuiltins {
         self.target_config
             .get(&target)
             .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,
-        }
+            .unwrap_or(&self.optimized_compiler_builtins)
     }
 
     pub fn llvm_enabled(&self, target: TargetSelection) -> bool {
diff --git a/src/bootstrap/src/core/config/mod.rs b/src/bootstrap/src/core/config/mod.rs
index dbd05fd2519..5999348a7fe 100644
--- a/src/bootstrap/src/core/config/mod.rs
+++ b/src/bootstrap/src/core/config/mod.rs
@@ -218,6 +218,33 @@ impl<T> Merge for Option<T> {
     }
 }
 
+#[derive(Clone, Debug, Default, Eq, PartialEq)]
+pub enum CompilerBuiltins {
+    #[default]
+    // Only build native rust intrinsic compiler functions.
+    BuildRustOnly,
+    // Some intrinsic functions have a C implementation provided by LLVM's
+    // compiler-rt builtins library. Build them from the LLVM source included
+    // with Rust.
+    BuildLLVMFuncs,
+    // Similar to BuildLLVMFuncs, but specify a path to an existing library
+    // containing LLVM's compiler-rt builtins instead of compiling them.
+    LinkLLVMBuiltinsLib(String),
+}
+
+impl<'de> Deserialize<'de> for CompilerBuiltins {
+    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+    where
+        D: Deserializer<'de>,
+    {
+        Ok(match Deserialize::deserialize(deserializer)? {
+            StringOrBool::Bool(false) => Self::BuildRustOnly,
+            StringOrBool::Bool(true) => Self::BuildLLVMFuncs,
+            StringOrBool::String(path) => Self::LinkLLVMBuiltinsLib(path),
+        })
+    }
+}
+
 #[derive(Copy, Clone, Default, Debug, Eq, PartialEq)]
 pub enum DebuginfoLevel {
     #[default]
diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs
index c32e4384cf6..e93525fbd09 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::clippy::{LintConfig, get_clippy_rules_in_order};
 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, StringOrBool, Target, TargetSelection};
+use crate::core::config::{CompilerBuiltins, LldMode, StringOrBool, Target, TargetSelection};
 use crate::utils::tests::git::git_test;
 
 pub(crate) fn parse(config: &str) -> Config {
@@ -183,7 +183,11 @@ runner = "x86_64-runner"
     );
     assert_eq!(config.gdb, Some("bar".into()), "setting string value with quotes");
     assert!(!config.deny_warnings, "setting boolean value");
-    assert!(config.optimized_compiler_builtins, "setting boolean value");
+    assert_eq!(
+        config.optimized_compiler_builtins,
+        CompilerBuiltins::BuildLLVMFuncs,
+        "setting boolean value"
+    );
     assert_eq!(
         config.tools,
         Some(["cargo".to_string()].into_iter().collect()),
@@ -212,7 +216,7 @@ runner = "x86_64-runner"
     let darwin = TargetSelection::from_user("aarch64-apple-darwin");
     let darwin_values = Target {
         runner: Some("apple".into()),
-        optimized_compiler_builtins: Some(StringOrBool::Bool(false)),
+        optimized_compiler_builtins: Some(CompilerBuiltins::BuildRustOnly),
         ..Default::default()
     };
     assert_eq!(
diff --git a/src/bootstrap/src/core/config/toml/build.rs b/src/bootstrap/src/core/config/toml/build.rs
index 728367b3972..25c19f1070a 100644
--- a/src/bootstrap/src/core/config/toml/build.rs
+++ b/src/bootstrap/src/core/config/toml/build.rs
@@ -11,7 +11,7 @@ use std::collections::HashMap;
 use serde::{Deserialize, Deserializer};
 
 use crate::core::config::toml::ReplaceOpt;
-use crate::core::config::{Merge, StringOrBool};
+use crate::core::config::{CompilerBuiltins, Merge, StringOrBool};
 use crate::{HashSet, PathBuf, define_config, exit};
 
 define_config! {
@@ -65,7 +65,7 @@ define_config! {
         // NOTE: only parsed by bootstrap.py, `--feature build-metrics` enables metrics unconditionally
         metrics: Option<bool> = "metrics",
         android_ndk: Option<PathBuf> = "android-ndk",
-        optimized_compiler_builtins: Option<bool> = "optimized-compiler-builtins",
+        optimized_compiler_builtins: Option<CompilerBuiltins> = "optimized-compiler-builtins",
         jobs: Option<u32> = "jobs",
         compiletest_diff_tool: Option<String> = "compiletest-diff-tool",
         compiletest_allow_stage0: Option<bool> = "compiletest-allow-stage0",
diff --git a/src/bootstrap/src/core/config/toml/rust.rs b/src/bootstrap/src/core/config/toml/rust.rs
index 3dab8d1d96d..7f111094c3f 100644
--- a/src/bootstrap/src/core/config/toml/rust.rs
+++ b/src/bootstrap/src/core/config/toml/rust.rs
@@ -269,9 +269,9 @@ pub fn check_incompatible_options_for_ci_rustc(
     err!(current_profiler, profiler, "build");
 
     let current_optimized_compiler_builtins =
-        current_config_toml.build.as_ref().and_then(|b| b.optimized_compiler_builtins);
+        current_config_toml.build.as_ref().and_then(|b| b.optimized_compiler_builtins.clone());
     let optimized_compiler_builtins =
-        ci_config_toml.build.as_ref().and_then(|b| b.optimized_compiler_builtins);
+        ci_config_toml.build.as_ref().and_then(|b| b.optimized_compiler_builtins.clone());
     err!(current_optimized_compiler_builtins, optimized_compiler_builtins, "build");
 
     // We always build the in-tree compiler on cross targets, so we only care
diff --git a/src/bootstrap/src/core/config/toml/target.rs b/src/bootstrap/src/core/config/toml/target.rs
index 3236b5cdbaa..020602e6a19 100644
--- a/src/bootstrap/src/core/config/toml/target.rs
+++ b/src/bootstrap/src/core/config/toml/target.rs
@@ -11,7 +11,9 @@
 
 use serde::{Deserialize, Deserializer};
 
-use crate::core::config::{LlvmLibunwind, Merge, ReplaceOpt, SplitDebuginfo, StringOrBool};
+use crate::core::config::{
+    CompilerBuiltins, LlvmLibunwind, Merge, ReplaceOpt, SplitDebuginfo, StringOrBool,
+};
 use crate::{CodegenBackendKind, HashSet, PathBuf, define_config, exit};
 
 define_config! {
@@ -39,7 +41,7 @@ define_config! {
         no_std: Option<bool> = "no-std",
         codegen_backends: Option<Vec<String>> = "codegen-backends",
         runner: Option<String> = "runner",
-        optimized_compiler_builtins: Option<StringOrBool> = "optimized-compiler-builtins",
+        optimized_compiler_builtins: Option<CompilerBuiltins> = "optimized-compiler-builtins",
         jemalloc: Option<bool> = "jemalloc",
     }
 }
@@ -71,7 +73,7 @@ pub struct Target {
     pub runner: Option<String>,
     pub no_std: bool,
     pub codegen_backends: Option<Vec<CodegenBackendKind>>,
-    pub optimized_compiler_builtins: Option<StringOrBool>,
+    pub optimized_compiler_builtins: Option<CompilerBuiltins>,
     pub jemalloc: Option<bool>,
 }
 
diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs
index de7cada93f2..4916ebbd610 100644
--- a/src/bootstrap/src/core/sanity.rs
+++ b/src/bootstrap/src/core/sanity.rs
@@ -18,7 +18,7 @@ use crate::builder::Builder;
 use crate::builder::Kind;
 #[cfg(not(test))]
 use crate::core::build_steps::tool;
-use crate::core::config::Target;
+use crate::core::config::{CompilerBuiltins, Target};
 use crate::utils::exec::command;
 use crate::{Build, Subcommand};
 
@@ -330,7 +330,8 @@ than building it.
 
         // compiler-rt c fallbacks for wasm cannot be built with gcc
         if target.contains("wasm")
-            && (build.config.optimized_compiler_builtins(*target)
+            && (*build.config.optimized_compiler_builtins(*target)
+                != CompilerBuiltins::BuildRustOnly
                 || build.config.rust_std_features.contains("compiler-builtins-c"))
         {
             let cc_tool = build.cc_tool(*target);