@@ -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