@@ -6,6 +6,7 @@ use std::sync::Once;
6
6
use std:: { ptr, slice, str} ;
7
7
8
8
use libc:: c_int;
9
+ use rustc_codegen_ssa:: TargetConfig ;
9
10
use rustc_codegen_ssa:: base:: wants_wasm_eh;
10
11
use rustc_codegen_ssa:: codegen_attrs:: check_tied_features;
11
12
use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
@@ -302,7 +303,7 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
302
303
/// Must express features in the way Rust understands them.
303
304
///
304
305
/// We do not have to worry about RUSTC_SPECIFIC_FEATURES here, those are handled outside codegen.
305
- pub ( crate ) fn target_features_cfg ( sess : & Session ) -> ( Vec < Symbol > , Vec < Symbol > ) {
306
+ pub ( crate ) fn target_config ( sess : & Session ) -> TargetConfig {
306
307
// Add base features for the target.
307
308
// We do *not* add the -Ctarget-features there, and instead duplicate the logic for that below.
308
309
// The reason is that if LLVM considers a feature implied but we do not, we don't want that to
@@ -402,7 +403,85 @@ pub(crate) fn target_features_cfg(sess: &Session) -> (Vec<Symbol>, Vec<Symbol>)
402
403
403
404
let target_features = f ( false ) ;
404
405
let unstable_target_features = f ( true ) ;
405
- ( target_features, unstable_target_features)
406
+ let mut cfg = TargetConfig {
407
+ target_features,
408
+ unstable_target_features,
409
+ has_reliable_f16 : true ,
410
+ has_reliable_f16_math : true ,
411
+ has_reliable_f128 : true ,
412
+ has_reliable_f128_math : true ,
413
+ } ;
414
+
415
+ update_target_reliable_float_cfg ( sess, & mut cfg) ;
416
+ cfg
417
+ }
418
+
419
+ /// Determine whether or not experimental float types are reliable based on known bugs.
420
+ fn update_target_reliable_float_cfg ( sess : & Session , cfg : & mut TargetConfig ) {
421
+ let target_arch = sess. target . arch . as_ref ( ) ;
422
+ let target_os = sess. target . options . os . as_ref ( ) ;
423
+ let target_env = sess. target . options . env . as_ref ( ) ;
424
+ let target_abi = sess. target . options . abi . as_ref ( ) ;
425
+ let target_pointer_width = sess. target . pointer_width ;
426
+
427
+ cfg. has_reliable_f16 = match ( target_arch, target_os) {
428
+ // Selection failure <https://github.com/llvm/llvm-project/issues/50374>
429
+ ( "s390x" , _) => false ,
430
+ // Unsupported <https://github.com/llvm/llvm-project/issues/94434>
431
+ ( "arm64ec" , _) => false ,
432
+ // MinGW ABI bugs <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054>
433
+ ( "x86_64" , "windows" ) if target_env == "gnu" && target_abi != "llvm" => false ,
434
+ // Infinite recursion <https://github.com/llvm/llvm-project/issues/97981>
435
+ ( "csky" , _) => false ,
436
+ ( "hexagon" , _) => false ,
437
+ ( "powerpc" | "powerpc64" , _) => false ,
438
+ ( "sparc" | "sparc64" , _) => false ,
439
+ ( "wasm32" | "wasm64" , _) => false ,
440
+ // `f16` support only requires that symbols converting to and from `f32` are available. We
441
+ // provide these in `compiler-builtins`, so `f16` should be available on all platforms that
442
+ // do not have other ABI issues or LLVM crashes.
443
+ _ => true ,
444
+ } ;
445
+
446
+ cfg. has_reliable_f128 = match ( target_arch, target_os) {
447
+ // Unsupported <https://github.com/llvm/llvm-project/issues/94434>
448
+ ( "arm64ec" , _) => false ,
449
+ // Selection bug <https://github.com/llvm/llvm-project/issues/96432>
450
+ ( "mips64" | "mips64r6" , _) => false ,
451
+ // Selection bug <https://github.com/llvm/llvm-project/issues/95471>
452
+ ( "nvptx64" , _) => false ,
453
+ // ABI bugs <https://github.com/rust-lang/rust/issues/125109> et al. (full
454
+ // list at <https://github.com/rust-lang/rust/issues/116909>)
455
+ ( "powerpc" | "powerpc64" , _) => false ,
456
+ // ABI unsupported <https://github.com/llvm/llvm-project/issues/41838>
457
+ ( "sparc" , _) => false ,
458
+ // Stack alignment bug <https://github.com/llvm/llvm-project/issues/77401>. NB: tests may
459
+ // not fail if our compiler-builtins is linked.
460
+ ( "x86" , _) => false ,
461
+ // MinGW ABI bugs <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054>
462
+ ( "x86_64" , "windows" ) if target_env == "gnu" && target_abi != "llvm" => false ,
463
+ // There are no known problems on other platforms, so the only requirement is that symbols
464
+ // are available. `compiler-builtins` provides all symbols required for core `f128`
465
+ // support, so this should work for everything else.
466
+ _ => true ,
467
+ } ;
468
+
469
+ // Assume that working `f16` means working `f16` math for most platforms, since
470
+ // operations just go through `f32`.
471
+ cfg. has_reliable_f16_math = cfg. has_reliable_f16 ;
472
+
473
+ cfg. has_reliable_f128_math = match ( target_arch, target_os) {
474
+ // LLVM lowers `fp128` math to `long double` symbols even on platforms where
475
+ // `long double` is not IEEE binary128. See
476
+ // <https://github.com/llvm/llvm-project/issues/44744>.
477
+ //
478
+ // This rules out anything that doesn't have `long double` = `binary128`; <= 32 bits
479
+ // (ld is `f64`), anything other than Linux (Windows and MacOS use `f64`), and `x86`
480
+ // (ld is 80-bit extended precision).
481
+ ( "x86_64" , _) => false ,
482
+ ( _, "linux" ) if target_pointer_width == 64 => true ,
483
+ _ => false ,
484
+ } && cfg. has_reliable_f128 ;
406
485
}
407
486
408
487
pub ( crate ) fn print_version ( ) {
@@ -686,7 +765,7 @@ pub(crate) fn global_llvm_features(
686
765
)
687
766
} else if let Some ( feature) = feature. strip_prefix ( '-' ) {
688
767
// FIXME: Why do we not remove implied features on "-" here?
689
- // We do the equivalent above in `target_features_cfg `.
768
+ // We do the equivalent above in `target_config `.
690
769
// See <https://github.com/rust-lang/rust/issues/134792>.
691
770
all_rust_features. push ( ( false , feature) ) ;
692
771
} else if !feature. is_empty ( ) {
0 commit comments