@@ -6,6 +6,7 @@ use std::sync::Once;
66use std:: { ptr, slice, str} ;
77
88use libc:: c_int;
9+ use rustc_codegen_ssa:: TargetConfig ;
910use rustc_codegen_ssa:: base:: wants_wasm_eh;
1011use rustc_codegen_ssa:: codegen_attrs:: check_tied_features;
1112use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
@@ -302,7 +303,7 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
302303/// Must express features in the way Rust understands them.
303304///
304305/// 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 {
306307 // Add base features for the target.
307308 // We do *not* add the -Ctarget-features there, and instead duplicate the logic for that below.
308309 // 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>)
402403
403404 let target_features = f ( false ) ;
404405 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 ;
406485}
407486
408487pub ( crate ) fn print_version ( ) {
@@ -686,7 +765,7 @@ pub(crate) fn global_llvm_features(
686765 )
687766 } else if let Some ( feature) = feature. strip_prefix ( '-' ) {
688767 // 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 `.
690769 // See <https://github.com/rust-lang/rust/issues/134792>.
691770 all_rust_features. push ( ( false , feature) ) ;
692771 } else if !feature. is_empty ( ) {
0 commit comments