Skip to content

Commit

Permalink
Fix CI for targets that conditionally disable f16 or f128 support
Browse files Browse the repository at this point in the history
  • Loading branch information
kleisauke committed Aug 12, 2024
1 parent 6a80b90 commit 42ac64e
Show file tree
Hide file tree
Showing 9 changed files with 127 additions and 115 deletions.
83 changes: 2 additions & 81 deletions build.rs
Original file line number Diff line number Diff line change
@@ -1,44 +1,8 @@
use std::{collections::BTreeMap, env, path::PathBuf, sync::atomic::Ordering};

#[allow(dead_code)]
struct Target {
triple: String,
os: String,
arch: String,
vendor: String,
env: String,
pointer_width: u8,
little_endian: bool,
features: Vec<String>,
}

impl Target {
fn from_env() -> Self {
let little_endian = match env::var("CARGO_CFG_TARGET_ENDIAN").unwrap().as_str() {
"little" => true,
"big" => false,
x => panic!("unknown endian {x}"),
};
mod configure;

Self {
triple: env::var("TARGET").unwrap(),
os: env::var("CARGO_CFG_TARGET_OS").unwrap(),
arch: env::var("CARGO_CFG_TARGET_ARCH").unwrap(),
vendor: env::var("CARGO_CFG_TARGET_VENDOR").unwrap(),
env: env::var("CARGO_CFG_TARGET_ENV").unwrap(),
pointer_width: env::var("CARGO_CFG_TARGET_POINTER_WIDTH")
.unwrap()
.parse()
.unwrap(),
little_endian,
features: env::var("CARGO_CFG_TARGET_FEATURE")
.unwrap_or_default()
.split(",")
.map(ToOwned::to_owned)
.collect(),
}
}
}
use crate::configure::{configure_f16_f128, Target};

fn main() {
println!("cargo:rerun-if-changed=build.rs");
Expand Down Expand Up @@ -261,49 +225,6 @@ fn configure_check_cfg() {
println!("cargo::rustc-check-cfg=cfg(assert_no_panic)");
}

/// Configure whether or not `f16` and `f128` support should be enabled.
fn configure_f16_f128(target: &Target) {
// 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. This does not mean that the
// backend does the right thing, or that the platform doesn't have ABI 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_ok, f128_ok) = match target.arch.as_str() {
// `f16` and `f128` both crash <https://github.com/llvm/llvm-project/issues/94434>
"arm64ec" => (false, false),
// `f16` crashes <https://github.com/llvm/llvm-project/issues/50374>
"s390x" => (false, true),
// `f128` crashes <https://github.com/llvm/llvm-project/issues/96432>
"mips64" | "mips64r6" => (true, false),
// `f128` crashes <https://github.com/llvm/llvm-project/issues/101545>
"powerpc64" if &target.os == "aix" => (true, false),
// `f128` crashes <https://github.com/llvm/llvm-project/issues/41838>
"sparc" | "sparcv9" => (true, false),
// `f16` miscompiles <https://github.com/llvm/llvm-project/issues/96438>
"wasm32" | "wasm64" => (false, true),
// Most everything else works as of LLVM 19
_ => (true, 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_ok && !disable_both {
println!("cargo::rustc-cfg=f16_enabled");
}

if f128_ok && !disable_both {
println!("cargo::rustc-cfg=f128_enabled");
}
}

#[cfg(feature = "c")]
mod c {
use std::collections::{BTreeMap, HashSet};
Expand Down
84 changes: 84 additions & 0 deletions configure.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
use std::env;

#[allow(dead_code)]
pub(crate) struct Target {
pub(crate) triple: String,
pub(crate) os: String,
pub(crate) arch: String,
pub(crate) vendor: String,
pub(crate) env: String,
pub(crate) pointer_width: u8,
pub(crate) little_endian: bool,
pub(crate) features: Vec<String>,
}

impl Target {
pub(crate) fn from_env() -> Self {
let little_endian = match env::var("CARGO_CFG_TARGET_ENDIAN").unwrap().as_str() {
"little" => true,
"big" => false,
x => panic!("unknown endian {x}"),
};

Self {
triple: env::var("TARGET").unwrap(),
os: env::var("CARGO_CFG_TARGET_OS").unwrap(),
arch: env::var("CARGO_CFG_TARGET_ARCH").unwrap(),
vendor: env::var("CARGO_CFG_TARGET_VENDOR").unwrap(),
env: env::var("CARGO_CFG_TARGET_ENV").unwrap(),
pointer_width: env::var("CARGO_CFG_TARGET_POINTER_WIDTH")
.unwrap()
.parse()
.unwrap(),
little_endian,
features: env::var("CARGO_CFG_TARGET_FEATURE")
.unwrap_or_default()
.split(",")
.map(ToOwned::to_owned)
.collect(),
}
}
}

/// Configure whether or not `f16` and `f128` support should be enabled.
pub(crate) fn configure_f16_f128(target: &Target) {
// 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. This does not mean that the
// backend does the right thing, or that the platform doesn't have ABI 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_ok, f128_ok) = match target.arch.as_str() {
// `f16` and `f128` both crash <https://github.com/llvm/llvm-project/issues/94434>
"arm64ec" => (false, false),
// `f16` crashes <https://github.com/llvm/llvm-project/issues/50374>
"s390x" => (false, true),
// `f128` crashes <https://github.com/llvm/llvm-project/issues/96432>
"mips64" | "mips64r6" => (true, false),
// `f128` crashes <https://github.com/llvm/llvm-project/issues/101545>
"powerpc64" if &target.os == "aix" => (true, false),
// `f128` crashes <https://github.com/llvm/llvm-project/issues/41838>
"sparc" | "sparcv9" => (true, false),
// `f16` miscompiles <https://github.com/llvm/llvm-project/issues/96438>
"wasm32" | "wasm64" => (false, true),
// Most everything else works as of LLVM 19
_ => (true, 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_ok && !disable_both {
println!("cargo::rustc-cfg=f16_enabled");
}

if f128_ok && !disable_both {
println!("cargo::rustc-cfg=f128_enabled");
}
}
45 changes: 26 additions & 19 deletions testcrate/build.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{collections::HashSet, env};
use std::collections::HashSet;

/// Features to enable
#[derive(Debug, PartialEq, Eq, Hash)]
Expand All @@ -9,35 +9,39 @@ enum Feature {
NoSysF16F128Convert,
}

mod builtins_configure {
include!("../configure.rs");
}

fn main() {
let target = env::var("TARGET").unwrap();
let target = builtins_configure::Target::from_env();
let mut features = HashSet::new();

// These platforms do not have f128 symbols available in their system libraries, so
// skip related tests.
if target.starts_with("arm-")
|| target.contains("apple-darwin")
|| target.contains("windows-msvc")
if target.arch == "arm"
|| target.vendor == "apple"
|| target.env == "msvc"
// GCC and LLVM disagree on the ABI of `f16` and `f128` with MinGW. See
// <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054>.
|| target.contains("windows-gnu")
|| (target.os == "windows" && target.env == "gnu")
// FIXME(llvm): There is an ABI incompatibility between GCC and Clang on 32-bit x86.
// See <https://github.com/llvm/llvm-project/issues/77401>.
|| target.starts_with("i686")
|| target.arch == "i686"
// 32-bit PowerPC and 64-bit LE gets code generated that Qemu cannot handle. See
// <https://github.com/rust-lang/compiler-builtins/pull/606#issuecomment-2105635926>.
|| target.starts_with("powerpc-")
|| target.starts_with("powerpc64le-")
|| target.arch == "powerpc"
|| target.arch == "powerpc64le"
// FIXME: We get different results from the builtin functions. See
// <https://github.com/rust-lang/compiler-builtins/pull/606#issuecomment-2105657287>.
|| target.starts_with("powerpc64-")
|| target.arch == "powerpc64"
{
features.insert(Feature::NoSysF128);
features.insert(Feature::NoSysF128IntConvert);
features.insert(Feature::NoSysF16F128Convert);
}

if target.starts_with("i586") || target.starts_with("i686") {
if target.arch == "i586" || target.arch == "i686" {
// 32-bit x86 does not have `__fixunstfti`/`__fixtfti` but does have everything else
features.insert(Feature::NoSysF128IntConvert);
// FIXME: 32-bit x86 has a bug in `f128 -> f16` system libraries
Expand All @@ -46,17 +50,18 @@ fn main() {

// These platforms do not have f16 symbols available in their system libraries, so
// skip related tests. Most of these are missing `f16 <-> f32` conversion routines.
if (target.starts_with("aarch64-") && target.contains("linux"))
|| target.starts_with("arm")
|| target.starts_with("powerpc-")
|| target.starts_with("powerpc64-")
|| target.starts_with("powerpc64le-")
|| target.starts_with("i586-")
|| target.contains("windows-")
if (target.arch == "aarch64" && target.os == "linux")
|| target.arch == "arm"
|| target.arch == "powerpc"
|| target.arch == "powerpc64le"
|| target.arch == "powerpc64le"
|| target.arch == "i586"
|| target.os == "windows"
// Linking says "error: function signature mismatch: __extendhfsf2" and seems to
// think the signature is either `(i32) -> f32` or `(f32) -> f32`. See
// <https://github.com/llvm/llvm-project/issues/96438>.
|| target.starts_with("wasm")
|| target.arch == "wasm32"
|| target.arch == "wasm64"
{
features.insert(Feature::NoSysF16);
features.insert(Feature::NoSysF16F128Convert);
Expand All @@ -78,4 +83,6 @@ fn main() {
println!("cargo:warning={warning}");
println!("cargo:rustc-cfg=feature=\"{name}\"");
}

builtins_configure::configure_f16_f128(&target);
}
2 changes: 1 addition & 1 deletion testcrate/src/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ macro_rules! impl_testio {
}
}

#[cfg(not(feature = "no-f16-f128"))]
#[cfg(all(f16_enabled, f128_enabled))]
impl_testio!(float f16, f128);
impl_testio!(float f32, f64);
impl_testio!(int i16, i32, i64, i128);
Expand Down
4 changes: 2 additions & 2 deletions testcrate/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
//! Some floating point tests are disabled for specific architectures, because they do not have
//! correct rounding.
#![no_std]
#![cfg_attr(not(feature = "no-f16-f128"), feature(f128))]
#![cfg_attr(not(feature = "no-f16-f128"), feature(f16))]
#![cfg_attr(f128_enabled, feature(f128))]
#![cfg_attr(f16_enabled, feature(f16))]
#![feature(isqrt)]

pub mod bench;
Expand Down
4 changes: 2 additions & 2 deletions testcrate/tests/addsub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ mod float_addsub {
}
}

#[cfg(not(feature = "no-f16-f128"))]
#[cfg(f128_enabled)]
#[cfg(not(all(target_arch = "x86", not(target_feature = "sse"))))]
#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
mod float_addsub_f128 {
Expand All @@ -131,7 +131,7 @@ mod float_addsub_f128 {
}
}

#[cfg(not(feature = "no-f16-f128"))]
#[cfg(f128_enabled)]
#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
mod float_addsub_f128_ppc {
use super::*;
Expand Down
2 changes: 1 addition & 1 deletion testcrate/tests/cmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ mod float_comparisons {
}

#[test]
#[cfg(not(feature = "no-f16-f128"))]
#[cfg(f128_enabled)]
fn cmp_f128() {
#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
use compiler_builtins::float::cmp::{
Expand Down
14 changes: 7 additions & 7 deletions testcrate/tests/conv.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#![cfg_attr(not(feature = "no-f16-f128"), feature(f16))]
#![cfg_attr(not(feature = "no-f16-f128"), feature(f128))]
#![cfg_attr(f128_enabled, feature(f128))]
#![cfg_attr(f16_enabled, feature(f16))]
// makes configuration easier
#![allow(unused_macros)]
#![allow(unused_imports)]
Expand Down Expand Up @@ -176,7 +176,7 @@ mod f_to_i {
}

#[test]
#[cfg(not(feature = "no-f16-f128"))]
#[cfg(f128_enabled)]
fn f128_to_int() {
#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
use compiler_builtins::float::conv::{
Expand Down Expand Up @@ -264,7 +264,7 @@ mod extend {
f32 => f64, Single => Double, __extendsfdf2vfp, all();
}

#[cfg(not(feature = "no-f16-f128"))]
#[cfg(all(f16_enabled, f128_enabled))]
#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
f_to_f! {
extend,
Expand All @@ -275,7 +275,7 @@ mod extend {
f64 => f128, Double => Quad, __extenddftf2, not(feature = "no-sys-f128");
}

#[cfg(not(feature = "no-f16-f128"))]
#[cfg(f128_enabled)]
#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
f_to_f! {
extend,
Expand All @@ -299,7 +299,7 @@ mod trunc {
f64 => f32, Double => Single, __truncdfsf2vfp, all();
}

#[cfg(not(feature = "no-f16-f128"))]
#[cfg(all(f16_enabled, f128_enabled))]
#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
f_to_f! {
trunc,
Expand All @@ -310,7 +310,7 @@ mod trunc {
f128 => f64, Quad => Double, __trunctfdf2, not(feature = "no-sys-f128");
}

#[cfg(not(feature = "no-f16-f128"))]
#[cfg(f128_enabled)]
#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
f_to_f! {
trunc,
Expand Down
4 changes: 2 additions & 2 deletions testcrate/tests/mul.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ mod float_mul {
}
}

#[cfg(not(feature = "no-f16-f128"))]
#[cfg(f128_enabled)]
#[cfg(not(all(target_arch = "x86", not(target_feature = "sse"))))]
#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
mod float_mul_f128 {
Expand All @@ -145,7 +145,7 @@ mod float_mul_f128 {
}
}

#[cfg(not(feature = "no-f16-f128"))]
#[cfg(f128_enabled)]
#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
mod float_mul_f128_ppc {
use super::*;
Expand Down

0 comments on commit 42ac64e

Please sign in to comment.