diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index b5e30c4d5c9..142ac0ff3d3 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -5,7 +5,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_span::{Symbol, sym}; -use crate::spec::Target; +use crate::spec::{FloatAbi, Target}; /// Features that control behaviour of rustc, rather than the codegen. /// These exist globally and are not in the target-specific lists below. @@ -148,7 +148,6 @@ const ARM_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("neon", Unstable(sym::arm_target_feature), &["vfp3"]), ("rclass", Unstable(sym::arm_target_feature), &[]), ("sha2", Unstable(sym::arm_target_feature), &["neon"]), - ("soft-float", Stability::Forbidden { reason: "unsound because it changes float ABI" }, &[]), // This is needed for inline assembly, but shouldn't be stabilized as-is // since it should be enabled per-function using #[instruction_set], not // #[target_feature]. @@ -204,6 +203,7 @@ const AARCH64_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("flagm", Stable, &[]), // FEAT_FLAGM2 ("flagm2", Unstable(sym::aarch64_unstable_target_feature), &[]), + // We forbid directly toggling just `fp-armv8`; it must be toggled with `neon`. ("fp-armv8", Stability::Forbidden { reason: "Rust ties `fp-armv8` to `neon`" }, &[]), // FEAT_FP16 // Rust ties FP and Neon: https://github.com/rust-lang/rust/pull/91608 @@ -758,6 +758,7 @@ impl Target { match &*self.arch { "x86" => { // We support 2 ABIs, hardfloat (default) and softfloat. + // x86 has no sane ABI indicator so we have to use the target feature. if self.has_feature("soft-float") { NOTHING } else { @@ -767,6 +768,7 @@ impl Target { } "x86_64" => { // We support 2 ABIs, hardfloat (default) and softfloat. + // x86 has no sane ABI indicator so we have to use the target feature. if self.has_feature("soft-float") { NOTHING } else { @@ -775,20 +777,27 @@ impl Target { } } "arm" => { - // We support 2 ABIs, hardfloat (default) and softfloat. - if self.has_feature("soft-float") { - NOTHING - } else { - // Hardfloat ABI. x87 must be enabled. - (&["fpregs"], &[]) + // On ARM, ABI handling is reasonably sane; we use `llvm_floatabi` to indicate + // to LLVM which ABI we are going for. + match self.llvm_floatabi.unwrap() { + FloatAbi::Soft => { + // Nothing special required, will use soft-float ABI throughout. + NOTHING + } + FloatAbi::Hard => { + // Must have `fpregs` and must not have `soft-float`. + (&["fpregs"], &["soft-float"]) + } } } "aarch64" | "arm64ec" => { + // Aarch64 has no sane ABI specifier, and LLVM doesn't even have a way to force + // the use of soft-float, so all we can do here is some crude hacks. match &*self.abi { "softfloat" => { // This is not fully correct, LLVM actually doesn't let us enforce the softfloat // ABI properly... see . - // FIXME: should be forbid "neon" here? But that would be a breaking change. + // FIXME: should we forbid "neon" here? But that would be a breaking change. NOTHING } _ => { @@ -799,6 +808,8 @@ impl Target { } } "riscv32" | "riscv64" => { + // RISC-V handles ABI in a very sane way, being fully explicit via `llvm_abiname` + // about what the intended ABI is. match &*self.llvm_abiname { "ilp32d" | "lp64d" => { // Requires d (which implies f), incompatible with e. diff --git a/tests/codegen/tied-features-strength.rs b/tests/codegen/tied-features-strength.rs index 4d96a7cde78..6daa5cd7d5e 100644 --- a/tests/codegen/tied-features-strength.rs +++ b/tests/codegen/tied-features-strength.rs @@ -1,5 +1,5 @@ // ignore-tidy-linelength -//@ revisions: ENABLE_SVE DISABLE_SVE ENABLE_NEON +//@ revisions: ENABLE_SVE DISABLE_SVE DISABLE_NEON ENABLE_NEON //@ compile-flags: --crate-type=rlib --target=aarch64-unknown-linux-gnu //@ needs-llvm-components: aarch64 @@ -13,9 +13,9 @@ //@ [DISABLE_SVE] compile-flags: -C target-feature=-sve -Copt-level=0 // DISABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fpmr,?)?|(-sve,?)|(\+neon,?)|(\+fp-armv8,?))*}}" } -// The DISABLE_NEON is disabled since neon is a required target feature for this targt, it cannot be disabled. -// it would have: compile-flags: -C target-feature=-neon -Copt-level=0 -// DISABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fpmr,?)?|(-fp-armv8,?)|(-neon,?))*}}" } +//@ [DISABLE_NEON] compile-flags: -C target-feature=-neon -Copt-level=0 +// `neon` and `fp-armv8` get enabled as target base features, but then disabled again at the end of the list. +// DISABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fp-armv8,?)|(\+neon,?))*}},-neon,-fp-armv8{{(,\+fpmr)?}}" } //@ [ENABLE_NEON] compile-flags: -C target-feature=+neon -Copt-level=0 // ENABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fpmr,?)?|(\+fp-armv8,?)|(\+neon,?))*}}" } diff --git a/tests/run-make/simd-ffi/rmake.rs b/tests/run-make/simd-ffi/rmake.rs index 04990c8bdf4..ef71dfa4c30 100644 --- a/tests/run-make/simd-ffi/rmake.rs +++ b/tests/run-make/simd-ffi/rmake.rs @@ -56,7 +56,7 @@ fn main() { .target(&target) .emit("llvm-ir,asm") .input("simd.rs") - .arg("-Ctarget-feature=+neon,+sse") + .arg("-Ctarget-feature=-soft-float,+neon,+sse") .arg(&format!("-Cextra-filename=-{target}")) .run(); }