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 `cfg_target_has_reliable_f16_f128` internal feature, which
provides the following new configuration gates:

* `cfg(target_has_reliable_f16)`
* `cfg(target_has_reliable_f16_math)`
* `cfg(target_has_reliable_f128)`
* `cfg(target_has_reliable_f128_math)`

`reliable_f16` and `reliable_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 planned to ever become stable, it is
only intended to replace the build scripts for `std` tests and
`compiler-builtins` that don't have any way to configure based on the
codegen backend.

MCP: https://github.com/rust-lang/compiler-team/issues/866
Closes: https://github.com/rust-lang/compiler-team/issues/866

[1]: 555e1d0386/library/std/build.rs (L84-L186)
This commit is contained in:
Trevor Gross 2025-04-24 22:11:23 +00:00
parent 555e1d0386
commit 6ceeb0849e
20 changed files with 311 additions and 27 deletions

View File

@ -41,8 +41,8 @@ use std::sync::Arc;
use cranelift_codegen::isa::TargetIsa;
use cranelift_codegen::settings::{self, Configurable};
use rustc_codegen_ssa::CodegenResults;
use rustc_codegen_ssa::traits::CodegenBackend;
use rustc_codegen_ssa::{CodegenResults, TargetConfig};
use rustc_metadata::EncodedMetadata;
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
use rustc_session::Session;
@ -178,7 +178,7 @@ impl CodegenBackend for CraneliftCodegenBackend {
}
}
fn target_features_cfg(&self, sess: &Session) -> (Vec<Symbol>, Vec<Symbol>) {
fn target_config(&self, sess: &Session) -> TargetConfig {
// FIXME return the actually used target features. this is necessary for #[cfg(target_feature)]
let target_features = if sess.target.arch == "x86_64" && sess.target.os != "none" {
// x86_64 mandates SSE2 support and rustc requires the x87 feature to be enabled
@ -197,7 +197,16 @@ impl CodegenBackend for CraneliftCodegenBackend {
};
// FIXME do `unstable_target_features` properly
let unstable_target_features = target_features.clone();
(target_features, unstable_target_features)
TargetConfig {
target_features,
unstable_target_features,
// Cranelift does not yet support f16 or f128
has_reliable_f16: false,
has_reliable_f16_math: false,
has_reliable_f128: false,
has_reliable_f128_math: false,
}
}
fn print_version(&self) {

View File

@ -55,7 +55,7 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri
)
} else if let Some(feature) = feature.strip_prefix('-') {
// FIXME: Why do we not remove implied features on "-" here?
// We do the equivalent above in `target_features_cfg`.
// We do the equivalent above in `target_config`.
// See <https://github.com/rust-lang/rust/issues/134792>.
all_rust_features.push((false, feature));
} else if !feature.is_empty() && diagnostics {

View File

@ -102,7 +102,7 @@ use rustc_codegen_ssa::back::write::{
};
use rustc_codegen_ssa::base::codegen_crate;
use rustc_codegen_ssa::traits::{CodegenBackend, ExtraBackendMethods, WriteBackendMethods};
use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen};
use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen, TargetConfig};
use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::sync::IntoDynSyncSend;
use rustc_errors::DiagCtxtHandle;
@ -260,8 +260,8 @@ impl CodegenBackend for GccCodegenBackend {
.join(sess)
}
fn target_features_cfg(&self, sess: &Session) -> (Vec<Symbol>, Vec<Symbol>) {
target_features_cfg(sess, &self.target_info)
fn target_config(&self, sess: &Session) -> TargetConfig {
target_config(sess, &self.target_info)
}
}
@ -485,10 +485,7 @@ fn to_gcc_opt_level(optlevel: Option<OptLevel>) -> OptimizationLevel {
}
/// Returns the features that should be set in `cfg(target_feature)`.
fn target_features_cfg(
sess: &Session,
target_info: &LockedTargetInfo,
) -> (Vec<Symbol>, Vec<Symbol>) {
fn target_config(sess: &Session, target_info: &LockedTargetInfo) -> TargetConfig {
// TODO(antoyo): use global_gcc_features.
let f = |allow_unstable| {
sess.target
@ -523,5 +520,14 @@ fn target_features_cfg(
let target_features = f(false);
let unstable_target_features = f(true);
(target_features, unstable_target_features)
TargetConfig {
target_features,
unstable_target_features,
// There are no known bugs with GCC support for f16 or f128
has_reliable_f16: true,
has_reliable_f16_math: true,
has_reliable_f128: true,
has_reliable_f128_math: true,
}
}

View File

@ -29,7 +29,7 @@ use back::owned_target_machine::OwnedTargetMachine;
use back::write::{create_informational_target_machine, create_target_machine};
use context::SimpleCx;
use errors::{AutoDiffWithoutLTO, ParseTargetMachineConfig};
use llvm_util::target_features_cfg;
use llvm_util::target_config;
use rustc_ast::expand::allocator::AllocatorKind;
use rustc_ast::expand::autodiff_attrs::AutoDiffItem;
use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule};
@ -37,7 +37,7 @@ use rustc_codegen_ssa::back::write::{
CodegenContext, FatLtoInput, ModuleConfig, TargetMachineFactoryConfig, TargetMachineFactoryFn,
};
use rustc_codegen_ssa::traits::*;
use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen};
use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen, TargetConfig};
use rustc_data_structures::fx::FxIndexMap;
use rustc_errors::{DiagCtxtHandle, FatalError};
use rustc_metadata::EncodedMetadata;
@ -338,8 +338,8 @@ impl CodegenBackend for LlvmCodegenBackend {
llvm_util::print_version();
}
fn target_features_cfg(&self, sess: &Session) -> (Vec<Symbol>, Vec<Symbol>) {
target_features_cfg(sess)
fn target_config(&self, sess: &Session) -> TargetConfig {
target_config(sess)
}
fn codegen_crate<'tcx>(

View File

@ -6,6 +6,7 @@ use std::sync::Once;
use std::{ptr, slice, str};
use libc::c_int;
use rustc_codegen_ssa::TargetConfig;
use rustc_codegen_ssa::base::wants_wasm_eh;
use rustc_codegen_ssa::codegen_attrs::check_tied_features;
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
/// Must express features in the way Rust understands them.
///
/// We do not have to worry about RUSTC_SPECIFIC_FEATURES here, those are handled outside codegen.
pub(crate) fn target_features_cfg(sess: &Session) -> (Vec<Symbol>, Vec<Symbol>) {
pub(crate) fn target_config(sess: &Session) -> TargetConfig {
// Add base features for the target.
// We do *not* add the -Ctarget-features there, and instead duplicate the logic for that below.
// The reason is that if LLVM considers a feature implied but we do not, we don't want that to
@ -402,7 +403,89 @@ pub(crate) fn target_features_cfg(sess: &Session) -> (Vec<Symbol>, Vec<Symbol>)
let target_features = f(false);
let unstable_target_features = f(true);
(target_features, unstable_target_features)
let mut cfg = TargetConfig {
target_features,
unstable_target_features,
has_reliable_f16: true,
has_reliable_f16_math: true,
has_reliable_f128: true,
has_reliable_f128_math: true,
};
update_target_reliable_float_cfg(sess, &mut cfg);
cfg
}
/// Determine whether or not experimental float types are reliable based on known bugs.
fn update_target_reliable_float_cfg(sess: &Session, cfg: &mut TargetConfig) {
let target_arch = sess.target.arch.as_ref();
let target_os = sess.target.options.os.as_ref();
let target_env = sess.target.options.env.as_ref();
let target_abi = sess.target.options.abi.as_ref();
let target_pointer_width = sess.target.pointer_width;
cfg.has_reliable_f16 = match (target_arch, target_os) {
// Selection failure <https://github.com/llvm/llvm-project/issues/50374>
("s390x", _) => false,
// Unsupported <https://github.com/llvm/llvm-project/issues/94434>
("arm64ec", _) => false,
// MinGW ABI bugs <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054>
("x86_64", "windows") if target_env == "gnu" && target_abi != "llvm" => false,
// Infinite recursion <https://github.com/llvm/llvm-project/issues/97981>
("csky", _) => false,
("hexagon", _) => false,
("powerpc" | "powerpc64", _) => false,
("sparc" | "sparc64", _) => false,
("wasm32" | "wasm64", _) => false,
// `f16` support only requires that symbols converting to and from `f32` are available. We
// provide these in `compiler-builtins`, so `f16` should be available on all platforms that
// do not have other ABI issues or LLVM crashes.
_ => true,
};
cfg.has_reliable_f128 = match (target_arch, target_os) {
// Unsupported <https://github.com/llvm/llvm-project/issues/94434>
("arm64ec", _) => false,
// Selection bug <https://github.com/llvm/llvm-project/issues/96432>
("mips64" | "mips64r6", _) => false,
// Selection bug <https://github.com/llvm/llvm-project/issues/95471>
("nvptx64", _) => false,
// ABI bugs <https://github.com/rust-lang/rust/issues/125109> et al. (full
// list at <https://github.com/rust-lang/rust/issues/116909>)
("powerpc" | "powerpc64", _) => false,
// ABI unsupported <https://github.com/llvm/llvm-project/issues/41838>
("sparc", _) => false,
// Stack alignment bug <https://github.com/llvm/llvm-project/issues/77401>. NB: tests may
// not fail if our compiler-builtins is linked.
("x86", _) => false,
// MinGW ABI bugs <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054>
("x86_64", "windows") if target_env == "gnu" && target_abi != "llvm" => false,
// There are no known problems on other platforms, so the only requirement is that symbols
// are available. `compiler-builtins` provides all symbols required for core `f128`
// support, so this should work for everything else.
_ => true,
};
cfg.has_reliable_f16_math = match (target_arch, target_os) {
// x86 has a crash for `powi`: <https://github.com/llvm/llvm-project/issues/105747>
("x86" | "x86_64", _) => false,
// Assume that working `f16` means working `f16` math for most platforms, since
// operations just go through `f32`.
_ => true,
} && cfg.has_reliable_f16;
cfg.has_reliable_f128_math = match (target_arch, target_os) {
// LLVM lowers `fp128` math to `long double` symbols even on platforms where
// `long double` is not IEEE binary128. See
// <https://github.com/llvm/llvm-project/issues/44744>.
//
// This rules out anything that doesn't have `long double` = `binary128`; <= 32 bits
// (ld is `f64`), anything other than Linux (Windows and MacOS use `f64`), and `x86`
// (ld is 80-bit extended precision).
("x86_64", _) => false,
(_, "linux") if target_pointer_width == 64 => true,
_ => false,
} && cfg.has_reliable_f128;
}
pub(crate) fn print_version() {
@ -686,7 +769,7 @@ pub(crate) fn global_llvm_features(
)
} else if let Some(feature) = feature.strip_prefix('-') {
// FIXME: Why do we not remove implied features on "-" here?
// We do the equivalent above in `target_features_cfg`.
// We do the equivalent above in `target_config`.
// See <https://github.com/rust-lang/rust/issues/134792>.
all_rust_features.push((false, feature));
} else if !feature.is_empty() {

View File

@ -235,6 +235,24 @@ pub struct CrateInfo {
pub lint_levels: CodegenLintLevels,
}
/// Target-specific options that get set in `cfg(...)`.
///
/// RUSTC_SPECIFIC_FEATURES should be skipped here, those are handled outside codegen.
pub struct TargetConfig {
/// Options to be set in `cfg(target_features)`.
pub target_features: Vec<Symbol>,
/// Options to be set in `cfg(target_features)`, but including unstable features.
pub unstable_target_features: Vec<Symbol>,
/// Option for `cfg(target_has_reliable_f16)`, true if `f16` basic arithmetic works.
pub has_reliable_f16: bool,
/// Option for `cfg(target_has_reliable_f16_math)`, true if `f16` math calls work.
pub has_reliable_f16_math: bool,
/// Option for `cfg(target_has_reliable_f128)`, true if `f128` basic arithmetic works.
pub has_reliable_f128: bool,
/// Option for `cfg(target_has_reliable_f128_math)`, true if `f128` math calls work.
pub has_reliable_f128_math: bool,
}
#[derive(Encodable, Decodable)]
pub struct CodegenResults {
pub modules: Vec<CompiledModule>,

View File

@ -18,7 +18,7 @@ use super::write::WriteBackendMethods;
use crate::back::archive::ArArchiveBuilderBuilder;
use crate::back::link::link_binary;
use crate::back::write::TargetMachineFactoryFn;
use crate::{CodegenResults, ModuleCodegen};
use crate::{CodegenResults, ModuleCodegen, TargetConfig};
pub trait BackendTypes {
type Value: CodegenObject;
@ -50,8 +50,15 @@ pub trait CodegenBackend {
/// - The second is like the first, but also includes unstable features.
///
/// RUSTC_SPECIFIC_FEATURES should be skipped here, those are handled outside codegen.
fn target_features_cfg(&self, _sess: &Session) -> (Vec<Symbol>, Vec<Symbol>) {
(vec![], vec![])
fn target_config(&self, _sess: &Session) -> TargetConfig {
TargetConfig {
target_features: vec![],
unstable_target_features: vec![],
has_reliable_f16: true,
has_reliable_f16_math: true,
has_reliable_f128: true,
has_reliable_f128_math: true,
}
}
fn print_passes(&self) {}

View File

@ -40,6 +40,26 @@ const GATED_CFGS: &[GatedCfg] = &[
// this is consistent with naming of the compiler flag it's for
(sym::fmt_debug, sym::fmt_debug, Features::fmt_debug),
(sym::emscripten_wasm_eh, sym::cfg_emscripten_wasm_eh, Features::cfg_emscripten_wasm_eh),
(
sym::target_has_reliable_f16,
sym::cfg_target_has_reliable_f16_f128,
Features::cfg_target_has_reliable_f16_f128,
),
(
sym::target_has_reliable_f16_math,
sym::cfg_target_has_reliable_f16_f128,
Features::cfg_target_has_reliable_f16_f128,
),
(
sym::target_has_reliable_f128,
sym::cfg_target_has_reliable_f16_f128,
Features::cfg_target_has_reliable_f16_f128,
),
(
sym::target_has_reliable_f128_math,
sym::cfg_target_has_reliable_f16_f128,
Features::cfg_target_has_reliable_f16_f128,
),
];
/// Find a gated cfg determined by the `pred`icate which is given the cfg's name.

View File

@ -205,6 +205,8 @@ declare_features! (
(unstable, anonymous_lifetime_in_impl_trait, "1.63.0", None),
/// Allows access to the emscripten_wasm_eh config, used by panic_unwind and unwind
(internal, cfg_emscripten_wasm_eh, "1.86.0", None),
/// Allows checking whether or not the backend correctly supports unstable float types.
(internal, cfg_target_has_reliable_f16_f128, "CURRENT_RUSTC_VERSION", None),
/// Allows identifying the `compiler_builtins` crate.
(internal, compiler_builtins, "1.13.0", None),
/// Allows writing custom MIR

View File

@ -38,14 +38,25 @@ pub(crate) fn add_configuration(
codegen_backend: &dyn CodegenBackend,
) {
let tf = sym::target_feature;
let tf_cfg = codegen_backend.target_config(sess);
let (target_features, unstable_target_features) = codegen_backend.target_features_cfg(sess);
sess.unstable_target_features.extend(tf_cfg.unstable_target_features.iter().copied());
sess.target_features.extend(tf_cfg.target_features.iter().copied());
sess.unstable_target_features.extend(unstable_target_features.iter().copied());
cfg.extend(tf_cfg.target_features.into_iter().map(|feat| (tf, Some(feat))));
sess.target_features.extend(target_features.iter().copied());
cfg.extend(target_features.into_iter().map(|feat| (tf, Some(feat))));
if tf_cfg.has_reliable_f16 {
cfg.insert((sym::target_has_reliable_f16, None));
}
if tf_cfg.has_reliable_f16_math {
cfg.insert((sym::target_has_reliable_f16_math, None));
}
if tf_cfg.has_reliable_f128 {
cfg.insert((sym::target_has_reliable_f128, None));
}
if tf_cfg.has_reliable_f128_math {
cfg.insert((sym::target_has_reliable_f128_math, None));
}
if sess.crt_static(None) {
cfg.insert((tf, Some(sym::crt_dash_static)));

View File

@ -142,6 +142,10 @@ pub(crate) fn disallow_cfgs(sess: &Session, user_cfgs: &Cfg) {
| (sym::target_has_atomic, Some(_))
| (sym::target_has_atomic_equal_alignment, Some(_))
| (sym::target_has_atomic_load_store, Some(_))
| (sym::target_has_reliable_f16, None | Some(_))
| (sym::target_has_reliable_f16_math, None | Some(_))
| (sym::target_has_reliable_f128, None | Some(_))
| (sym::target_has_reliable_f128_math, None | Some(_))
| (sym::target_thread_local, None) => disallow(cfg, "--target"),
(sym::fmt_debug, None | Some(_)) => disallow(cfg, "-Z fmt-debug"),
(sym::emscripten_wasm_eh, None | Some(_)) => disallow(cfg, "-Z emscripten_wasm_eh"),

View File

@ -623,6 +623,7 @@ symbols! {
cfg_target_feature,
cfg_target_has_atomic,
cfg_target_has_atomic_equal_alignment,
cfg_target_has_reliable_f16_f128,
cfg_target_thread_local,
cfg_target_vendor,
cfg_trace: "<cfg>", // must not be a valid identifier
@ -2073,6 +2074,10 @@ symbols! {
target_has_atomic,
target_has_atomic_equal_alignment,
target_has_atomic_load_store,
target_has_reliable_f128,
target_has_reliable_f128_math,
target_has_reliable_f16,
target_has_reliable_f16_math,
target_os,
target_pointer_width,
target_thread_local,

View File

@ -0,0 +1,8 @@
error: unexpected `--cfg target_has_reliable_f128` flag
|
= note: config `target_has_reliable_f128` is only supposed to be controlled by `--target`
= note: manually setting a built-in cfg can and does create incoherent behaviors
= note: `#[deny(explicit_builtin_cfgs_in_flags)]` on by default
error: aborting due to 1 previous error

View File

@ -0,0 +1,8 @@
error: unexpected `--cfg target_has_reliable_f128_math` flag
|
= note: config `target_has_reliable_f128_math` is only supposed to be controlled by `--target`
= note: manually setting a built-in cfg can and does create incoherent behaviors
= note: `#[deny(explicit_builtin_cfgs_in_flags)]` on by default
error: aborting due to 1 previous error

View File

@ -0,0 +1,8 @@
error: unexpected `--cfg target_has_reliable_f16` flag
|
= note: config `target_has_reliable_f16` is only supposed to be controlled by `--target`
= note: manually setting a built-in cfg can and does create incoherent behaviors
= note: `#[deny(explicit_builtin_cfgs_in_flags)]` on by default
error: aborting due to 1 previous error

View File

@ -0,0 +1,8 @@
error: unexpected `--cfg target_has_reliable_f16_math` flag
|
= note: config `target_has_reliable_f16_math` is only supposed to be controlled by `--target`
= note: manually setting a built-in cfg can and does create incoherent behaviors
= note: `#[deny(explicit_builtin_cfgs_in_flags)]` on by default
error: aborting due to 1 previous error

View File

@ -8,6 +8,7 @@
//@ revisions: target_thread_local_ relocation_model_
//@ revisions: fmt_debug_
//@ revisions: emscripten_wasm_eh_
//@ revisions: reliable_f16_ reliable_f16_math_ reliable_f128_ reliable_f128_math_
//@ [overflow_checks_]compile-flags: --cfg overflow_checks
//@ [debug_assertions_]compile-flags: --cfg debug_assertions
@ -35,6 +36,10 @@
//@ [relocation_model_]compile-flags: --cfg relocation_model="a"
//@ [fmt_debug_]compile-flags: --cfg fmt_debug="shallow"
//@ [emscripten_wasm_eh_]compile-flags: --cfg emscripten_wasm_eh
//@ [reliable_f16_]compile-flags: --cfg target_has_reliable_f16
//@ [reliable_f16_math_]compile-flags: --cfg target_has_reliable_f16_math
//@ [reliable_f128_]compile-flags: --cfg target_has_reliable_f128
//@ [reliable_f128_math_]compile-flags: --cfg target_has_reliable_f128_math
fn main() {}

View File

@ -0,0 +1,12 @@
//@ compile-flags: --check-cfg=cfg(target_has_reliable_f16,target_has_reliable_f16_math,target_has_reliable_f128,target_has_reliable_f128_math)
fn main() {
cfg!(target_has_reliable_f16);
//~^ ERROR `cfg(target_has_reliable_f16)` is experimental and subject to change
cfg!(target_has_reliable_f16_math);
//~^ ERROR `cfg(target_has_reliable_f16_math)` is experimental and subject to change
cfg!(target_has_reliable_f128);
//~^ ERROR `cfg(target_has_reliable_f128)` is experimental and subject to change
cfg!(target_has_reliable_f128_math);
//~^ ERROR `cfg(target_has_reliable_f128_math)` is experimental and subject to change
}

View File

@ -0,0 +1,39 @@
error[E0658]: `cfg(target_has_reliable_f16)` is experimental and subject to change
--> $DIR/feature-gate-cfg-target-has-reliable-f16-f128.rs:4:10
|
LL | cfg!(target_has_reliable_f16);
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= help: add `#![feature(cfg_target_has_reliable_f16_f128)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: `cfg(target_has_reliable_f16_math)` is experimental and subject to change
--> $DIR/feature-gate-cfg-target-has-reliable-f16-f128.rs:6:10
|
LL | cfg!(target_has_reliable_f16_math);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: add `#![feature(cfg_target_has_reliable_f16_f128)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: `cfg(target_has_reliable_f128)` is experimental and subject to change
--> $DIR/feature-gate-cfg-target-has-reliable-f16-f128.rs:8:10
|
LL | cfg!(target_has_reliable_f128);
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: add `#![feature(cfg_target_has_reliable_f16_f128)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: `cfg(target_has_reliable_f128_math)` is experimental and subject to change
--> $DIR/feature-gate-cfg-target-has-reliable-f16-f128.rs:10:10
|
LL | cfg!(target_has_reliable_f128_math);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: add `#![feature(cfg_target_has_reliable_f16_f128)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0658`.

View File

@ -0,0 +1,31 @@
//@ run-pass
//@ compile-flags: --check-cfg=cfg(target_has_reliable_f16,target_has_reliable_f16_math,target_has_reliable_f128,target_has_reliable_f128_math)
// Verify that the feature gates and config work and are registered as known config
// options.
#![deny(unexpected_cfgs)]
#![feature(cfg_target_has_reliable_f16_f128)]
#[cfg(target_has_reliable_f16)]
pub fn has_f16() {}
#[cfg(target_has_reliable_f16_math)]
pub fn has_f16_math() {}
#[cfg(target_has_reliable_f128 )]
pub fn has_f128() {}
#[cfg(target_has_reliable_f128_math)]
pub fn has_f128_math() {}
fn main() {
if cfg!(target_arch = "aarch64") && cfg!(target_os = "linux") {
// Aarch64+Linux is one target that has support for all features, so use it to spot
// check that the compiler does indeed enable these gates.
assert!(cfg!(target_has_reliable_f16));
assert!(cfg!(target_has_reliable_f16_math));
assert!(cfg!(target_has_reliable_f128));
assert!(cfg!(target_has_reliable_f128_math));
}
}