Skip to content

Commit f027438

Browse files
committed
Auto merge of #136146 - RalfJung:x86-abi, r=workingjubilee
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. All built-in targets are being updated here; custom (JSON-defined) x86 (32bit and 64bit) softfloat targets need to explicitly set `rustc-abi` to `x86-softfloat`.
2 parents 534d79a + 8596ce1 commit f027438

22 files changed

+161
-60
lines changed

Diff for: compiler/rustc_target/src/spec/json.rs

+15
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,19 @@ impl Target {
128128
Some(Ok(()))
129129
})).unwrap_or(Ok(()))
130130
} );
131+
($key_name:ident, RustcAbi) => ( {
132+
let name = (stringify!($key_name)).replace("_", "-");
133+
obj.remove(&name).and_then(|o| o.as_str().and_then(|s| {
134+
match s.parse::<super::RustcAbi>() {
135+
Ok(rustc_abi) => base.$key_name = Some(rustc_abi),
136+
_ => return Some(Err(format!(
137+
"'{s}' is not a valid value for rustc-abi. \
138+
Use 'x86-softfloat' or leave the field unset."
139+
))),
140+
}
141+
Some(Ok(()))
142+
})).unwrap_or(Ok(()))
143+
} );
131144
($key_name:ident, RelocModel) => ( {
132145
let name = (stringify!($key_name)).replace("_", "-");
133146
obj.remove(&name).and_then(|o| o.as_str().and_then(|s| {
@@ -612,6 +625,7 @@ impl Target {
612625
key!(llvm_mcount_intrinsic, optional);
613626
key!(llvm_abiname);
614627
key!(llvm_floatabi, FloatAbi)?;
628+
key!(rustc_abi, RustcAbi)?;
615629
key!(relax_elf_relocations, bool);
616630
key!(llvm_args, list);
617631
key!(use_ctors_section, bool);
@@ -788,6 +802,7 @@ impl ToJson for Target {
788802
target_option_val!(llvm_mcount_intrinsic);
789803
target_option_val!(llvm_abiname);
790804
target_option_val!(llvm_floatabi);
805+
target_option_val!(rustc_abi);
791806
target_option_val!(relax_elf_relocations);
792807
target_option_val!(llvm_args);
793808
target_option_val!(use_ctors_section);

Diff for: compiler/rustc_target/src/spec/mod.rs

+45-4
Original file line numberDiff line numberDiff line change
@@ -1114,6 +1114,33 @@ impl ToJson for FloatAbi {
11141114
}
11151115
}
11161116

1117+
/// The Rustc-specific variant of the ABI used for this target.
1118+
#[derive(Clone, Copy, PartialEq, Hash, Debug)]
1119+
pub enum RustcAbi {
1120+
/// On x86-32/64 only: do not use any FPU or SIMD registers for the ABI.
1121+
X86Softfloat,
1122+
}
1123+
1124+
impl FromStr for RustcAbi {
1125+
type Err = ();
1126+
1127+
fn from_str(s: &str) -> Result<RustcAbi, ()> {
1128+
Ok(match s {
1129+
"x86-softfloat" => RustcAbi::X86Softfloat,
1130+
_ => return Err(()),
1131+
})
1132+
}
1133+
}
1134+
1135+
impl ToJson for RustcAbi {
1136+
fn to_json(&self) -> Json {
1137+
match *self {
1138+
RustcAbi::X86Softfloat => "x86-softfloat",
1139+
}
1140+
.to_json()
1141+
}
1142+
}
1143+
11171144
#[derive(Clone, Copy, PartialEq, Hash, Debug)]
11181145
pub enum TlsModel {
11191146
GeneralDynamic,
@@ -2505,6 +2532,12 @@ pub struct TargetOptions {
25052532
/// If not provided, LLVM will infer the float ABI from the target triple (`llvm_target`).
25062533
pub llvm_floatabi: Option<FloatAbi>,
25072534

2535+
/// Picks a specific ABI for this target. This is *not* just for "Rust" ABI functions,
2536+
/// it can also affect "C" ABI functions; the point is that this flag is interpreted by
2537+
/// rustc and not forwarded to LLVM.
2538+
/// So far, this is only used on x86.
2539+
pub rustc_abi: Option<RustcAbi>,
2540+
25082541
/// Whether or not RelaxElfRelocation flag will be passed to the linker
25092542
pub relax_elf_relocations: bool,
25102543

@@ -2664,10 +2697,6 @@ impl TargetOptions {
26642697
.collect();
26652698
}
26662699
}
2667-
2668-
pub(crate) fn has_feature(&self, search_feature: &str) -> bool {
2669-
self.features.split(',').any(|f| f.strip_prefix('+').is_some_and(|f| f == search_feature))
2670-
}
26712700
}
26722701

26732702
impl Default for TargetOptions {
@@ -2774,6 +2803,7 @@ impl Default for TargetOptions {
27742803
llvm_mcount_intrinsic: None,
27752804
llvm_abiname: "".into(),
27762805
llvm_floatabi: None,
2806+
rustc_abi: None,
27772807
relax_elf_relocations: false,
27782808
llvm_args: cvs![],
27792809
use_ctors_section: false,
@@ -3240,6 +3270,17 @@ impl Target {
32403270
_ => {}
32413271
}
32423272

3273+
// Check consistency of Rust ABI declaration.
3274+
if let Some(rust_abi) = self.rustc_abi {
3275+
match rust_abi {
3276+
RustcAbi::X86Softfloat => check_matches!(
3277+
&*self.arch,
3278+
"x86" | "x86_64",
3279+
"`x86-softfloat` ABI is only valid for x86 targets"
3280+
),
3281+
}
3282+
}
3283+
32433284
// Check that the given target-features string makes some basic sense.
32443285
if !self.features.is_empty() {
32453286
let mut features_enabled = FxHashSet::default();

Diff for: compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// The cdecl ABI is used. It differs from the stdcall or fastcall ABI.
66
// "i686-unknown-windows" is used to get the minimal subset of windows-specific features.
77

8-
use crate::spec::{Target, base};
8+
use crate::spec::{RustcAbi, Target, base};
99

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

2627
// Use -GNU here, because of the reason below:
2728
// Background and Problem:

Diff for: compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
// features.
66

77
use crate::spec::{
8-
Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy, RelroLevel, SanitizerSet, StackProbeType,
9-
Target, TargetOptions,
8+
Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy, RelroLevel, RustcAbi, SanitizerSet,
9+
StackProbeType, Target, TargetOptions,
1010
};
1111

1212
pub(crate) fn target() -> Target {
@@ -20,6 +20,7 @@ pub(crate) fn target() -> Target {
2020
relro_level: RelroLevel::Full,
2121
linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
2222
linker: Some("rust-lld".into()),
23+
rustc_abi: Some(RustcAbi::X86Softfloat),
2324
features: "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-avx,-avx2,+soft-float".into(),
2425
supported_sanitizers: SanitizerSet::KCFI | SanitizerSet::KERNELADDRESS,
2526
disable_redzone: true,

Diff for: compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
// LLVM. "x86_64-unknown-windows" is used to get the minimal subset of windows-specific features.
77

88
use crate::abi::call::Conv;
9-
use crate::spec::{Target, base};
9+
use crate::spec::{RustcAbi, Target, base};
1010

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

3031
Target {
3132
llvm_target: "x86_64-unknown-windows".into(),

Diff for: compiler/rustc_target/src/target_features.rs

+36-16
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
55
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
66
use rustc_span::{Symbol, sym};
77

8-
use crate::spec::{FloatAbi, Target};
8+
use crate::spec::{FloatAbi, RustcAbi, Target};
99

1010
/// Features that control behaviour of rustc, rather than the codegen.
1111
/// These exist globally and are not in the target-specific lists below.
@@ -422,7 +422,9 @@ const X86_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
422422
("sha512", Unstable(sym::sha512_sm_x86), &["avx2"]),
423423
("sm3", Unstable(sym::sha512_sm_x86), &["avx"]),
424424
("sm4", Unstable(sym::sha512_sm_x86), &["avx2"]),
425-
("soft-float", Stability::Forbidden { reason: "unsound because it changes float ABI" }, &[]),
425+
// This cannot actually be toggled, the ABI always fixes it, so it'd make little sense to
426+
// stabilize. It must be in this list for the ABI check to be able to use it.
427+
("soft-float", Stability::Unstable(sym::x87_target_feature), &[]),
426428
("sse", Stable, &[]),
427429
("sse2", Stable, &["sse"]),
428430
("sse3", Stable, &["sse2"]),
@@ -773,23 +775,41 @@ impl Target {
773775
// questions "which ABI is used".
774776
match &*self.arch {
775777
"x86" => {
776-
// We support 2 ABIs, hardfloat (default) and softfloat.
777-
// x86 has no sane ABI indicator so we have to use the target feature.
778-
if self.has_feature("soft-float") {
779-
NOTHING
780-
} else {
781-
// Hardfloat ABI. x87 must be enabled.
782-
FeatureConstraints { required: &["x87"], incompatible: &[] }
778+
// We use our own ABI indicator here; LLVM does not have anything native.
779+
// Every case should require or forbid `soft-float`!
780+
match self.rustc_abi {
781+
None => {
782+
// Default hardfloat ABI.
783+
// x87 must be enabled, soft-float must be disabled.
784+
FeatureConstraints { required: &["x87"], incompatible: &["soft-float"] }
785+
}
786+
Some(RustcAbi::X86Softfloat) => {
787+
// Softfloat ABI, requires corresponding target feature. That feature trumps
788+
// `x87` and all other FPU features so those do not matter.
789+
// Note that this one requirement is the entire implementation of the ABI!
790+
// LLVM handles the rest.
791+
FeatureConstraints { required: &["soft-float"], incompatible: &[] }
792+
}
783793
}
784794
}
785795
"x86_64" => {
786-
// We support 2 ABIs, hardfloat (default) and softfloat.
787-
// x86 has no sane ABI indicator so we have to use the target feature.
788-
if self.has_feature("soft-float") {
789-
NOTHING
790-
} else {
791-
// Hardfloat ABI. x87 and SSE2 must be enabled.
792-
FeatureConstraints { required: &["x87", "sse2"], incompatible: &[] }
796+
// We use our own ABI indicator here; LLVM does not have anything native.
797+
// Every case should require or forbid `soft-float`!
798+
match self.rustc_abi {
799+
None => {
800+
// Default hardfloat ABI. On x86-64, this always includes SSE2.
801+
FeatureConstraints {
802+
required: &["x87", "sse2"],
803+
incompatible: &["soft-float"],
804+
}
805+
}
806+
Some(RustcAbi::X86Softfloat) => {
807+
// Softfloat ABI, requires corresponding target feature. That feature trumps
808+
// `x87` and all other FPU features so those do not matter.
809+
// Note that this one requirement is the entire implementation of the ABI!
810+
// LLVM handles the rest.
811+
FeatureConstraints { required: &["soft-float"], incompatible: &[] }
812+
}
793813
}
794814
}
795815
"arm" => {

Diff for: src/ci/docker/scripts/rfl-build.sh

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
set -euo pipefail
44

5-
LINUX_VERSION=v6.13-rc1
5+
LINUX_VERSION=50e57739141b41f731ab31f8380821c7969f9dc4
66

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

Diff for: tests/ui/target-feature/forbidden-hardfloat-target-feature-attribute.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
//! Ensure ABI-incompatible features cannot be enabled via `#[target_feature]`.
12
//@ compile-flags: --target=riscv32e-unknown-none-elf --crate-type=lib
23
//@ needs-llvm-components: riscv
34
#![feature(no_core, lang_items, riscv_target_feature)]

Diff for: tests/ui/target-feature/forbidden-hardfloat-target-feature-attribute.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: target feature `d` cannot be enabled with `#[target_feature]`: this feature is incompatible with the target ABI
2-
--> $DIR/forbidden-hardfloat-target-feature-attribute.rs:9:18
2+
--> $DIR/forbidden-hardfloat-target-feature-attribute.rs:10:18
33
|
44
LL | #[target_feature(enable = "d")]
55
| ^^^^^^^^^^^^

Diff for: tests/ui/target-feature/forbidden-hardfloat-target-feature-cfg.rs

-14
This file was deleted.

Diff for: tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable-implied.rs

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

Diff for: tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable-neon.rs

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
//@ compile-flags: -Ctarget-feature=-neon
44
// For now this is just a warning.
55
//@ build-pass
6+
//@error-pattern: must be enabled to ensure that the ABI
67
#![feature(no_core, lang_items)]
78
#![no_core]
89

Diff for: tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable.rs

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

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//! Ensure ABI-incompatible features cannot be enabled via `-Ctarget-feature`.
2+
//@ compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=lib
3+
//@ needs-llvm-components: x86
4+
//@ compile-flags: -Ctarget-feature=+soft-float
5+
// For now this is just a warning.
6+
//@ build-pass
7+
//@error-pattern: must be disabled to ensure that the ABI
8+
#![feature(no_core, lang_items, riscv_target_feature)]
9+
#![no_core]
10+
11+
#[lang = "sized"]
12+
pub trait Sized {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
warning: target feature `soft-float` must be disabled to ensure that the ABI of the current target can be implemented correctly
2+
|
3+
= note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
4+
= note: for more information, see issue #116344 <https://github.com/rust-lang/rust/issues/116344>
5+
6+
warning: unstable feature specified for `-Ctarget-feature`: `soft-float`
7+
|
8+
= note: this feature is not stably supported; its behavior can change in the future
9+
10+
warning: 2 warnings emitted
11+
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
//@ compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=lib
2-
//@ needs-llvm-components: x86
1+
//! Ensure "forbidden" target features cannot be enabled via `#[target_feature]`.
2+
//@ compile-flags: --target=riscv32e-unknown-none-elf --crate-type=lib
3+
//@ needs-llvm-components: riscv
34
#![feature(no_core, lang_items)]
45
#![no_core]
56

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

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

77
error: aborting due to 1 previous error
88

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
//@ compile-flags: --target=x86_64-unknown-none --crate-type=lib
2-
//@ needs-llvm-components: x86
1+
//! Ensure "forbidden" target features are not exposed via `cfg`.
2+
//@ compile-flags: --target=riscv32e-unknown-none-elf --crate-type=lib
3+
//@ needs-llvm-components: riscv
34
//@ check-pass
45
#![feature(no_core, lang_items)]
56
#![no_core]
@@ -10,5 +11,5 @@ pub trait Sized {}
1011

1112
// The compile_error macro does not exist, so if the `cfg` evaluates to `true` this
1213
// complains about the missing macro rather than showing the error... but that's good enough.
13-
#[cfg(target_feature = "soft-float")]
14-
compile_error!("the soft-float feature should not be exposed in `cfg`");
14+
#[cfg(target_feature = "forced-atomics")]
15+
compile_error!("the forced-atomics feature should not be exposed in `cfg`");

0 commit comments

Comments
 (0)