Use the compiler to determine whether or not to enable f16 and f128
Currently we whether or not to build and test `f16` and `f128` support
mostly based on the target triple. This isn't always accurate, however,
since support also varies by backend and the backend version.
Since recently, `rustc` is aware of this with the unstable config option
`target_has_reliable_{f16,f128}`, which better represents when the types
are actually expected to be available and usable. Switch our
compiler-builtins and libm configuration to use this by probing `rustc`
for the target's settings.
A few small `cfg` fixes are needed with this.
This commit is contained in:
parent
6c4221818e
commit
be35d37d8b
8 changed files with 65 additions and 110 deletions
|
|
@ -6,6 +6,5 @@ fn main() {
|
|||
println!("cargo::rerun-if-changed=../configure.rs");
|
||||
|
||||
let target = builtins_configure::Target::from_env();
|
||||
builtins_configure::configure_f16_f128(&target);
|
||||
builtins_configure::configure_aliases(&target);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -177,6 +177,7 @@ float_bench! {
|
|||
],
|
||||
}
|
||||
|
||||
#[cfg(f128_enabled)]
|
||||
float_bench! {
|
||||
name: cmp_f128_gt,
|
||||
sig: (a: f128, b: f128) -> CmpResult,
|
||||
|
|
@ -189,6 +190,7 @@ float_bench! {
|
|||
asm: []
|
||||
}
|
||||
|
||||
#[cfg(f128_enabled)]
|
||||
float_bench! {
|
||||
name: cmp_f128_unord,
|
||||
sig: (a: f128, b: f128) -> CmpResult,
|
||||
|
|
|
|||
|
|
@ -116,5 +116,4 @@ fn main() {
|
|||
}
|
||||
|
||||
builtins_configure::configure_aliases(&target);
|
||||
builtins_configure::configure_f16_f128(&target);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ mod i_to_f {
|
|||
i128, __floattidf;
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "no-f16-f128"))]
|
||||
#[cfg(f128_enabled)]
|
||||
#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
|
||||
i_to_f! { f128, Quad, not(feature = "no-sys-f128-int-convert"),
|
||||
u32, __floatunsitf;
|
||||
|
|
@ -129,7 +129,7 @@ mod i_to_f {
|
|||
i128, __floattitf;
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "no-f16-f128"))]
|
||||
#[cfg(f128_enabled)]
|
||||
#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
|
||||
i_to_f! { f128, Quad, not(feature = "no-sys-f128-int-convert"),
|
||||
u32, __floatunsikf;
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ mod float_div {
|
|||
f64, __divdf3, Double, all();
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "no-f16-f128"))]
|
||||
#[cfg(f128_enabled)]
|
||||
#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
|
||||
float! {
|
||||
f128, __divtf3, Quad,
|
||||
|
|
@ -156,7 +156,7 @@ mod float_div {
|
|||
not(any(feature = "no-sys-f128", all(target_arch = "aarch64", target_os = "linux")));
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "no-f16-f128"))]
|
||||
#[cfg(f128_enabled)]
|
||||
#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
|
||||
float! {
|
||||
f128, __divkf3, Quad, not(feature = "no-sys-f128");
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ mod configure;
|
|||
|
||||
use std::env;
|
||||
|
||||
use configure::{Target, configure_aliases, configure_f16_f128};
|
||||
use configure::{Target, configure_aliases};
|
||||
|
||||
fn main() {
|
||||
println!("cargo::rerun-if-changed=build.rs");
|
||||
|
|
@ -12,7 +12,6 @@ fn main() {
|
|||
let cwd = env::current_dir().unwrap();
|
||||
|
||||
configure_check_cfg();
|
||||
configure_f16_f128(&target);
|
||||
configure_aliases(&target);
|
||||
|
||||
configure_libm(&target);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// Configuration that is shared between `compiler_builtins` and `builtins_test`.
|
||||
|
||||
use std::env;
|
||||
use std::process::{Command, Stdio};
|
||||
use std::{env, str};
|
||||
|
||||
#[derive(Debug)]
|
||||
#[allow(dead_code)]
|
||||
|
|
@ -16,6 +17,8 @@ pub struct Target {
|
|||
pub pointer_width: u8,
|
||||
pub little_endian: bool,
|
||||
pub features: Vec<String>,
|
||||
pub reliable_f128: bool,
|
||||
pub reliable_f16: bool,
|
||||
}
|
||||
|
||||
impl Target {
|
||||
|
|
@ -32,6 +35,19 @@ impl Target {
|
|||
.map(|s| s.to_lowercase().replace("_", "-"))
|
||||
.collect();
|
||||
|
||||
// Query rustc for options that Cargo does not provide env for. The bootstrap hack is used
|
||||
// to get consistent output regardless of channel (`f16`/`f128` config options are hidden
|
||||
// on stable otherwise).
|
||||
let mut cmd = Command::new(env::var("RUSTC").unwrap());
|
||||
cmd.args(["--print=cfg", "--target", &triple])
|
||||
.env("RUSTC_BOOTSTRAP", "1")
|
||||
.stderr(Stdio::inherit());
|
||||
let out = cmd
|
||||
.output()
|
||||
.unwrap_or_else(|e| panic!("failed to run `{cmd:?}`: {e}"));
|
||||
assert!(out.status.success(), "failed to run `{cmd:?}`");
|
||||
let rustc_cfg = str::from_utf8(&out.stdout).unwrap();
|
||||
|
||||
Self {
|
||||
triple,
|
||||
triple_split,
|
||||
|
|
@ -51,6 +67,8 @@ impl Target {
|
|||
.split(",")
|
||||
.map(ToOwned::to_owned)
|
||||
.collect(),
|
||||
reliable_f128: rustc_cfg.lines().any(|l| l == "target_has_reliable_f128"),
|
||||
reliable_f16: rustc_cfg.lines().any(|l| l == "target_has_reliable_f16"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -74,63 +92,24 @@ pub fn configure_aliases(target: &Target) {
|
|||
if target.triple_split[0] == "thumbv6m" || target.triple_split[0] == "thumbv8m.base" {
|
||||
println!("cargo:rustc-cfg=thumb_1")
|
||||
}
|
||||
}
|
||||
|
||||
/// Configure whether or not `f16` and `f128` support should be enabled.
|
||||
pub 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 and generates code that can be called
|
||||
// without crashing (no infinite recursion). This does not mean that the platform doesn't have
|
||||
// ABI or other bugs.
|
||||
//
|
||||
// We do this here rather than in `rust-lang/rust` because configuring via cargo features is
|
||||
// not straightforward.
|
||||
//
|
||||
// Original source of this list:
|
||||
// <https://github.com/rust-lang/compiler-builtins/pull/652#issuecomment-2266151350>
|
||||
let f16_enabled = match target.arch.as_str() {
|
||||
// Unsupported <https://github.com/llvm/llvm-project/issues/94434>
|
||||
"arm64ec" => false,
|
||||
// Selection failure <https://github.com/llvm/llvm-project/issues/50374>
|
||||
"s390x" => false,
|
||||
// Infinite recursion <https://github.com/llvm/llvm-project/issues/97981>
|
||||
"csky" => false,
|
||||
"hexagon" => false,
|
||||
"powerpc" | "powerpc64" => false,
|
||||
"sparc" | "sparc64" => false,
|
||||
"wasm32" | "wasm64" => false,
|
||||
// Most everything else works as of LLVM 19
|
||||
_ => true,
|
||||
};
|
||||
/* Not all backends support `f16` and `f128` to the same level on all architectures, so we
|
||||
* need to disable things if the compiler may crash. See configuration at:
|
||||
* * https://github.com/rust-lang/rust/blob/c65dccabacdfd6c8a7f7439eba13422fdd89b91e/compiler/rustc_codegen_llvm/src/llvm_util.rs#L367-L432
|
||||
* * https://github.com/rust-lang/rustc_codegen_gcc/blob/4b5c44b14166083eef8d71f15f5ea1f53fc976a0/src/lib.rs#L496-L507
|
||||
* * https://github.com/rust-lang/rustc_codegen_cranelift/blob/c713ffab3c6e28ab4b4dd4e392330f786ea657ad/src/lib.rs#L196-L226
|
||||
*/
|
||||
|
||||
let f128_enabled = match target.arch.as_str() {
|
||||
// Unsupported (libcall is not supported) <https://github.com/llvm/llvm-project/issues/121122>
|
||||
"amdgpu" => false,
|
||||
// Unsupported <https://github.com/llvm/llvm-project/issues/94434>
|
||||
"arm64ec" => false,
|
||||
// FIXME(llvm20): fixed by <https://github.com/llvm/llvm-project/pull/117525>
|
||||
"mips64" | "mips64r6" => false,
|
||||
// Selection failure <https://github.com/llvm/llvm-project/issues/95471>
|
||||
"nvptx64" => false,
|
||||
// Selection failure <https://github.com/llvm/llvm-project/issues/101545>
|
||||
"powerpc64" if &target.os == "aix" => false,
|
||||
// Selection failure <https://github.com/llvm/llvm-project/issues/41838>
|
||||
"sparc" => false,
|
||||
// Most everything else works as of LLVM 19
|
||||
_ => true,
|
||||
};
|
||||
|
||||
// If the feature is set, disable these types.
|
||||
let disable_both = env::var_os("CARGO_FEATURE_NO_F16_F128").is_some();
|
||||
// If the feature is set, disable both of these types.
|
||||
let no_f16_f128 = target.cargo_features.iter().any(|s| s == "no-f16-f128");
|
||||
|
||||
println!("cargo::rustc-check-cfg=cfg(f16_enabled)");
|
||||
println!("cargo::rustc-check-cfg=cfg(f128_enabled)");
|
||||
|
||||
if f16_enabled && !disable_both {
|
||||
if target.reliable_f16 && !no_f16_f128 {
|
||||
println!("cargo::rustc-cfg=f16_enabled");
|
||||
}
|
||||
|
||||
if f128_enabled && !disable_both {
|
||||
println!("cargo::rustc-check-cfg=cfg(f128_enabled)");
|
||||
if target.reliable_f128 && !no_f16_f128 {
|
||||
println!("cargo::rustc-cfg=f128_enabled");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
// Configuration shared with both libm and libm-test
|
||||
|
||||
use std::env;
|
||||
use std::path::PathBuf;
|
||||
use std::process::{Command, Stdio};
|
||||
use std::{env, str};
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub struct Config {
|
||||
|
|
@ -9,6 +10,7 @@ pub struct Config {
|
|||
pub out_dir: PathBuf,
|
||||
pub opt_level: String,
|
||||
pub cargo_features: Vec<String>,
|
||||
pub target_triple: String,
|
||||
pub target_arch: String,
|
||||
pub target_env: String,
|
||||
pub target_family: Option<String>,
|
||||
|
|
@ -16,10 +18,13 @@ pub struct Config {
|
|||
pub target_string: String,
|
||||
pub target_vendor: String,
|
||||
pub target_features: Vec<String>,
|
||||
pub reliable_f128: bool,
|
||||
pub reliable_f16: bool,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn from_env() -> Self {
|
||||
let target_triple = env::var("TARGET").unwrap();
|
||||
let target_features = env::var("CARGO_CFG_TARGET_FEATURE")
|
||||
.map(|feats| feats.split(',').map(ToOwned::to_owned).collect())
|
||||
.unwrap_or_default();
|
||||
|
|
@ -28,7 +33,21 @@ impl Config {
|
|||
.map(|s| s.to_lowercase().replace("_", "-"))
|
||||
.collect();
|
||||
|
||||
// Query rustc for options that Cargo does not provide env for. The bootstrap hack is used
|
||||
// to get consistent output regardless of channel (`f16`/`f128` config options are hidden
|
||||
// on stable otherwise).
|
||||
let mut cmd = Command::new(env::var("RUSTC").unwrap());
|
||||
cmd.args(["--print=cfg", "--target", &target_triple])
|
||||
.env("RUSTC_BOOTSTRAP", "1")
|
||||
.stderr(Stdio::inherit());
|
||||
let out = cmd
|
||||
.output()
|
||||
.unwrap_or_else(|e| panic!("failed to run `{cmd:?}`: {e}"));
|
||||
assert!(out.status.success(), "failed to run `{cmd:?}`");
|
||||
let rustc_cfg = str::from_utf8(&out.stdout).unwrap();
|
||||
|
||||
Self {
|
||||
target_triple,
|
||||
manifest_dir: PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()),
|
||||
out_dir: PathBuf::from(env::var("OUT_DIR").unwrap()),
|
||||
opt_level: env::var("OPT_LEVEL").unwrap(),
|
||||
|
|
@ -40,6 +59,8 @@ impl Config {
|
|||
target_string: env::var("TARGET").unwrap(),
|
||||
target_vendor: env::var("CARGO_CFG_TARGET_VENDOR").unwrap(),
|
||||
target_features,
|
||||
reliable_f128: rustc_cfg.lines().any(|l| l == "target_has_reliable_f128"),
|
||||
reliable_f16: rustc_cfg.lines().any(|l| l == "target_has_reliable_f16"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -128,62 +149,18 @@ fn emit_f16_f128_cfg(cfg: &Config) {
|
|||
return;
|
||||
}
|
||||
|
||||
// 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 and generates code that can be called
|
||||
// without crashing (no infinite recursion). This does not mean that the platform doesn't have
|
||||
// ABI or other bugs.
|
||||
//
|
||||
// We do this here rather than in `rust-lang/rust` because configuring via cargo features is
|
||||
// not straightforward.
|
||||
//
|
||||
// Original source of this list:
|
||||
// <https://github.com/rust-lang/compiler-builtins/pull/652#issuecomment-2266151350>
|
||||
let f16_enabled = match cfg.target_arch.as_str() {
|
||||
// Unsupported <https://github.com/llvm/llvm-project/issues/94434>
|
||||
"arm64ec" => false,
|
||||
// Selection failure <https://github.com/llvm/llvm-project/issues/50374>
|
||||
"s390x" => false,
|
||||
// Infinite recursion <https://github.com/llvm/llvm-project/issues/97981>
|
||||
// FIXME(llvm): loongarch fixed by <https://github.com/llvm/llvm-project/pull/107791>
|
||||
"csky" => false,
|
||||
"hexagon" => false,
|
||||
"loongarch64" => false,
|
||||
"mips" | "mips64" | "mips32r6" | "mips64r6" => false,
|
||||
"powerpc" | "powerpc64" => false,
|
||||
"sparc" | "sparc64" => false,
|
||||
"wasm32" | "wasm64" => false,
|
||||
// Most everything else works as of LLVM 19
|
||||
_ => true,
|
||||
};
|
||||
/* See the compiler-builtins configure file for info about the meaning of these options */
|
||||
|
||||
let f128_enabled = match cfg.target_arch.as_str() {
|
||||
// Unsupported (libcall is not supported) <https://github.com/llvm/llvm-project/issues/121122>
|
||||
"amdgpu" => false,
|
||||
// Unsupported <https://github.com/llvm/llvm-project/issues/94434>
|
||||
"arm64ec" => false,
|
||||
// Selection failure <https://github.com/llvm/llvm-project/issues/96432>
|
||||
"mips64" | "mips64r6" => false,
|
||||
// Selection failure <https://github.com/llvm/llvm-project/issues/95471>
|
||||
"nvptx64" => false,
|
||||
// Selection failure <https://github.com/llvm/llvm-project/issues/101545>
|
||||
"powerpc64" if &cfg.target_os == "aix" => false,
|
||||
// Selection failure <https://github.com/llvm/llvm-project/issues/41838>
|
||||
"sparc" => false,
|
||||
// Most everything else works as of LLVM 19
|
||||
_ => true,
|
||||
};
|
||||
|
||||
// If the feature is set, disable these types.
|
||||
let disable_both = env::var_os("CARGO_FEATURE_NO_F16_F128").is_some();
|
||||
// If the feature is set, disable both of these types.
|
||||
let no_f16_f128 = cfg.cargo_features.iter().any(|s| s == "no-f16-f128");
|
||||
|
||||
println!("cargo:rustc-check-cfg=cfg(f16_enabled)");
|
||||
println!("cargo:rustc-check-cfg=cfg(f128_enabled)");
|
||||
|
||||
if f16_enabled && !disable_both {
|
||||
if cfg.reliable_f16 && !no_f16_f128 {
|
||||
println!("cargo:rustc-cfg=f16_enabled");
|
||||
}
|
||||
|
||||
if f128_enabled && !disable_both {
|
||||
println!("cargo:rustc-check-cfg=cfg(f128_enabled)");
|
||||
if cfg.reliable_f128 && !no_f16_f128 {
|
||||
println!("cargo:rustc-cfg=f128_enabled");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue