Skip to content

Commit ed17b95

Browse files
committed
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.
1 parent 95abb0e commit ed17b95

File tree

8 files changed

+66
-111
lines changed

8 files changed

+66
-111
lines changed

builtins-test-intrinsics/build.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,5 @@ fn main() {
66
println!("cargo::rerun-if-changed=../configure.rs");
77

88
let target = builtins_configure::Target::from_env();
9-
builtins_configure::configure_f16_f128(&target);
109
builtins_configure::configure_aliases(&target);
1110
}

builtins-test/benches/float_cmp.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ float_bench! {
177177
],
178178
}
179179

180+
#[cfg(f128_enabled)]
180181
float_bench! {
181182
name: cmp_f128_gt,
182183
sig: (a: f128, b: f128) -> CmpResult,
@@ -189,6 +190,7 @@ float_bench! {
189190
asm: []
190191
}
191192

193+
#[cfg(f128_enabled)]
192194
float_bench! {
193195
name: cmp_f128_unord,
194196
sig: (a: f128, b: f128) -> CmpResult,

builtins-test/build.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,5 +116,4 @@ fn main() {
116116
}
117117

118118
builtins_configure::configure_aliases(&target);
119-
builtins_configure::configure_f16_f128(&target);
120119
}

builtins-test/tests/conv.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ mod i_to_f {
118118
i128, __floattidf;
119119
}
120120

121-
#[cfg(not(feature = "no-f16-f128"))]
121+
#[cfg(f128_enabled)]
122122
#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
123123
i_to_f! { f128, Quad, not(feature = "no-sys-f128-int-convert"),
124124
u32, __floatunsitf;
@@ -129,7 +129,7 @@ mod i_to_f {
129129
i128, __floattitf;
130130
}
131131

132-
#[cfg(not(feature = "no-f16-f128"))]
132+
#[cfg(f128_enabled)]
133133
#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
134134
i_to_f! { f128, Quad, not(feature = "no-sys-f128-int-convert"),
135135
u32, __floatunsikf;

builtins-test/tests/div_rem.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ mod float_div {
147147
f64, __divdf3, Double, all();
148148
}
149149

150-
#[cfg(not(feature = "no-f16-f128"))]
150+
#[cfg(f128_enabled)]
151151
#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
152152
float! {
153153
f128, __divtf3, Quad,
@@ -156,7 +156,7 @@ mod float_div {
156156
not(any(feature = "no-sys-f128", all(target_arch = "aarch64", target_os = "linux")));
157157
}
158158

159-
#[cfg(not(feature = "no-f16-f128"))]
159+
#[cfg(f128_enabled)]
160160
#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
161161
float! {
162162
f128, __divkf3, Quad, not(feature = "no-sys-f128");

compiler-builtins/build.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ mod configure;
22

33
use std::env;
44

5-
use configure::{Target, configure_aliases, configure_f16_f128};
5+
use configure::{Target, configure_aliases};
66

77
fn main() {
88
println!("cargo::rerun-if-changed=build.rs");
@@ -12,7 +12,6 @@ fn main() {
1212
let cwd = env::current_dir().unwrap();
1313

1414
configure_check_cfg();
15-
configure_f16_f128(&target);
1615
configure_aliases(&target);
1716

1817
configure_libm(&target);

compiler-builtins/configure.rs

Lines changed: 30 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Configuration that is shared between `compiler_builtins` and `builtins_test`.
22

3-
use std::env;
3+
use std::process::{Command, Stdio};
4+
use std::{env, str};
45

56
#[derive(Debug)]
67
#[allow(dead_code)]
@@ -16,6 +17,8 @@ pub struct Target {
1617
pub pointer_width: u8,
1718
pub little_endian: bool,
1819
pub features: Vec<String>,
20+
pub reliable_f128: bool,
21+
pub reliable_f16: bool,
1922
}
2023

2124
impl Target {
@@ -32,6 +35,19 @@ impl Target {
3235
.map(|s| s.to_lowercase().replace("_", "-"))
3336
.collect();
3437

38+
// Query rustc for options that Cargo does not provide env for. The bootstrap hack is used
39+
// to get consistent output regardless of channel (`f16`/`f128` config options are hidden
40+
// on stable otherwise).
41+
let mut cmd = Command::new(env::var("RUSTC").unwrap());
42+
cmd.args(["--print=cfg", "--target", &triple])
43+
.env("RUSTC_BOOTSTRAP", "1")
44+
.stderr(Stdio::inherit());
45+
let out = cmd
46+
.output()
47+
.unwrap_or_else(|e| panic!("failed to run `{cmd:?}`: {e}"));
48+
assert!(out.status.success(), "failed to run `{cmd:?}`");
49+
let rustc_cfg = str::from_utf8(&out.stdout).unwrap();
50+
3551
Self {
3652
triple,
3753
triple_split,
@@ -51,6 +67,8 @@ impl Target {
5167
.split(",")
5268
.map(ToOwned::to_owned)
5369
.collect(),
70+
reliable_f128: rustc_cfg.lines().any(|l| l == "target_has_reliable_f128"),
71+
reliable_f16: rustc_cfg.lines().any(|l| l == "target_has_reliable_f16"),
5472
}
5573
}
5674

@@ -74,63 +92,24 @@ pub fn configure_aliases(target: &Target) {
7492
if target.triple_split[0] == "thumbv6m" || target.triple_split[0] == "thumbv8m.base" {
7593
println!("cargo:rustc-cfg=thumb_1")
7694
}
77-
}
78-
79-
/// Configure whether or not `f16` and `f128` support should be enabled.
80-
pub fn configure_f16_f128(target: &Target) {
81-
// Set whether or not `f16` and `f128` are supported at a basic level by LLVM. This only means
82-
// that the backend will not crash when using these types and generates code that can be called
83-
// without crashing (no infinite recursion). This does not mean that the platform doesn't have
84-
// ABI or other bugs.
85-
//
86-
// We do this here rather than in `rust-lang/rust` because configuring via cargo features is
87-
// not straightforward.
88-
//
89-
// Original source of this list:
90-
// <https://github.com/rust-lang/compiler-builtins/pull/652#issuecomment-2266151350>
91-
let f16_enabled = match target.arch.as_str() {
92-
// Unsupported <https://github.com/llvm/llvm-project/issues/94434>
93-
"arm64ec" => false,
94-
// Selection failure <https://github.com/llvm/llvm-project/issues/50374>
95-
"s390x" => false,
96-
// Infinite recursion <https://github.com/llvm/llvm-project/issues/97981>
97-
"csky" => false,
98-
"hexagon" => false,
99-
"powerpc" | "powerpc64" => false,
100-
"sparc" | "sparc64" => false,
101-
"wasm32" | "wasm64" => false,
102-
// Most everything else works as of LLVM 19
103-
_ => true,
104-
};
10595

106-
let f128_enabled = match target.arch.as_str() {
107-
// Unsupported (libcall is not supported) <https://github.com/llvm/llvm-project/issues/121122>
108-
"amdgpu" => false,
109-
// Unsupported <https://github.com/llvm/llvm-project/issues/94434>
110-
"arm64ec" => false,
111-
// FIXME(llvm20): fixed by <https://github.com/llvm/llvm-project/pull/117525>
112-
"mips64" | "mips64r6" => false,
113-
// Selection failure <https://github.com/llvm/llvm-project/issues/95471>
114-
"nvptx64" => false,
115-
// Selection failure <https://github.com/llvm/llvm-project/issues/101545>
116-
"powerpc64" if &target.os == "aix" => false,
117-
// Selection failure <https://github.com/llvm/llvm-project/issues/41838>
118-
"sparc" => false,
119-
// Most everything else works as of LLVM 19
120-
_ => true,
121-
};
96+
/* Not all backends support `f16` and `f128` to the same level on all architectures, so we
97+
* need to disable things if the compiler may crash. See configuration at:
98+
* * https://github.com/rust-lang/rust/blob/c65dccabacdfd6c8a7f7439eba13422fdd89b91e/compiler/rustc_codegen_llvm/src/llvm_util.rs#L367-L432
99+
* * https://github.com/rust-lang/rustc_codegen_gcc/blob/4b5c44b14166083eef8d71f15f5ea1f53fc976a0/src/lib.rs#L496-L507
100+
* * https://github.com/rust-lang/rustc_codegen_cranelift/blob/c713ffab3c6e28ab4b4dd4e392330f786ea657ad/src/lib.rs#L196-L226
101+
*/
122102

123-
// If the feature is set, disable these types.
124-
let disable_both = env::var_os("CARGO_FEATURE_NO_F16_F128").is_some();
103+
// If the feature is set, disable both of these types.
104+
let no_f16_f128 = target.cargo_features.iter().any(|s| s == "no-f16-f128");
125105

126106
println!("cargo::rustc-check-cfg=cfg(f16_enabled)");
127-
println!("cargo::rustc-check-cfg=cfg(f128_enabled)");
128-
129-
if f16_enabled && !disable_both {
107+
if target.reliable_f16 && !no_f16_f128 {
130108
println!("cargo::rustc-cfg=f16_enabled");
131109
}
132110

133-
if f128_enabled && !disable_both {
111+
println!("cargo::rustc-check-cfg=cfg(f128_enabled)");
112+
if target.reliable_f128 && !no_f16_f128 {
134113
println!("cargo::rustc-cfg=f128_enabled");
135114
}
136115
}

libm/configure.rs

Lines changed: 29 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,30 @@
11
// Configuration shared with both libm and libm-test
22

3-
use std::env;
43
use std::path::PathBuf;
4+
use std::process::{Command, Stdio};
5+
use std::{env, str};
56

67
#[allow(dead_code)]
78
pub struct Config {
89
pub manifest_dir: PathBuf,
910
pub out_dir: PathBuf,
1011
pub opt_level: String,
1112
pub cargo_features: Vec<String>,
13+
pub target_triple: String,
1214
pub target_arch: String,
1315
pub target_env: String,
1416
pub target_family: Option<String>,
1517
pub target_os: String,
1618
pub target_string: String,
1719
pub target_vendor: String,
1820
pub target_features: Vec<String>,
21+
pub reliable_f128: bool,
22+
pub reliable_f16: bool,
1923
}
2024

2125
impl Config {
2226
pub fn from_env() -> Self {
27+
let target_triple = env::var("TARGET").unwrap();
2328
let target_features = env::var("CARGO_CFG_TARGET_FEATURE")
2429
.map(|feats| feats.split(',').map(ToOwned::to_owned).collect())
2530
.unwrap_or_default();
@@ -28,7 +33,21 @@ impl Config {
2833
.map(|s| s.to_lowercase().replace("_", "-"))
2934
.collect();
3035

36+
// Query rustc for options that Cargo does not provide env for. The bootstrap hack is used
37+
// to get consistent output regardless of channel (`f16`/`f128` config options are hidden
38+
// on stable otherwise).
39+
let mut cmd = Command::new(env::var("RUSTC").unwrap());
40+
cmd.args(["--print=cfg", "--target", &target_triple])
41+
.env("RUSTC_BOOTSTRAP", "1")
42+
.stderr(Stdio::inherit());
43+
let out = cmd
44+
.output()
45+
.unwrap_or_else(|e| panic!("failed to run `{cmd:?}`: {e}"));
46+
assert!(out.status.success(), "failed to run `{cmd:?}`");
47+
let rustc_cfg = str::from_utf8(&out.stdout).unwrap();
48+
3149
Self {
50+
target_triple,
3251
manifest_dir: PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()),
3352
out_dir: PathBuf::from(env::var("OUT_DIR").unwrap()),
3453
opt_level: env::var("OPT_LEVEL").unwrap(),
@@ -40,6 +59,8 @@ impl Config {
4059
target_string: env::var("TARGET").unwrap(),
4160
target_vendor: env::var("CARGO_CFG_TARGET_VENDOR").unwrap(),
4261
target_features,
62+
reliable_f128: rustc_cfg.lines().any(|l| l == "target_has_reliable_f128"),
63+
reliable_f16: rustc_cfg.lines().any(|l| l == "target_has_reliable_f16"),
4364
}
4465
}
4566
}
@@ -128,62 +149,18 @@ fn emit_f16_f128_cfg(cfg: &Config) {
128149
return;
129150
}
130151

131-
// Set whether or not `f16` and `f128` are supported at a basic level by LLVM. This only means
132-
// that the backend will not crash when using these types and generates code that can be called
133-
// without crashing (no infinite recursion). This does not mean that the platform doesn't have
134-
// ABI or other bugs.
135-
//
136-
// We do this here rather than in `rust-lang/rust` because configuring via cargo features is
137-
// not straightforward.
138-
//
139-
// Original source of this list:
140-
// <https://github.com/rust-lang/compiler-builtins/pull/652#issuecomment-2266151350>
141-
let f16_enabled = match cfg.target_arch.as_str() {
142-
// Unsupported <https://github.com/llvm/llvm-project/issues/94434>
143-
"arm64ec" => false,
144-
// Selection failure <https://github.com/llvm/llvm-project/issues/50374>
145-
"s390x" => false,
146-
// Infinite recursion <https://github.com/llvm/llvm-project/issues/97981>
147-
// FIXME(llvm): loongarch fixed by <https://github.com/llvm/llvm-project/pull/107791>
148-
"csky" => false,
149-
"hexagon" => false,
150-
"loongarch64" => false,
151-
"mips" | "mips64" | "mips32r6" | "mips64r6" => false,
152-
"powerpc" | "powerpc64" => false,
153-
"sparc" | "sparc64" => false,
154-
"wasm32" | "wasm64" => false,
155-
// Most everything else works as of LLVM 19
156-
_ => true,
157-
};
158-
159-
let f128_enabled = match cfg.target_arch.as_str() {
160-
// Unsupported (libcall is not supported) <https://github.com/llvm/llvm-project/issues/121122>
161-
"amdgpu" => false,
162-
// Unsupported <https://github.com/llvm/llvm-project/issues/94434>
163-
"arm64ec" => false,
164-
// Selection failure <https://github.com/llvm/llvm-project/issues/96432>
165-
"mips64" | "mips64r6" => false,
166-
// Selection failure <https://github.com/llvm/llvm-project/issues/95471>
167-
"nvptx64" => false,
168-
// Selection failure <https://github.com/llvm/llvm-project/issues/101545>
169-
"powerpc64" if &cfg.target_os == "aix" => false,
170-
// Selection failure <https://github.com/llvm/llvm-project/issues/41838>
171-
"sparc" => false,
172-
// Most everything else works as of LLVM 19
173-
_ => true,
174-
};
175-
176-
// If the feature is set, disable these types.
177-
let disable_both = env::var_os("CARGO_FEATURE_NO_F16_F128").is_some();
152+
/* See the compiler-builtins configure file for info about the meaning of these options */
178153

179-
println!("cargo:rustc-check-cfg=cfg(f16_enabled)");
180-
println!("cargo:rustc-check-cfg=cfg(f128_enabled)");
154+
// If the feature is set, disable both of these types.
155+
let no_f16_f128 = cfg.cargo_features.iter().any(|s| s == "no-f16-f128");
181156

182-
if f16_enabled && !disable_both {
157+
println!("cargo:rustc-check-cfg=cfg(f16_enabled)");
158+
if cfg.reliable_f16 && !no_f16_f128 {
183159
println!("cargo:rustc-cfg=f16_enabled");
184160
}
185161

186-
if f128_enabled && !disable_both {
162+
println!("cargo:rustc-check-cfg=cfg(f128_enabled)");
163+
if cfg.reliable_f128 && !no_f16_f128 {
187164
println!("cargo:rustc-cfg=f128_enabled");
188165
}
189166
}

0 commit comments

Comments
 (0)