From 309c50b7d46cfde1107ec4e81031dc6cfa359528 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Fri, 2 Aug 2024 13:48:13 -0400 Subject: [PATCH] Configure which platforms get `f16` and `f128` enabled by default By moving the logic for which platforms get symbols to `compiler_builtins` rather than rust-lang/rust, we can control where symbols get enabled without relying on Cargo features. Using Cargo features turned out to be a problem in [1]. This will help resolve errors like [2]. [1]: https://github.com/rust-lang/rust/issues/128358 [2]: https://github.com/rust-lang/rust/issues/128401 --- build.rs | 52 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/build.rs b/build.rs index b48fc256..d5a6d6d7 100644 --- a/build.rs +++ b/build.rs @@ -14,7 +14,7 @@ struct Target { impl Target { fn from_env() -> Self { - let little_endian = match env::var("CARGO_CFG_TARGET_LITTLE_ENDIAN").unwrap().as_str() { + let little_endian = match env::var("CARGO_CFG_TARGET_ENDIAN").unwrap().as_str() { "little" => true, "big" => false, x => panic!("unknown endian {x}"), @@ -31,7 +31,7 @@ impl Target { .parse() .unwrap(), little_endian, - features: env::var("CARGO_CFG_TARGET_FEATURES") + features: env::var("CARGO_CFG_TARGET_FEATURE") .unwrap() .split(",") .map(ToOwned::to_owned) @@ -42,11 +42,12 @@ impl Target { fn main() { println!("cargo:rerun-if-changed=build.rs"); - configure_check_cfg(); - let target = Target::from_env(); let cwd = env::current_dir().unwrap(); + configure_check_cfg(); + configure_f16_f128(&target); + println!("cargo:compiler-rt={}", cwd.join("compiler-rt").display()); // Activate libm's unstable features to make full use of Nightly. @@ -259,6 +260,49 @@ fn configure_check_cfg() { println!("cargo::rustc-check-cfg=cfg(assert_no_panic)"); } +/// Configure whether or not `f16` and `f128` support should be enabled. +fn configure_f16_f128(target: &Target) { + // Set whether or not `f16` and `f128` are supported at a basic level by LLVM. This only means + // that the backend will not crash when using these types. This does not mean that the + // backend does the right thing, or that the platform doesn't have ABI bugs. + // + // We do this so symbols are provided when `long double` is `f128` which prevents linking + // errors on musl (musl makes use of `long double`). + // + // HACK: this logic should be in `rust-lang/rust` so changes only need to be done in one + // place. However, there is no straightforward way to do this, so we do it here. + let (f16_ok, f128_ok) = match target.arch.as_str() { + // No selection failures + "aarch64" | "x86" | "x86_64" | "riscv32" | "riscv64" | "mips" | "mips64" => (true, true), + // `f16` selection failure https://github.com/llvm/llvm-project/issues/93894 + "loongarch" | "loongarch64" => (false, true), + // conversion selection failure. `f128` is needed because of `long double`, `f16` is more + // optional. . + "powerpc" | "powerpc64" => (false, true), + // No `f16` support + "s390x" => (false, true), + _ => (false, false), + }; + + // If the feature is set, disable these types. + let disable_both = env::var_os("CARGO_FEATURE_NO_F16_F128").is_some(); + + println!("cargo:warning=f16 {f16_ok} f128 {f128_ok} disable both {disable_both}"); + + println!("cargo::rustc-check-cfg=cfg(f16_enabled)"); + println!("cargo::rustc-check-cfg=cfg(f128_enabled)"); + + if f16_ok && !disable_both { + println!("cargo::rustc-cfg=f16_enabled"); + println!("cargo:warning=f16 enabled"); + } + + if f128_ok && !disable_both { + println!("cargo::rustc-cfg=f128_enabled"); + println!("cargo:warning=f128 enabled"); + } +} + #[cfg(feature = "c")] mod c { use std::collections::{BTreeMap, HashSet};