22
33use std:: env;
44use std:: path:: PathBuf ;
5+ use std:: process:: { Command , Stdio } ;
56
67#[ allow( dead_code) ]
78pub 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
2127impl 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 Ok ( out) = cmd. output ( ) else {
46+ panic ! ( "failed to run `{cmd:?}`" )
47+ } ;
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