|
| 1 | +// This portion of configuration is shared between `std` and `coretests`. |
| 2 | + |
| 3 | +use std::env; |
| 4 | + |
| 5 | +#[allow(dead_code)] // Not all importers of this file use all fields |
| 6 | +pub struct Config { |
| 7 | + pub target_arch: String, |
| 8 | + pub target_os: String, |
| 9 | + pub target_vendor: String, |
| 10 | + pub target_env: String, |
| 11 | + pub target_abi: String, |
| 12 | + pub target_pointer_width: u32, |
| 13 | + pub target_features: Vec<String>, |
| 14 | + pub is_miri: bool, |
| 15 | +} |
| 16 | + |
| 17 | +impl Config { |
| 18 | + pub fn from_env() -> Self { |
| 19 | + Self { |
| 20 | + target_arch: env::var("CARGO_CFG_TARGET_ARCH") |
| 21 | + .expect("CARGO_CFG_TARGET_ARCH was not set"), |
| 22 | + target_os: env::var("CARGO_CFG_TARGET_OS").expect("CARGO_CFG_TARGET_OS was not set"), |
| 23 | + target_vendor: env::var("CARGO_CFG_TARGET_VENDOR") |
| 24 | + .expect("CARGO_CFG_TARGET_VENDOR was not set"), |
| 25 | + target_env: env::var("CARGO_CFG_TARGET_ENV").expect("CARGO_CFG_TARGET_ENV was not set"), |
| 26 | + target_abi: env::var("CARGO_CFG_TARGET_ABI").expect("CARGO_CFG_TARGET_ABI was not set"), |
| 27 | + target_pointer_width: env::var("CARGO_CFG_TARGET_POINTER_WIDTH") |
| 28 | + .expect("CARGO_CFG_TARGET_POINTER_WIDTH was not set") |
| 29 | + .parse() |
| 30 | + .unwrap(), |
| 31 | + target_features: env::var("CARGO_CFG_TARGET_FEATURE") |
| 32 | + .unwrap_or_default() |
| 33 | + .split(",") |
| 34 | + .map(ToOwned::to_owned) |
| 35 | + .collect(), |
| 36 | + is_miri: env::var_os("CARGO_CFG_MIRI").is_some(), |
| 37 | + } |
| 38 | + } |
| 39 | +} |
| 40 | + |
| 41 | +pub fn configure_f16_f128(cfg: &Config) { |
| 42 | + // Emit these on platforms that have no known ABI bugs, LLVM selection bugs, lowering bugs, |
| 43 | + // missing symbols, or other problems, to determine when tests get run. |
| 44 | + // If more broken platforms are found, please update the tracking issue at |
| 45 | + // <https://github.com/rust-lang/rust/issues/116909> |
| 46 | + // |
| 47 | + // Some of these match arms are redundant; the goal is to separate reasons that the type is |
| 48 | + // unreliable, even when multiple reasons might fail the same platform. |
| 49 | + println!("cargo:rustc-check-cfg=cfg(reliable_f16)"); |
| 50 | + println!("cargo:rustc-check-cfg=cfg(reliable_f128)"); |
| 51 | + |
| 52 | + // This is a step beyond only having the types and basic functions available. Math functions |
| 53 | + // aren't consistently available or correct. |
| 54 | + println!("cargo:rustc-check-cfg=cfg(reliable_f16_math)"); |
| 55 | + println!("cargo:rustc-check-cfg=cfg(reliable_f128_math)"); |
| 56 | + |
| 57 | + let target_arch = cfg.target_arch.as_str(); |
| 58 | + let target_os = cfg.target_os.as_str(); |
| 59 | + |
| 60 | + let has_reliable_f16 = match (target_arch, target_os) { |
| 61 | + // We can always enable these in Miri as that is not affected by codegen bugs. |
| 62 | + _ if cfg.is_miri => true, |
| 63 | + // Selection failure <https://github.com/llvm/llvm-project/issues/50374> |
| 64 | + ("s390x", _) => false, |
| 65 | + // Unsupported <https://github.com/llvm/llvm-project/issues/94434> |
| 66 | + ("arm64ec", _) => false, |
| 67 | + // MinGW ABI bugs <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054> |
| 68 | + ("x86_64", "windows") if cfg.target_env == "gnu" && cfg.target_abi != "llvm" => false, |
| 69 | + // Infinite recursion <https://github.com/llvm/llvm-project/issues/97981> |
| 70 | + ("csky", _) => false, |
| 71 | + ("hexagon", _) => false, |
| 72 | + ("loongarch64", _) => false, |
| 73 | + ("mips" | "mips64" | "mips32r6" | "mips64r6", _) => false, |
| 74 | + ("powerpc" | "powerpc64", _) => false, |
| 75 | + ("sparc" | "sparc64", _) => false, |
| 76 | + ("wasm32" | "wasm64", _) => false, |
| 77 | + // `f16` support only requires that symbols converting to and from `f32` are available. We |
| 78 | + // provide these in `compiler-builtins`, so `f16` should be available on all platforms that |
| 79 | + // do not have other ABI issues or LLVM crashes. |
| 80 | + _ => true, |
| 81 | + }; |
| 82 | + |
| 83 | + let has_reliable_f128 = match (target_arch, target_os) { |
| 84 | + // We can always enable these in Miri as that is not affected by codegen bugs. |
| 85 | + _ if cfg.is_miri => true, |
| 86 | + // Unsupported <https://github.com/llvm/llvm-project/issues/94434> |
| 87 | + ("arm64ec", _) => false, |
| 88 | + // Selection bug <https://github.com/llvm/llvm-project/issues/96432> |
| 89 | + ("mips64" | "mips64r6", _) => false, |
| 90 | + // Selection bug <https://github.com/llvm/llvm-project/issues/95471> |
| 91 | + ("nvptx64", _) => false, |
| 92 | + // ABI bugs <https://github.com/rust-lang/rust/issues/125109> et al. (full |
| 93 | + // list at <https://github.com/rust-lang/rust/issues/116909>) |
| 94 | + ("powerpc" | "powerpc64", _) => false, |
| 95 | + // ABI unsupported <https://github.com/llvm/llvm-project/issues/41838> |
| 96 | + ("sparc", _) => false, |
| 97 | + // Stack alignment bug <https://github.com/llvm/llvm-project/issues/77401>. NB: tests may |
| 98 | + // not fail if our compiler-builtins is linked. |
| 99 | + ("x86", _) => false, |
| 100 | + // MinGW ABI bugs <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054> |
| 101 | + ("x86_64", "windows") if cfg.target_env == "gnu" && cfg.target_abi != "llvm" => false, |
| 102 | + // There are no known problems on other platforms, so the only requirement is that symbols |
| 103 | + // are available. `compiler-builtins` provides all symbols required for core `f128` |
| 104 | + // support, so this should work for everything else. |
| 105 | + _ => true, |
| 106 | + }; |
| 107 | + |
| 108 | + // Configure platforms that have reliable basics but may have unreliable math. |
| 109 | + |
| 110 | + // LLVM is currently adding missing routines, <https://github.com/llvm/llvm-project/issues/93566> |
| 111 | + let has_reliable_f16_math = has_reliable_f16 |
| 112 | + && match (target_arch, target_os) { |
| 113 | + // FIXME: Disabled on Miri as the intrinsics are not implemented yet. |
| 114 | + _ if cfg.is_miri => false, |
| 115 | + // x86 has a crash for `powi`: <https://github.com/llvm/llvm-project/issues/105747> |
| 116 | + ("x86" | "x86_64", _) => false, |
| 117 | + // Assume that working `f16` means working `f16` math for most platforms, since |
| 118 | + // operations just go through `f32`. |
| 119 | + _ => true, |
| 120 | + }; |
| 121 | + |
| 122 | + let has_reliable_f128_math = has_reliable_f128 |
| 123 | + && match (target_arch, target_os) { |
| 124 | + // FIXME: Disabled on Miri as the intrinsics are not implemented yet. |
| 125 | + _ if cfg.is_miri => false, |
| 126 | + // LLVM lowers `fp128` math to `long double` symbols even on platforms where |
| 127 | + // `long double` is not IEEE binary128. See |
| 128 | + // <https://github.com/llvm/llvm-project/issues/44744>. |
| 129 | + // |
| 130 | + // This rules out anything that doesn't have `long double` = `binary128`; <= 32 bits |
| 131 | + // (ld is `f64`), anything other than Linux (Windows and MacOS use `f64`), and `x86` |
| 132 | + // (ld is 80-bit extended precision). |
| 133 | + ("x86_64", _) => false, |
| 134 | + (_, "linux") if cfg.target_pointer_width == 64 => true, |
| 135 | + _ => false, |
| 136 | + }; |
| 137 | + |
| 138 | + if has_reliable_f16 { |
| 139 | + println!("cargo:rustc-cfg=reliable_f16"); |
| 140 | + } |
| 141 | + if has_reliable_f128 { |
| 142 | + println!("cargo:rustc-cfg=reliable_f128"); |
| 143 | + } |
| 144 | + if has_reliable_f16_math { |
| 145 | + println!("cargo:rustc-cfg=reliable_f16_math"); |
| 146 | + } |
| 147 | + if has_reliable_f128_math { |
| 148 | + println!("cargo:rustc-cfg=reliable_f128_math"); |
| 149 | + } |
| 150 | +} |
0 commit comments