Skip to content

Commit 9a08be7

Browse files
committed
add rustc_abi to control ABI decisions LLVM does not have flags for, and use it for x86 softfloat
1 parent 79fe463 commit 9a08be7

8 files changed

+100
-23
lines changed

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 rust-abi. \
138+
Use 'x86-softfloat' or 'x86-sse2'."
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| {
@@ -611,6 +624,7 @@ impl Target {
611624
key!(llvm_mcount_intrinsic, optional);
612625
key!(llvm_abiname);
613626
key!(llvm_floatabi, FloatAbi)?;
627+
key!(rustc_abi, RustcAbi)?;
614628
key!(relax_elf_relocations, bool);
615629
key!(llvm_args, list);
616630
key!(use_ctors_section, bool);
@@ -786,6 +800,7 @@ impl ToJson for Target {
786800
target_option_val!(llvm_mcount_intrinsic);
787801
target_option_val!(llvm_abiname);
788802
target_option_val!(llvm_floatabi);
803+
target_option_val!(rustc_abi);
789804
target_option_val!(relax_elf_relocations);
790805
target_option_val!(llvm_args);
791806
target_option_val!(use_ctors_section);

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,
@@ -2502,6 +2529,12 @@ pub struct TargetOptions {
25022529
/// If not provided, LLVM will infer the float ABI from the target triple (`llvm_target`).
25032530
pub llvm_floatabi: Option<FloatAbi>,
25042531

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

@@ -2661,10 +2694,6 @@ impl TargetOptions {
26612694
.collect();
26622695
}
26632696
}
2664-
2665-
pub(crate) fn has_feature(&self, search_feature: &str) -> bool {
2666-
self.features.split(',').any(|f| f.strip_prefix('+').is_some_and(|f| f == search_feature))
2667-
}
26682697
}
26692698

26702699
impl Default for TargetOptions {
@@ -2770,6 +2799,7 @@ impl Default for TargetOptions {
27702799
llvm_mcount_intrinsic: None,
27712800
llvm_abiname: "".into(),
27722801
llvm_floatabi: None,
2802+
rustc_abi: None,
27732803
relax_elf_relocations: false,
27742804
llvm_args: cvs![],
27752805
use_ctors_section: false,
@@ -3236,6 +3266,17 @@ impl Target {
32363266
_ => {}
32373267
}
32383268

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

compiler/rustc_target/src/spec/targets/i586_unknown_linux_gnu.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use crate::spec::Target;
22

33
pub(crate) fn target() -> Target {
44
let mut base = super::i686_unknown_linux_gnu::target();
5+
base.rustc_abi = None;
56
base.cpu = "pentium".into();
67
base.llvm_target = "i586-unknown-linux-gnu".into();
78
base

compiler/rustc_target/src/spec/targets/i586_unknown_linux_musl.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use crate::spec::Target;
22

33
pub(crate) fn target() -> Target {
44
let mut base = super::i686_unknown_linux_musl::target();
5+
base.rustc_abi = None;
56
base.cpu = "pentium".into();
67
base.llvm_target = "i586-unknown-linux-musl".into();
78
// FIXME(compiler-team#422): musl targets should be dynamically linked by default.

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:

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,

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(),

compiler/rustc_target/src/target_features.rs

+31-15
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.
@@ -770,23 +770,39 @@ impl Target {
770770
// questions "which ABI is used".
771771
match &*self.arch {
772772
"x86" => {
773-
// We support 2 ABIs, hardfloat (default) and softfloat.
774-
// x86 has no sane ABI indicator so we have to use the target feature.
775-
if self.has_feature("soft-float") {
776-
NOTHING
777-
} else {
778-
// Hardfloat ABI. x87 must be enabled.
779-
FeatureConstraints { required: &["x87"], incompatible: &[] }
773+
// We use our own ABI indicator here; LLVM does not have anything native.
774+
match self.rustc_abi {
775+
None => {
776+
// Default hardfloat ABI.
777+
// x87 must be enabled, soft-float must be disabled.
778+
FeatureConstraints { required: &["x87"], incompatible: &["soft-float"] }
779+
}
780+
Some(RustcAbi::X86Softfloat) => {
781+
// Softfloat ABI, requires corresponding target feature. That feature trumps
782+
// `x87` and all other FPU features so those do not matter.
783+
// Note that this one requirement is the entire implementation of the ABI!
784+
// LLVM handles the rest.
785+
FeatureConstraints { required: &["soft-float"], incompatible: &[] }
786+
}
780787
}
781788
}
782789
"x86_64" => {
783-
// We support 2 ABIs, hardfloat (default) and softfloat.
784-
// x86 has no sane ABI indicator so we have to use the target feature.
785-
if self.has_feature("soft-float") {
786-
NOTHING
787-
} else {
788-
// Hardfloat ABI. x87 and SSE2 must be enabled.
789-
FeatureConstraints { required: &["x87", "sse2"], incompatible: &[] }
790+
// We use our own ABI indicator here; LLVM does not have anything native.
791+
match self.rustc_abi {
792+
None => {
793+
// Default hardfloat ABI. On x86-64, this always includes SSE2.
794+
FeatureConstraints {
795+
required: &["x87", "sse2"],
796+
incompatible: &["soft-float"],
797+
}
798+
}
799+
Some(RustcAbi::X86Softfloat) => {
800+
// Softfloat ABI, requires corresponding target feature. That feature trumps
801+
// `x87` and all other FPU features so those do not matter.
802+
// Note that this one requirement is the entire implementation of the ABI!
803+
// LLVM handles the rest.
804+
FeatureConstraints { required: &["soft-float"], incompatible: &[] }
805+
}
790806
}
791807
}
792808
"arm" => {

0 commit comments

Comments
 (0)