Skip to content

Commit 4055b73

Browse files
committed
Auto merge of #140323 - tgross35:cfg-unstable-float, r=<try>
Implement the internal feature `cfg_target_has_reliable_f16_f128` Support for `f16` and `f128` is varied across targets, backends, and backend versions. Eventually we would like to reach a point where all backends support these approximately equally, but until then we have to work around some of these nuances of support being observable. Introduce the `target_has_reliable_f16_f128` configuration option, gated behind `cfg_target_has_reliable_f16_f128`, as an indicator for whether or not the backend supports these types to a point that they can and should be tested. The configuration mostly follows the logic used by `target_feature`, and similarly takes a value: #[cfg(target_has_reliable_f16_f128 = "f16")] Accepted values are: * `f16` * `f16-math` * `f128` * `f128-math` `f16` and `f128` indicate that basic arithmetic for the type works correctly. The `-math` versions indicate that anything relying on `libm` works correctly, since sometimes this hits a separate class of codegen bugs. These options match configuration set by the build script at [1]. The logic for LLVM support is duplicated as-is from the same script. There are a few possible updates that will come as a follow up. The config introduced here is not intended to ever become stable, it is only intended to replace the build scripts for `std` tests and in `compiler-builtins` that don't have any way to set configuration based on the codegen backend. MCP: rust-lang/compiler-team#866 Closes: rust-lang/compiler-team#866 [1]: https://github.com/rust-lang/rust/blob/555e1d0386f024a8359645c3217f4b3eae9be042/library/std/build.rs#L84-L186 --- The second commit makes use of this config to replace `cfg_{f16,f128}{,_math}` in `library/`. try-job: aarch64-gnu try-job: i686-msvc-1 try-job: test-various try-job: x86_64-gnu try-job: x86_64-msvc-ext2
2 parents d3508a8 + e7fb9c5 commit 4055b73

33 files changed

+805
-294
lines changed

compiler/rustc_codegen_cranelift/src/lib.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ use std::sync::Arc;
4141

4242
use cranelift_codegen::isa::TargetIsa;
4343
use cranelift_codegen::settings::{self, Configurable};
44-
use rustc_codegen_ssa::CodegenResults;
4544
use rustc_codegen_ssa::traits::CodegenBackend;
45+
use rustc_codegen_ssa::{CodegenResults, TargetFeatureCfg};
4646
use rustc_metadata::EncodedMetadata;
4747
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
4848
use rustc_session::Session;
@@ -178,7 +178,7 @@ impl CodegenBackend for CraneliftCodegenBackend {
178178
}
179179
}
180180

181-
fn target_features_cfg(&self, sess: &Session) -> (Vec<Symbol>, Vec<Symbol>) {
181+
fn target_features_cfg(&self, sess: &Session) -> TargetFeatureCfg {
182182
// FIXME return the actually used target features. this is necessary for #[cfg(target_feature)]
183183
let target_features = if sess.target.arch == "x86_64" && sess.target.os != "none" {
184184
// x86_64 mandates SSE2 support and rustc requires the x87 feature to be enabled
@@ -197,7 +197,13 @@ impl CodegenBackend for CraneliftCodegenBackend {
197197
};
198198
// FIXME do `unstable_target_features` properly
199199
let unstable_target_features = target_features.clone();
200-
(target_features, unstable_target_features)
200+
201+
TargetFeatureCfg {
202+
target_features,
203+
unstable_target_features,
204+
// Cranelift does not yet support f16 or f128
205+
reliable_unstable_float: vec![],
206+
}
201207
}
202208

203209
fn print_version(&self) {

compiler/rustc_codegen_gcc/src/lib.rs

+10-8
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ use rustc_codegen_ssa::back::write::{
102102
};
103103
use rustc_codegen_ssa::base::codegen_crate;
104104
use rustc_codegen_ssa::traits::{CodegenBackend, ExtraBackendMethods, WriteBackendMethods};
105-
use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen};
105+
use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen, TargetFeatureCfg};
106106
use rustc_data_structures::fx::FxIndexMap;
107107
use rustc_data_structures::sync::IntoDynSyncSend;
108108
use rustc_errors::DiagCtxtHandle;
@@ -112,8 +112,8 @@ use rustc_middle::ty::TyCtxt;
112112
use rustc_middle::util::Providers;
113113
use rustc_session::Session;
114114
use rustc_session::config::{OptLevel, OutputFilenames};
115-
use rustc_span::Symbol;
116115
use rustc_span::fatal_error::FatalError;
116+
use rustc_span::{Symbol, sym};
117117
use rustc_target::spec::RelocModel;
118118
use tempfile::TempDir;
119119

@@ -260,7 +260,7 @@ impl CodegenBackend for GccCodegenBackend {
260260
.join(sess)
261261
}
262262

263-
fn target_features_cfg(&self, sess: &Session) -> (Vec<Symbol>, Vec<Symbol>) {
263+
fn target_features_cfg(&self, sess: &Session) -> TargetFeatureCfg {
264264
target_features_cfg(sess, &self.target_info)
265265
}
266266
}
@@ -485,10 +485,7 @@ fn to_gcc_opt_level(optlevel: Option<OptLevel>) -> OptimizationLevel {
485485
}
486486

487487
/// Returns the features that should be set in `cfg(target_feature)`.
488-
fn target_features_cfg(
489-
sess: &Session,
490-
target_info: &LockedTargetInfo,
491-
) -> (Vec<Symbol>, Vec<Symbol>) {
488+
fn target_features_cfg(sess: &Session, target_info: &LockedTargetInfo) -> TargetFeatureCfg {
492489
// TODO(antoyo): use global_gcc_features.
493490
let f = |allow_unstable| {
494491
sess.target
@@ -523,5 +520,10 @@ fn target_features_cfg(
523520

524521
let target_features = f(false);
525522
let unstable_target_features = f(true);
526-
(target_features, unstable_target_features)
523+
524+
// There are no known bugs with GCC support for f16 or f128
525+
let reliable_unstable_float =
526+
[sym::f16, sym::f16_dash_math, sym::f128, sym::f128_dash_math].to_vec();
527+
528+
TargetFeatureCfg { target_features, unstable_target_features, reliable_unstable_float }
527529
}

compiler/rustc_codegen_llvm/src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ use rustc_codegen_ssa::back::write::{
3737
CodegenContext, FatLtoInput, ModuleConfig, TargetMachineFactoryConfig, TargetMachineFactoryFn,
3838
};
3939
use rustc_codegen_ssa::traits::*;
40-
use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen};
40+
use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen, TargetFeatureCfg};
4141
use rustc_data_structures::fx::FxIndexMap;
4242
use rustc_errors::{DiagCtxtHandle, FatalError};
4343
use rustc_metadata::EncodedMetadata;
@@ -338,7 +338,7 @@ impl CodegenBackend for LlvmCodegenBackend {
338338
llvm_util::print_version();
339339
}
340340

341-
fn target_features_cfg(&self, sess: &Session) -> (Vec<Symbol>, Vec<Symbol>) {
341+
fn target_features_cfg(&self, sess: &Session) -> TargetFeatureCfg {
342342
target_features_cfg(sess)
343343
}
344344

compiler/rustc_codegen_llvm/src/llvm_util.rs

+97-3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use std::sync::Once;
66
use std::{ptr, slice, str};
77

88
use libc::c_int;
9+
use rustc_codegen_ssa::TargetFeatureCfg;
910
use rustc_codegen_ssa::base::wants_wasm_eh;
1011
use rustc_codegen_ssa::codegen_attrs::check_tied_features;
1112
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -15,7 +16,7 @@ use rustc_fs_util::path_to_c_string;
1516
use rustc_middle::bug;
1617
use rustc_session::Session;
1718
use rustc_session::config::{PrintKind, PrintRequest};
18-
use rustc_span::Symbol;
19+
use rustc_span::{Symbol, sym};
1920
use rustc_target::spec::{MergeFunctions, PanicStrategy, SmallDataThresholdSupport};
2021
use rustc_target::target_features::{RUSTC_SPECIAL_FEATURES, RUSTC_SPECIFIC_FEATURES};
2122

@@ -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_features_cfg(sess: &Session) -> TargetFeatureCfg {
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,100 @@ 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+
407+
TargetFeatureCfg {
408+
target_features,
409+
unstable_target_features,
410+
reliable_unstable_float: target_features_cfg_float(sess),
411+
}
412+
}
413+
414+
/// Determine whether or not experimental float types are reliable based on known bugs.
415+
fn target_features_cfg_float(sess: &Session) -> Vec<Symbol> {
416+
let mut ret = Vec::new();
417+
let target_arch = sess.target.arch.as_ref();
418+
let target_os = sess.target.options.os.as_ref();
419+
let target_env = sess.target.options.env.as_ref();
420+
let target_abi = sess.target.options.abi.as_ref();
421+
let target_pointer_width = sess.target.pointer_width;
422+
423+
let has_reliable_f16 = match (target_arch, target_os) {
424+
// Selection failure <https://github.com/llvm/llvm-project/issues/50374>
425+
("s390x", _) => false,
426+
// Unsupported <https://github.com/llvm/llvm-project/issues/94434>
427+
("arm64ec", _) => false,
428+
// MinGW ABI bugs <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054>
429+
("x86_64", "windows") if target_env == "gnu" && target_abi != "llvm" => false,
430+
// Infinite recursion <https://github.com/llvm/llvm-project/issues/97981>
431+
("csky", _) => false,
432+
("hexagon", _) => false,
433+
("powerpc" | "powerpc64", _) => false,
434+
("sparc" | "sparc64", _) => false,
435+
("wasm32" | "wasm64", _) => false,
436+
// `f16` support only requires that symbols converting to and from `f32` are available. We
437+
// provide these in `compiler-builtins`, so `f16` should be available on all platforms that
438+
// do not have other ABI issues or LLVM crashes.
439+
_ => true,
440+
};
441+
442+
let has_reliable_f128 = match (target_arch, target_os) {
443+
// Unsupported <https://github.com/llvm/llvm-project/issues/94434>
444+
("arm64ec", _) => false,
445+
// Selection bug <https://github.com/llvm/llvm-project/issues/96432>
446+
("mips64" | "mips64r6", _) => false,
447+
// Selection bug <https://github.com/llvm/llvm-project/issues/95471>
448+
("nvptx64", _) => false,
449+
// ABI bugs <https://github.com/rust-lang/rust/issues/125109> et al. (full
450+
// list at <https://github.com/rust-lang/rust/issues/116909>)
451+
("powerpc" | "powerpc64", _) => false,
452+
// ABI unsupported <https://github.com/llvm/llvm-project/issues/41838>
453+
("sparc", _) => false,
454+
// Stack alignment bug <https://github.com/llvm/llvm-project/issues/77401>. NB: tests may
455+
// not fail if our compiler-builtins is linked.
456+
("x86", _) => false,
457+
// MinGW ABI bugs <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054>
458+
("x86_64", "windows") if target_env == "gnu" && target_abi != "llvm" => false,
459+
// There are no known problems on other platforms, so the only requirement is that symbols
460+
// are available. `compiler-builtins` provides all symbols required for core `f128`
461+
// support, so this should work for everything else.
462+
_ => true,
463+
};
464+
465+
let has_reliable_f16_math = match (target_arch, target_os) {
466+
// x86 has a crash for `powi`: <https://github.com/llvm/llvm-project/issues/105747>
467+
("x86" | "x86_64", _) => false,
468+
// Assume that working `f16` means working `f16` math for most platforms, since
469+
// operations just go through `f32`.
470+
_ => has_reliable_f16,
471+
} && has_reliable_f16;
472+
473+
let 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+
} && has_reliable_f128;
485+
486+
if has_reliable_f16 {
487+
ret.push(sym::f16);
488+
}
489+
if has_reliable_f16_math {
490+
ret.push(sym::f16_dash_math);
491+
}
492+
if has_reliable_f128 {
493+
ret.push(sym::f128);
494+
}
495+
if has_reliable_f128_math {
496+
ret.push(sym::f128_dash_math);
497+
}
498+
499+
ret
406500
}
407501

408502
pub(crate) fn print_version() {

compiler/rustc_codegen_ssa/src/lib.rs

+13
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,19 @@ pub struct CrateInfo {
235235
pub lint_levels: CodegenLintLevels,
236236
}
237237

238+
/// Target-specific feature support.
239+
///
240+
/// RUSTC_SPECIFIC_FEATURES should be skipped here, those are handled outside codegen.
241+
pub struct TargetFeatureCfg {
242+
/// Options to be set in `cfg(target_features)`.
243+
pub target_features: Vec<Symbol>,
244+
/// Options to be set in `cfg(target_features)`, but including unstable features.
245+
pub unstable_target_features: Vec<Symbol>,
246+
/// Options to set in `cfg(target_has_reliable_f16_f128)` Valid options are `f16`, `f128`,
247+
/// `f16-math`, and `f128-math`.
248+
pub reliable_unstable_float: Vec<Symbol>,
249+
}
250+
238251
#[derive(Encodable, Decodable)]
239252
pub struct CodegenResults {
240253
pub modules: Vec<CompiledModule>,

compiler/rustc_codegen_ssa/src/traits/backend.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use super::write::WriteBackendMethods;
1818
use crate::back::archive::ArArchiveBuilderBuilder;
1919
use crate::back::link::link_binary;
2020
use crate::back::write::TargetMachineFactoryFn;
21-
use crate::{CodegenResults, ModuleCodegen};
21+
use crate::{CodegenResults, ModuleCodegen, TargetFeatureCfg};
2222

2323
pub trait BackendTypes {
2424
type Value: CodegenObject;
@@ -50,8 +50,12 @@ pub trait CodegenBackend {
5050
/// - The second is like the first, but also includes unstable features.
5151
///
5252
/// RUSTC_SPECIFIC_FEATURES should be skipped here, those are handled outside codegen.
53-
fn target_features_cfg(&self, _sess: &Session) -> (Vec<Symbol>, Vec<Symbol>) {
54-
(vec![], vec![])
53+
fn target_features_cfg(&self, _sess: &Session) -> TargetFeatureCfg {
54+
TargetFeatureCfg {
55+
target_features: vec![],
56+
unstable_target_features: vec![],
57+
reliable_unstable_float: vec![],
58+
}
5559
}
5660

5761
fn print_passes(&self) {}

compiler/rustc_feature/src/builtin_attrs.rs

+5
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ const GATED_CFGS: &[GatedCfg] = &[
4040
// this is consistent with naming of the compiler flag it's for
4141
(sym::fmt_debug, sym::fmt_debug, Features::fmt_debug),
4242
(sym::emscripten_wasm_eh, sym::cfg_emscripten_wasm_eh, Features::cfg_emscripten_wasm_eh),
43+
(
44+
sym::target_has_reliable_f16_f128,
45+
sym::cfg_target_has_reliable_f16_f128,
46+
Features::cfg_target_has_reliable_f16_f128,
47+
),
4348
];
4449

4550
/// Find a gated cfg determined by the `pred`icate which is given the cfg's name.

compiler/rustc_feature/src/unstable.rs

+2
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,8 @@ declare_features! (
205205
(unstable, anonymous_lifetime_in_impl_trait, "1.63.0", None),
206206
/// Allows access to the emscripten_wasm_eh config, used by panic_unwind and unwind
207207
(internal, cfg_emscripten_wasm_eh, "1.86.0", None),
208+
/// Allows checking whether or not the backend correctly supports unstable float types.
209+
(internal, cfg_target_has_reliable_f16_f128, "CURRENT_RUSTC_VERSION", None),
208210
/// Allows identifying the `compiler_builtins` crate.
209211
(internal, compiler_builtins, "1.13.0", None),
210212
/// Allows writing custom MIR

compiler/rustc_interface/src/util.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std::sync::atomic::{AtomicBool, Ordering};
55
use std::{env, iter, thread};
66

77
use rustc_ast as ast;
8+
use rustc_codegen_ssa::TargetFeatureCfg;
89
use rustc_codegen_ssa::traits::CodegenBackend;
910
use rustc_data_structures::sync;
1011
use rustc_metadata::{DylibError, load_symbol_from_dylib};
@@ -39,13 +40,19 @@ pub(crate) fn add_configuration(
3940
) {
4041
let tf = sym::target_feature;
4142

42-
let (target_features, unstable_target_features) = codegen_backend.target_features_cfg(sess);
43+
let TargetFeatureCfg { target_features, unstable_target_features, reliable_unstable_float } =
44+
codegen_backend.target_features_cfg(sess);
4345

4446
sess.unstable_target_features.extend(unstable_target_features.iter().copied());
4547

4648
sess.target_features.extend(target_features.iter().copied());
4749

4850
cfg.extend(target_features.into_iter().map(|feat| (tf, Some(feat))));
51+
cfg.extend(
52+
reliable_unstable_float
53+
.into_iter()
54+
.map(|feat| (sym::target_has_reliable_f16_f128, Some(feat))),
55+
);
4956

5057
if sess.crt_static(None) {
5158
cfg.insert((tf, Some(sym::crt_dash_static)));

compiler/rustc_session/src/config/cfg.rs

+4
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ pub(crate) fn disallow_cfgs(sess: &Session, user_cfgs: &Cfg) {
142142
| (sym::target_has_atomic, Some(_))
143143
| (sym::target_has_atomic_equal_alignment, Some(_))
144144
| (sym::target_has_atomic_load_store, Some(_))
145+
| (sym::target_has_reliable_f16_f128, Some(_))
145146
| (sym::target_thread_local, None) => disallow(cfg, "--target"),
146147
(sym::fmt_debug, None | Some(_)) => disallow(cfg, "-Z fmt-debug"),
147148
(sym::emscripten_wasm_eh, None | Some(_)) => disallow(cfg, "-Z emscripten_wasm_eh"),
@@ -463,6 +464,9 @@ impl CheckCfg {
463464
ins!(sym, no_values).extend(atomic_values);
464465
}
465466

467+
let reliable_float_vals = [sym::f16, sym::f128, sym::f16_dash_math, sym::f128_dash_math];
468+
ins!(sym::target_has_reliable_f16_f128, no_values).extend(reliable_float_vals);
469+
466470
ins!(sym::target_thread_local, no_values);
467471

468472
ins!(sym::ub_checks, no_values);

compiler/rustc_span/src/symbol.rs

+4
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,7 @@ symbols! {
623623
cfg_target_feature,
624624
cfg_target_has_atomic,
625625
cfg_target_has_atomic_equal_alignment,
626+
cfg_target_has_reliable_f16_f128,
626627
cfg_target_thread_local,
627628
cfg_target_vendor,
628629
cfg_trace: "<cfg>", // must not be a valid identifier
@@ -937,8 +938,10 @@ symbols! {
937938
external_doc,
938939
f,
939940
f128,
941+
f128_dash_math: "f128-math",
940942
f128_nan,
941943
f16,
944+
f16_dash_math: "f16-math",
942945
f16_nan,
943946
f16c_target_feature,
944947
f32,
@@ -2073,6 +2076,7 @@ symbols! {
20732076
target_has_atomic,
20742077
target_has_atomic_equal_alignment,
20752078
target_has_atomic_load_store,
2079+
target_has_reliable_f16_f128,
20762080
target_os,
20772081
target_pointer_width,
20782082
target_thread_local,

0 commit comments

Comments
 (0)