Add f16 and f128 configuration from compiler-builtins

In preparation of adding routines from these two types, duplicate the
`compiler-builtins` configuration here.
This commit is contained in:
Trevor Gross
2024-10-26 00:44:50 -05:00
committed by Trevor Gross
parent b9871da445
commit f2e16b6ac1
9 changed files with 208 additions and 83 deletions

View File

@@ -21,7 +21,7 @@ arch = []
# This tells the compiler to assume that a Nightly toolchain is being used and # This tells the compiler to assume that a Nightly toolchain is being used and
# that it should activate any useful Nightly things accordingly. # that it should activate any useful Nightly things accordingly.
unstable = ["unstable-intrinsics"] unstable = ["unstable-intrinsics", "unstable-float"]
# Enable calls to functions in `core::intrinsics` # Enable calls to functions in `core::intrinsics`
unstable-intrinsics = [] unstable-intrinsics = []
@@ -29,6 +29,9 @@ unstable-intrinsics = []
# Make some internal things public for testing. # Make some internal things public for testing.
unstable-test-support = [] unstable-test-support = []
# Enable the nightly-only `f16` and `f128`.
unstable-float = []
# Used to prevent using any intrinsics or arch-specific code. # Used to prevent using any intrinsics or arch-specific code.
# #
# HACK: this is a negative feature which is generally a bad idea in Cargo, but # HACK: this is a negative feature which is generally a bad idea in Cargo, but

View File

@@ -1,6 +1,10 @@
use std::env; use std::env;
mod configure;
fn main() { fn main() {
let cfg = configure::Config::from_env();
println!("cargo:rerun-if-changed=build.rs"); println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rustc-check-cfg=cfg(assert_no_panic)"); println!("cargo:rustc-check-cfg=cfg(assert_no_panic)");
@@ -14,29 +18,5 @@ fn main() {
} }
} }
configure_intrinsics(); configure::emit_libm_config(&cfg);
configure_arch();
}
/// Simplify the feature logic for enabling intrinsics so code only needs to use
/// `cfg(intrinsics_enabled)`.
fn configure_intrinsics() {
println!("cargo:rustc-check-cfg=cfg(intrinsics_enabled)");
// Disabled by default; `unstable-intrinsics` enables again; `force-soft-floats` overrides
// to disable.
if cfg!(feature = "unstable-intrinsics") && !cfg!(feature = "force-soft-floats") {
println!("cargo:rustc-cfg=intrinsics_enabled");
}
}
/// Simplify the feature logic for enabling arch-specific features so code only needs to use
/// `cfg(arch_enabled)`.
fn configure_arch() {
println!("cargo:rustc-check-cfg=cfg(arch_enabled)");
// Enabled by default via the "arch" feature, `force-soft-floats` overrides to disable.
if cfg!(feature = "arch") && !cfg!(feature = "force-soft-floats") {
println!("cargo:rustc-cfg=arch_enabled");
}
} }

View File

@@ -0,0 +1,168 @@
// Configuration shared with both libm and libm-test
use std::env;
use std::path::PathBuf;
#[allow(dead_code)]
pub struct Config {
pub manifest_dir: PathBuf,
pub out_dir: PathBuf,
pub opt_level: u8,
pub target_arch: String,
pub target_env: String,
pub target_family: Option<String>,
pub target_os: String,
pub target_string: String,
pub target_vendor: String,
pub target_features: Vec<String>,
}
impl Config {
pub fn from_env() -> Self {
let target_features = env::var("CARGO_CFG_TARGET_FEATURE")
.map(|feats| feats.split(',').map(ToOwned::to_owned).collect())
.unwrap_or_default();
Self {
manifest_dir: PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()),
out_dir: PathBuf::from(env::var("OUT_DIR").unwrap()),
opt_level: env::var("OPT_LEVEL").unwrap().parse().unwrap(),
target_arch: env::var("CARGO_CFG_TARGET_ARCH").unwrap(),
target_env: env::var("CARGO_CFG_TARGET_ENV").unwrap(),
target_family: env::var("CARGO_CFG_TARGET_FAMILY").ok(),
target_os: env::var("CARGO_CFG_TARGET_OS").unwrap(),
target_string: env::var("TARGET").unwrap(),
target_vendor: env::var("CARGO_CFG_TARGET_VENDOR").unwrap(),
target_features,
}
}
}
/// Libm gets most config options made available.
#[allow(dead_code)]
pub fn emit_libm_config(cfg: &Config) {
emit_intrinsics_cfg();
emit_arch_cfg();
emit_optimization_cfg(cfg);
emit_cfg_shorthands(cfg);
emit_f16_f128_cfg(cfg);
}
/// Tests don't need most feature-related config.
#[allow(dead_code)]
pub fn emit_test_config(cfg: &Config) {
emit_optimization_cfg(cfg);
emit_cfg_shorthands(cfg);
emit_f16_f128_cfg(cfg);
}
/// Simplify the feature logic for enabling intrinsics so code only needs to use
/// `cfg(intrinsics_enabled)`.
fn emit_intrinsics_cfg() {
println!("cargo:rustc-check-cfg=cfg(intrinsics_enabled)");
// Disabled by default; `unstable-intrinsics` enables again; `force-soft-floats` overrides
// to disable.
if cfg!(feature = "unstable-intrinsics") && !cfg!(feature = "force-soft-floats") {
println!("cargo:rustc-cfg=intrinsics_enabled");
}
}
/// Simplify the feature logic for enabling arch-specific features so code only needs to use
/// `cfg(arch_enabled)`.
fn emit_arch_cfg() {
println!("cargo:rustc-check-cfg=cfg(arch_enabled)");
// Enabled by default via the "arch" feature, `force-soft-floats` overrides to disable.
if cfg!(feature = "arch") && !cfg!(feature = "force-soft-floats") {
println!("cargo:rustc-cfg=arch_enabled");
}
}
/// Some tests are extremely slow. Emit a config option based on optimization level.
fn emit_optimization_cfg(cfg: &Config) {
println!("cargo:rustc-check-cfg=cfg(optimizations_enabled)");
if cfg.opt_level >= 2 {
println!("cargo:rustc-cfg=optimizations_enabled");
}
}
/// Provide an alias for common longer config combinations.
fn emit_cfg_shorthands(cfg: &Config) {
println!("cargo:rustc-check-cfg=cfg(x86_no_sse)");
if cfg.target_arch == "x86" && !cfg.target_features.iter().any(|f| f == "sse") {
// Shorthand to detect i586 targets
println!("cargo:rustc-cfg=x86_no_sse");
}
}
/// Configure whether or not `f16` and `f128` support should be enabled.
fn emit_f16_f128_cfg(cfg: &Config) {
println!("cargo:rustc-check-cfg=cfg(f16_enabled)");
println!("cargo:rustc-check-cfg=cfg(f128_enabled)");
// `unstable-float` enables these features.
if !cfg!(feature = "unstable-float") {
return;
}
// Set whether or not `f16` and `f128` are supported at a basic level by LLVM. This only means
// that the backend will not crash when using these types and generates code that can be called
// without crashing (no infinite recursion). This does not mean that the platform doesn't have
// ABI or other bugs.
//
// We do this here rather than in `rust-lang/rust` because configuring via cargo features is
// not straightforward.
//
// Original source of this list:
// <https://github.com/rust-lang/compiler-builtins/pull/652#issuecomment-2266151350>
let f16_enabled = match cfg.target_arch.as_str() {
// Unsupported <https://github.com/llvm/llvm-project/issues/94434>
"arm64ec" => false,
// Selection failure <https://github.com/llvm/llvm-project/issues/50374>
"s390x" => false,
// Infinite recursion <https://github.com/llvm/llvm-project/issues/97981>
// FIXME(llvm): loongarch fixed by <https://github.com/llvm/llvm-project/pull/107791>
"csky" => false,
"hexagon" => false,
"loongarch64" => false,
"mips" | "mips64" | "mips32r6" | "mips64r6" => false,
"powerpc" | "powerpc64" => false,
"sparc" | "sparc64" => false,
"wasm32" | "wasm64" => false,
// Most everything else works as of LLVM 19
_ => true,
};
let f128_enabled = match cfg.target_arch.as_str() {
// Unsupported (libcall is not supported) <https://github.com/llvm/llvm-project/issues/121122>
"amdgpu" => false,
// Unsupported <https://github.com/llvm/llvm-project/issues/94434>
"arm64ec" => false,
// Selection failure <https://github.com/llvm/llvm-project/issues/96432>
"mips64" | "mips64r6" => false,
// Selection failure <https://github.com/llvm/llvm-project/issues/95471>
"nvptx64" => false,
// Selection failure <https://github.com/llvm/llvm-project/issues/101545>
"powerpc64" if &cfg.target_os == "aix" => false,
// Selection failure <https://github.com/llvm/llvm-project/issues/41838>
"sparc" => false,
// Most everything else works as of LLVM 19
_ => true,
};
// If the feature is set, disable these types.
let disable_both = env::var_os("CARGO_FEATURE_NO_F16_F128").is_some();
println!("cargo:rustc-check-cfg=cfg(f16_enabled)");
println!("cargo:rustc-check-cfg=cfg(f128_enabled)");
if f16_enabled && !disable_both {
println!("cargo:rustc-cfg=f16_enabled");
}
if f128_enabled && !disable_both {
println!("cargo:rustc-cfg=f128_enabled");
}
}

View File

@@ -21,5 +21,7 @@ force-soft-floats = []
unexpected_cfgs = { level = "warn", check-cfg = [ unexpected_cfgs = { level = "warn", check-cfg = [
"cfg(arch_enabled)", "cfg(arch_enabled)",
"cfg(assert_no_panic)", "cfg(assert_no_panic)",
"cfg(f128_enabled)",
"cfg(f16_enabled)",
"cfg(intrinsics_enabled)", "cfg(intrinsics_enabled)",
] } ] }

View File

@@ -12,3 +12,10 @@ heck = "0.5.0"
proc-macro2 = "1.0.88" proc-macro2 = "1.0.88"
quote = "1.0.37" quote = "1.0.37"
syn = { version = "2.0.79", features = ["full", "extra-traits", "visit-mut"] } syn = { version = "2.0.79", features = ["full", "extra-traits", "visit-mut"] }
[lints.rust]
# Values used during testing
unexpected_cfgs = { level = "warn", check-cfg = [
'cfg(f16_enabled)',
'cfg(f128_enabled)',
] }

View File

@@ -5,7 +5,10 @@ edition = "2021"
publish = false publish = false
[features] [features]
default = [] default = ["unstable-float"]
# Propagated from libm because this affects which functions we test.
unstable-float = ["libm/unstable-float"]
# Generate tests which are random inputs and the outputs are calculated with # Generate tests which are random inputs and the outputs are calculated with
# musl libc. # musl libc.
@@ -44,3 +47,9 @@ criterion = { version = "0.5.1", default-features = false, features = ["cargo_be
[[bench]] [[bench]]
name = "random" name = "random"
harness = false harness = false
[lints.rust]
# Values from the chared config.rs used by `libm` but not the test crate
unexpected_cfgs = { level = "warn", check-cfg = [
'cfg(feature, values("arch", "force-soft-floats", "unstable-intrinsics"))',
] }

View File

@@ -1,66 +1,16 @@
use std::fmt::Write; use std::fmt::Write;
use std::path::PathBuf; use std::fs;
use std::{env, fs};
#[path = "../../configure.rs"]
mod configure;
use configure::Config;
fn main() { fn main() {
let cfg = Config::from_env(); let cfg = Config::from_env();
emit_optimization_cfg(&cfg);
emit_cfg_shorthands(&cfg);
list_all_tests(&cfg); list_all_tests(&cfg);
}
#[allow(dead_code)] configure::emit_test_config(&cfg);
struct Config {
manifest_dir: PathBuf,
out_dir: PathBuf,
opt_level: u8,
target_arch: String,
target_env: String,
target_family: Option<String>,
target_os: String,
target_string: String,
target_vendor: String,
target_features: Vec<String>,
}
impl Config {
fn from_env() -> Self {
let target_features = env::var("CARGO_CFG_TARGET_FEATURE")
.map(|feats| feats.split(',').map(ToOwned::to_owned).collect())
.unwrap_or_default();
Self {
manifest_dir: PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()),
out_dir: PathBuf::from(env::var("OUT_DIR").unwrap()),
opt_level: env::var("OPT_LEVEL").unwrap().parse().unwrap(),
target_arch: env::var("CARGO_CFG_TARGET_ARCH").unwrap(),
target_env: env::var("CARGO_CFG_TARGET_ENV").unwrap(),
target_family: env::var("CARGO_CFG_TARGET_FAMILY").ok(),
target_os: env::var("CARGO_CFG_TARGET_OS").unwrap(),
target_string: env::var("TARGET").unwrap(),
target_vendor: env::var("CARGO_CFG_TARGET_VENDOR").unwrap(),
target_features,
}
}
}
/// Some tests are extremely slow. Emit a config option based on optimization level.
fn emit_optimization_cfg(cfg: &Config) {
println!("cargo::rustc-check-cfg=cfg(optimizations_enabled)");
if cfg.opt_level >= 2 {
println!("cargo::rustc-cfg=optimizations_enabled");
}
}
/// Provide an alias for common longer config combinations.
fn emit_cfg_shorthands(cfg: &Config) {
println!("cargo::rustc-check-cfg=cfg(x86_no_sse)");
if cfg.target_arch == "x86" && !cfg.target_features.iter().any(|f| f == "sse") {
// Shorthand to detect i586 targets
println!("cargo::rustc-cfg=x86_no_sse");
}
} }
/// Create a list of all source files in an array. This can be used for making sure that /// Create a list of all source files in an array. This can be used for making sure that

View File

@@ -2,6 +2,8 @@
#![no_std] #![no_std]
#![cfg_attr(intrinsics_enabled, allow(internal_features))] #![cfg_attr(intrinsics_enabled, allow(internal_features))]
#![cfg_attr(intrinsics_enabled, feature(core_intrinsics))] #![cfg_attr(intrinsics_enabled, feature(core_intrinsics))]
#![cfg_attr(f128_enabled, feature(f128))]
#![cfg_attr(f16_enabled, feature(f16))]
#![allow(clippy::assign_op_pattern)] #![allow(clippy::assign_op_pattern)]
#![allow(clippy::deprecated_cfg_attr)] #![allow(clippy::deprecated_cfg_attr)]
#![allow(clippy::eq_op)] #![allow(clippy::eq_op)]

View File

@@ -219,5 +219,9 @@ macro_rules! float_impl {
}; };
} }
#[cfg(f16_enabled)]
float_impl!(f16, u16, i16, i8, 16, 10);
float_impl!(f32, u32, i32, i16, 32, 23); float_impl!(f32, u32, i32, i16, 32, 23);
float_impl!(f64, u64, i64, i16, 64, 52); float_impl!(f64, u64, i64, i16, 64, 52);
#[cfg(f128_enabled)]
float_impl!(f128, u128, i128, i16, 128, 112);