Thanks to visit codestin.com
Credit goes to github.com

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)