Skip to content

Commit 545c7ef

Browse files
committed
Use the compiler to determine whether or not to enable f16 and f128
1 parent cc53499 commit 545c7ef

File tree

5 files changed

+76
-107
lines changed

5 files changed

+76
-107
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/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
}

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: 38 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,10 @@ 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,
22+
pub reliable_f128_math: bool,
23+
pub reliable_f16_math: bool,
1924
}
2025

2126
impl Target {
@@ -32,6 +37,19 @@ impl Target {
3237
.map(|s| s.to_lowercase().replace("_", "-"))
3338
.collect();
3439

40+
// Query rustc for options that Cargo does not provide env for. The bootstrap hack is used
41+
// to get consistent output regardless of channel (`f16`/`f128` config options are hidden
42+
// on stable otherwise).
43+
let mut cmd = Command::new(env::var("RUSTC").unwrap());
44+
cmd.args(["--print=cfg", "--target", &triple])
45+
.env("RUSTC_BOOTSTRAP", "1")
46+
.stderr(Stdio::inherit());
47+
let out = cmd
48+
.output()
49+
.unwrap_or_else(|e| panic!("failed to run `{cmd:?}`: {e}"));
50+
assert!(out.status.success(), "failed to run `{cmd:?}`");
51+
let rustc_cfg = str::from_utf8(&out.stdout).unwrap();
52+
3553
Self {
3654
triple,
3755
triple_split,
@@ -51,6 +69,14 @@ impl Target {
5169
.split(",")
5270
.map(ToOwned::to_owned)
5371
.collect(),
72+
reliable_f128: rustc_cfg.lines().any(|l| l == "target_has_reliable_f128"),
73+
reliable_f16: rustc_cfg.lines().any(|l| l == "target_has_reliable_f16"),
74+
reliable_f128_math: rustc_cfg
75+
.lines()
76+
.any(|l| l == "target_has_reliable_f128_math"),
77+
reliable_f16_math: rustc_cfg
78+
.lines()
79+
.any(|l| l == "target_has_reliable_f16_math"),
5480
}
5581
}
5682

@@ -74,63 +100,24 @@ pub fn configure_aliases(target: &Target) {
74100
if target.triple_split[0] == "thumbv6m" || target.triple_split[0] == "thumbv8m.base" {
75101
println!("cargo:rustc-cfg=thumb_1")
76102
}
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-
};
105103

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-
};
104+
/* Not all backends support `f16` and `f128` to the same level on all architectures, so we
105+
* need to disable things if the compiler may crash. See configuration at:
106+
* * https://github.com/rust-lang/rust/blob/c65dccabacdfd6c8a7f7439eba13422fdd89b91e/compiler/rustc_codegen_llvm/src/llvm_util.rs#L367-L432
107+
* * https://github.com/rust-lang/rustc_codegen_gcc/blob/4b5c44b14166083eef8d71f15f5ea1f53fc976a0/src/lib.rs#L496-L507
108+
* * https://github.com/rust-lang/rustc_codegen_cranelift/blob/c713ffab3c6e28ab4b4dd4e392330f786ea657ad/src/lib.rs#L196-L226
109+
*/
122110

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

126114
println!("cargo::rustc-check-cfg=cfg(f16_enabled)");
127-
println!("cargo::rustc-check-cfg=cfg(f128_enabled)");
128-
129-
if f16_enabled && !disable_both {
115+
if target.reliable_f16 && !no_f16_f128 {
130116
println!("cargo::rustc-cfg=f16_enabled");
131117
}
132118

133-
if f128_enabled && !disable_both {
119+
println!("cargo::rustc-check-cfg=cfg(f128_enabled)");
120+
if target.reliable_f128 && !no_f16_f128 {
134121
println!("cargo::rustc-cfg=f128_enabled");
135122
}
136123
}

libm/configure.rs

Lines changed: 37 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,32 @@
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,
23+
pub reliable_f128_math: bool,
24+
pub reliable_f16_math: bool,
1925
}
2026

2127
impl Config {
2228
pub fn from_env() -> Self {
29+
let target_triple = env::var("TARGET").unwrap();
2330
let target_features = env::var("CARGO_CFG_TARGET_FEATURE")
2431
.map(|feats| feats.split(',').map(ToOwned::to_owned).collect())
2532
.unwrap_or_default();
@@ -28,7 +35,21 @@ impl Config {
2835
.map(|s| s.to_lowercase().replace("_", "-"))
2936
.collect();
3037

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", &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+
3151
Self {
52+
target_triple,
3253
manifest_dir: PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()),
3354
out_dir: PathBuf::from(env::var("OUT_DIR").unwrap()),
3455
opt_level: env::var("OPT_LEVEL").unwrap(),
@@ -40,6 +61,14 @@ impl Config {
4061
target_string: env::var("TARGET").unwrap(),
4162
target_vendor: env::var("CARGO_CFG_TARGET_VENDOR").unwrap(),
4263
target_features,
64+
reliable_f128: rustc_cfg.lines().any(|l| l == "target_has_reliable_f128"),
65+
reliable_f16: rustc_cfg.lines().any(|l| l == "target_has_reliable_f16"),
66+
reliable_f128_math: rustc_cfg
67+
.lines()
68+
.any(|l| l == "target_has_reliable_f128_math"),
69+
reliable_f16_math: rustc_cfg
70+
.lines()
71+
.any(|l| l == "target_has_reliable_f16_math"),
4372
}
4473
}
4574
}
@@ -128,62 +157,18 @@ fn emit_f16_f128_cfg(cfg: &Config) {
128157
return;
129158
}
130159

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();
160+
/* See the compiler-builtins configure file for info about the meaning of these options */
178161

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

182-
if f16_enabled && !disable_both {
165+
println!("cargo:rustc-check-cfg=cfg(f16_enabled)");
166+
if cfg.reliable_f16 && !no_f16_f128 {
183167
println!("cargo:rustc-cfg=f16_enabled");
184168
}
185169

186-
if f128_enabled && !disable_both {
170+
println!("cargo:rustc-check-cfg=cfg(f128_enabled)");
171+
if cfg.reliable_f128 && !no_f16_f128 {
187172
println!("cargo:rustc-cfg=f128_enabled");
188173
}
189174
}

0 commit comments

Comments
 (0)