Skip to content

Commit

Permalink
Auto merge of #136146 - RalfJung:x86-abi, r=workingjubilee
Browse files Browse the repository at this point in the history
Explicitly choose x86 softfloat/hardfloat ABI

Part of #135408:
Instead of choosing this based on the target features listed in the target spec, make that choice explicit.
This means that all x86 (32bit and 64bit) softfloat target need to explicitly set `rustc-abi` to `x86-softfloat`.

Also fix some mistakes in the platform-docs where the x87 errata footnotes were missing or wrong.

try-job: x86_64-rust-for-linux
  • Loading branch information
bors committed Feb 2, 2025
2 parents 4a43094 + 42962c2 commit 3ad08df
Show file tree
Hide file tree
Showing 23 changed files with 166 additions and 65 deletions.
15 changes: 15 additions & 0 deletions compiler/rustc_target/src/spec/json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,19 @@ impl Target {
Some(Ok(()))
})).unwrap_or(Ok(()))
} );
($key_name:ident, RustcAbi) => ( {
let name = (stringify!($key_name)).replace("_", "-");
obj.remove(&name).and_then(|o| o.as_str().and_then(|s| {
match s.parse::<super::RustcAbi>() {
Ok(rustc_abi) => base.$key_name = Some(rustc_abi),
_ => return Some(Err(format!(
"'{s}' is not a valid value for rustc-abi. \
Use 'x86-softfloat' or leave the field unset."
))),
}
Some(Ok(()))
})).unwrap_or(Ok(()))
} );
($key_name:ident, RelocModel) => ( {
let name = (stringify!($key_name)).replace("_", "-");
obj.remove(&name).and_then(|o| o.as_str().and_then(|s| {
Expand Down Expand Up @@ -612,6 +625,7 @@ impl Target {
key!(llvm_mcount_intrinsic, optional);
key!(llvm_abiname);
key!(llvm_floatabi, FloatAbi)?;
key!(rustc_abi, RustcAbi)?;
key!(relax_elf_relocations, bool);
key!(llvm_args, list);
key!(use_ctors_section, bool);
Expand Down Expand Up @@ -788,6 +802,7 @@ impl ToJson for Target {
target_option_val!(llvm_mcount_intrinsic);
target_option_val!(llvm_abiname);
target_option_val!(llvm_floatabi);
target_option_val!(rustc_abi);
target_option_val!(relax_elf_relocations);
target_option_val!(llvm_args);
target_option_val!(use_ctors_section);
Expand Down
49 changes: 45 additions & 4 deletions compiler/rustc_target/src/spec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1114,6 +1114,33 @@ impl ToJson for FloatAbi {
}
}

/// The Rustc-specific variant of the ABI used for this target.
#[derive(Clone, Copy, PartialEq, Hash, Debug)]
pub enum RustcAbi {
/// On x86-32/64 only: do not use any FPU or SIMD registers for the ABI.
X86Softfloat,
}

impl FromStr for RustcAbi {
type Err = ();

fn from_str(s: &str) -> Result<RustcAbi, ()> {
Ok(match s {
"x86-softfloat" => RustcAbi::X86Softfloat,
_ => return Err(()),
})
}
}

impl ToJson for RustcAbi {
fn to_json(&self) -> Json {
match *self {
RustcAbi::X86Softfloat => "x86-softfloat",
}
.to_json()
}
}

#[derive(Clone, Copy, PartialEq, Hash, Debug)]
pub enum TlsModel {
GeneralDynamic,
Expand Down Expand Up @@ -2505,6 +2532,12 @@ pub struct TargetOptions {
/// If not provided, LLVM will infer the float ABI from the target triple (`llvm_target`).
pub llvm_floatabi: Option<FloatAbi>,

/// Picks a specific ABI for this target. This is *not* just for "Rust" ABI functions,
/// it can also affect "C" ABI functions; the point is that this flag is interpreted by
/// rustc and not forwarded to LLVM.
/// So far, this is only used on x86.
pub rustc_abi: Option<RustcAbi>,

/// Whether or not RelaxElfRelocation flag will be passed to the linker
pub relax_elf_relocations: bool,

Expand Down Expand Up @@ -2664,10 +2697,6 @@ impl TargetOptions {
.collect();
}
}

pub(crate) fn has_feature(&self, search_feature: &str) -> bool {
self.features.split(',').any(|f| f.strip_prefix('+').is_some_and(|f| f == search_feature))
}
}

impl Default for TargetOptions {
Expand Down Expand Up @@ -2774,6 +2803,7 @@ impl Default for TargetOptions {
llvm_mcount_intrinsic: None,
llvm_abiname: "".into(),
llvm_floatabi: None,
rustc_abi: None,
relax_elf_relocations: false,
llvm_args: cvs![],
use_ctors_section: false,
Expand Down Expand Up @@ -3240,6 +3270,17 @@ impl Target {
_ => {}
}

// Check consistency of Rust ABI declaration.
if let Some(rust_abi) = self.rustc_abi {
match rust_abi {
RustcAbi::X86Softfloat => check_matches!(
&*self.arch,
"x86" | "x86_64",
"`x86-softfloat` ABI is only valid for x86 targets"
),
}
}

// Check that the given target-features string makes some basic sense.
if !self.features.is_empty() {
let mut features_enabled = FxHashSet::default();
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// The cdecl ABI is used. It differs from the stdcall or fastcall ABI.
// "i686-unknown-windows" is used to get the minimal subset of windows-specific features.

use crate::spec::{Target, base};
use crate::spec::{RustcAbi, Target, base};

pub(crate) fn target() -> Target {
let mut base = base::uefi_msvc::opts();
Expand All @@ -22,6 +22,7 @@ pub(crate) fn target() -> Target {
// If you initialize FP units yourself, you can override these flags with custom linker
// arguments, thus giving you access to full MMX/SSE acceleration.
base.features = "-mmx,-sse,+soft-float".into();
base.rustc_abi = Some(RustcAbi::X86Softfloat);

// Use -GNU here, because of the reason below:
// Background and Problem:
Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
// features.

use crate::spec::{
Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy, RelroLevel, SanitizerSet, StackProbeType,
Target, TargetOptions,
Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy, RelroLevel, RustcAbi, SanitizerSet,
StackProbeType, Target, TargetOptions,
};

pub(crate) fn target() -> Target {
Expand All @@ -20,6 +20,7 @@ pub(crate) fn target() -> Target {
relro_level: RelroLevel::Full,
linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
linker: Some("rust-lld".into()),
rustc_abi: Some(RustcAbi::X86Softfloat),
features: "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-avx,-avx2,+soft-float".into(),
supported_sanitizers: SanitizerSet::KCFI | SanitizerSet::KERNELADDRESS,
disable_redzone: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// LLVM. "x86_64-unknown-windows" is used to get the minimal subset of windows-specific features.

use crate::abi::call::Conv;
use crate::spec::{Target, base};
use crate::spec::{RustcAbi, Target, base};

pub(crate) fn target() -> Target {
let mut base = base::uefi_msvc::opts();
Expand All @@ -26,6 +26,7 @@ pub(crate) fn target() -> Target {
// If you initialize FP units yourself, you can override these flags with custom linker
// arguments, thus giving you access to full MMX/SSE acceleration.
base.features = "-mmx,-sse,+soft-float".into();
base.rustc_abi = Some(RustcAbi::X86Softfloat);

Target {
llvm_target: "x86_64-unknown-windows".into(),
Expand Down
52 changes: 36 additions & 16 deletions compiler/rustc_target/src/target_features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{FloatAbi, Target};
use crate::spec::{FloatAbi, RustcAbi, Target};

/// Features that control behaviour of rustc, rather than the codegen.
/// These exist globally and are not in the target-specific lists below.
Expand Down Expand Up @@ -422,7 +422,9 @@ const X86_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
("sha512", Unstable(sym::sha512_sm_x86), &["avx2"]),
("sm3", Unstable(sym::sha512_sm_x86), &["avx"]),
("sm4", Unstable(sym::sha512_sm_x86), &["avx2"]),
("soft-float", Stability::Forbidden { reason: "unsound because it changes float ABI" }, &[]),
// This cannot actually be toggled, the ABI always fixes it, so it'd make little sense to
// stabilize. It must be in this list for the ABI check to be able to use it.
("soft-float", Stability::Unstable(sym::x87_target_feature), &[]),
("sse", Stable, &[]),
("sse2", Stable, &["sse"]),
("sse3", Stable, &["sse2"]),
Expand Down Expand Up @@ -773,23 +775,41 @@ impl Target {
// questions "which ABI is used".
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 {
// Hardfloat ABI. x87 must be enabled.
FeatureConstraints { required: &["x87"], incompatible: &[] }
// We use our own ABI indicator here; LLVM does not have anything native.
// Every case should require or forbid `soft-float`!
match self.rustc_abi {
None => {
// Default hardfloat ABI.
// x87 must be enabled, soft-float must be disabled.
FeatureConstraints { required: &["x87"], incompatible: &["soft-float"] }
}
Some(RustcAbi::X86Softfloat) => {
// Softfloat ABI, requires corresponding target feature. That feature trumps
// `x87` and all other FPU features so those do not matter.
// Note that this one requirement is the entire implementation of the ABI!
// LLVM handles the rest.
FeatureConstraints { required: &["soft-float"], incompatible: &[] }
}
}
}
"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 {
// Hardfloat ABI. x87 and SSE2 must be enabled.
FeatureConstraints { required: &["x87", "sse2"], incompatible: &[] }
// We use our own ABI indicator here; LLVM does not have anything native.
// Every case should require or forbid `soft-float`!
match self.rustc_abi {
None => {
// Default hardfloat ABI. On x86-64, this always includes SSE2.
FeatureConstraints {
required: &["x87", "sse2"],
incompatible: &["soft-float"],
}
}
Some(RustcAbi::X86Softfloat) => {
// Softfloat ABI, requires corresponding target feature. That feature trumps
// `x87` and all other FPU features so those do not matter.
// Note that this one requirement is the entire implementation of the ABI!
// LLVM handles the rest.
FeatureConstraints { required: &["soft-float"], incompatible: &[] }
}
}
}
"arm" => {
Expand Down
4 changes: 2 additions & 2 deletions src/ci/docker/scripts/rfl-build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

set -euo pipefail

LINUX_VERSION=v6.13-rc1
LINUX_VERSION=5c4c930873e33cff6d1db9cae56a6cc321fde1af

# Build rustc, rustdoc, cargo, clippy-driver and rustfmt
../x.py build --stage 2 library rustdoc clippy rustfmt
Expand All @@ -28,7 +28,7 @@ rm -rf linux || true
# Download Linux at a specific commit
mkdir -p linux
git -C linux init
git -C linux remote add origin https://github.com/Rust-for-Linux/linux.git
git -C linux remote add origin https://github.com/Darksonn/linux.git
git -C linux fetch --depth 1 origin ${LINUX_VERSION}
git -C linux checkout FETCH_HEAD

Expand Down
10 changes: 5 additions & 5 deletions src/doc/rustc/src/platform-support.md
Original file line number Diff line number Diff line change
Expand Up @@ -309,13 +309,13 @@ target | std | host | notes
[`hexagon-unknown-none-elf`](platform-support/hexagon-unknown-none-elf.md)| * | | Bare Hexagon (v60+, HVX)
[`i386-apple-ios`](platform-support/apple-ios.md) | ✓ | | 32-bit x86 iOS [^x86_32-floats-return-ABI]
[`i586-pc-nto-qnx700`](platform-support/nto-qnx.md) | * | | 32-bit x86 QNX Neutrino 7.0 RTOS [^x86_32-floats-return-ABI]
[`i586-unknown-netbsd`](platform-support/netbsd.md) | ✓ | | 32-bit x86, restricted to Pentium
[`i586-unknown-netbsd`](platform-support/netbsd.md) | ✓ | | 32-bit x86, restricted to Pentium [^x86_32-floats-x87]
[`i686-apple-darwin`](platform-support/apple-darwin.md) | ✓ | ✓ | 32-bit macOS (10.12+, Sierra+) [^x86_32-floats-return-ABI]
`i686-unknown-haiku` | ✓ | ✓ | 32-bit Haiku [^x86_32-floats-return-ABI]
[`i686-unknown-hurd-gnu`](platform-support/hurd.md) | ✓ | ✓ | 32-bit GNU/Hurd [^x86_32-floats-return-ABI]
`i686-unknown-haiku` | ✓ | ✓ | 32-bit Haiku with SSE [^x86_32-floats-return-ABI]
[`i686-unknown-hurd-gnu`](platform-support/hurd.md) | ✓ | ✓ | 32-bit GNU/Hurd w/o SSE [^x86_32-floats-x87]
[`i686-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD/i386 with SSE2 [^x86_32-floats-return-ABI]
[`i686-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 32-bit OpenBSD [^x86_32-floats-return-ABI]
[`i686-unknown-redox`](platform-support/redox.md) | ✓ | | i686 Redox OS
[`i686-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 32-bit OpenBSD with SSE2 [^x86_32-floats-return-ABI]
[`i686-unknown-redox`](platform-support/redox.md) | ✓ | | i686 Redox OS w/o SSE [^x86_32-floats-x87]
`i686-uwp-windows-gnu` | ✓ | | [^x86_32-floats-return-ABI]
[`i686-uwp-windows-msvc`](platform-support/uwp-windows-msvc.md) | ✓ | | [^x86_32-floats-return-ABI]
[`i686-win7-windows-gnu`](platform-support/win7-windows-gnu.md) | ✓ | | 32-bit Windows 7 support [^x86_32-floats-return-ABI]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//! Ensure ABI-incompatible features cannot be enabled via `#[target_feature]`.
//@ compile-flags: --target=riscv32e-unknown-none-elf --crate-type=lib
//@ needs-llvm-components: riscv
#![feature(no_core, lang_items, riscv_target_feature)]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error: target feature `d` cannot be enabled with `#[target_feature]`: this feature is incompatible with the target ABI
--> $DIR/forbidden-hardfloat-target-feature-attribute.rs:9:18
--> $DIR/forbidden-hardfloat-target-feature-attribute.rs:10:18
|
LL | #[target_feature(enable = "d")]
| ^^^^^^^^^^^^
Expand Down
14 changes: 0 additions & 14 deletions tests/ui/target-feature/forbidden-hardfloat-target-feature-cfg.rs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
//! Ensure that if disabling a target feature implies disabling an ABI-required target feature,
//! we complain.
//@ compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=lib
//@ needs-llvm-components: x86
//@ compile-flags: -Ctarget-feature=-sse
// For now this is just a warning.
//@ build-pass
//@error-pattern: must be enabled to ensure that the ABI
#![feature(no_core, lang_items)]
#![no_core]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
//@ compile-flags: -Ctarget-feature=-neon
// For now this is just a warning.
//@ build-pass
//@error-pattern: must be enabled to ensure that the ABI
#![feature(no_core, lang_items)]
#![no_core]

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
//! Ensure ABI-required features cannot be disabled via `-Ctarget-feature`.
//@ compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=lib
//@ needs-llvm-components: x86
//@ compile-flags: -Ctarget-feature=-x87
// For now this is just a warning.
//@ build-pass
//@error-pattern: must be enabled to ensure that the ABI
#![feature(no_core, lang_items)]
#![no_core]

Expand Down
12 changes: 12 additions & 0 deletions tests/ui/target-feature/forbidden-hardfloat-target-feature-flag.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//! Ensure ABI-incompatible features cannot be enabled via `-Ctarget-feature`.
//@ compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=lib
//@ needs-llvm-components: x86
//@ compile-flags: -Ctarget-feature=+soft-float
// For now this is just a warning.
//@ build-pass
//@error-pattern: must be disabled to ensure that the ABI
#![feature(no_core, lang_items, riscv_target_feature)]
#![no_core]

#[lang = "sized"]
pub trait Sized {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
warning: target feature `soft-float` must be disabled to ensure that the ABI of the current target can be implemented correctly
|
= note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #116344 <https://github.com/rust-lang/rust/issues/116344>

warning: unstable feature specified for `-Ctarget-feature`: `soft-float`
|
= note: this feature is not stably supported; its behavior can change in the future

warning: 2 warnings emitted

7 changes: 4 additions & 3 deletions tests/ui/target-feature/forbidden-target-feature-attribute.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
//@ compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=lib
//@ needs-llvm-components: x86
//! Ensure "forbidden" target features cannot be enabled via `#[target_feature]`.
//@ compile-flags: --target=riscv32e-unknown-none-elf --crate-type=lib
//@ needs-llvm-components: riscv
#![feature(no_core, lang_items)]
#![no_core]

#[lang = "sized"]
pub trait Sized {}

#[target_feature(enable = "soft-float")]
#[target_feature(enable = "forced-atomics")]
//~^ERROR: cannot be enabled with
pub unsafe fn my_fun() {}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error: target feature `soft-float` cannot be enabled with `#[target_feature]`: unsound because it changes float ABI
--> $DIR/forbidden-target-feature-attribute.rs:9:18
error: target feature `forced-atomics` cannot be enabled with `#[target_feature]`: unsound because it changes the ABI of atomic operations
--> $DIR/forbidden-target-feature-attribute.rs:10:18
|
LL | #[target_feature(enable = "soft-float")]
| ^^^^^^^^^^^^^^^^^^^^^
LL | #[target_feature(enable = "forced-atomics")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 1 previous error

Loading

0 comments on commit 3ad08df

Please sign in to comment.