Rollup merge of #151154 - fneddy:s390x_softfloat_abi, r=workingjubilee

Add `s390x-unknown-none-softfloat` with `RustcAbi::Softfloat`

followup on rust-lang/rust#150766

add an `s390x-unknown-none-softfloat` target to use for kernel compilation, as the Linux kernel does not wish to pay the overhead of saving float registers by default on kernel switch. this target's `extern "C"` ABI is unspecified, so it is unstable and subject to change between versions, just like the Linux intrakernel ABI and `extern "Rust"` ABIs are unstable.

enforce target feature incompatibility by adding `RustcAbi::Softfloat`. this is itself just a rename of `RustcAbi::X86Softfloat`, accepting both "x86-softfloat" and "softfloat" as valid strings in the target.json format. the target-features of `"soft-float"` and `"vector"` are incompatible for s390x, so issue a compatibility warning if they are combined.
This commit is contained in:
Jonathan Brouwer 2026-02-09 23:37:48 +01:00 committed by GitHub
commit 1f59a4a86b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
23 changed files with 350 additions and 22 deletions

View file

@ -28,7 +28,7 @@ where
BackendRepr::ScalableVector { .. } => panic!("scalable vectors are unsupported"),
BackendRepr::Scalar(scalar) => {
if is_ret && matches!(scalar.primitive(), Primitive::Int(Integer::I128, _)) {
if cx.target_spec().rustc_abi == Some(RustcAbi::X86Softfloat) {
if cx.target_spec().rustc_abi == Some(RustcAbi::Softfloat) {
// Use the native `i128` LLVM type for the softfloat ABI -- in other words, adjust nothing.
} else {
// `i128` is returned in xmm0 by Clang and GCC

View file

@ -76,7 +76,7 @@ macro_rules! target_spec_enum {
pub enum $Name:ident {
$(
$( #[$variant_attr:meta] )*
$Variant:ident = $string:literal,
$Variant:ident = $string:literal $(,$alias:literal)* ,
)*
}
parse_error_type = $parse_error_type:literal;
@ -88,6 +88,7 @@ macro_rules! target_spec_enum {
$(
$( #[$variant_attr] )*
#[serde(rename = $string)] // for JSON schema generation only
$( #[serde(alias = $alias)] )*
$Variant,
)*
}
@ -97,7 +98,10 @@ macro_rules! target_spec_enum {
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(match s {
$( $string => Self::$Variant, )*
$(
$string => Self::$Variant,
$($alias => Self::$Variant,)*
)*
_ => {
let all = [$( concat!("'", $string, "'") ),*].join(", ");
return Err(format!("invalid {}: '{s}'. allowed values: {all}", $parse_error_type));
@ -123,7 +127,7 @@ macro_rules! target_spec_enum {
pub enum $Name:ident {
$(
$( #[$variant_attr:meta] )*
$Variant:ident = $string:literal,
$Variant:ident = $string:literal $(,$alias:literal)* ,
)*
}
$( #[$other_variant_attr:meta] )*
@ -134,6 +138,7 @@ macro_rules! target_spec_enum {
pub enum $Name {
$(
$( #[$variant_attr:meta] )*
$( #[serde(alias = $alias)] )*
$Variant,
)*
/// The vast majority of the time, the compiler deals with a fixed
@ -165,7 +170,10 @@ macro_rules! target_spec_enum {
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(match s {
$( $string => Self::$Variant, )*
$(
$string => Self::$Variant,
$($alias => Self::$Variant,)*
)*
_ => Self::$OtherVariant(s.to_owned().into()),
})
}

View file

@ -1005,8 +1005,8 @@ crate::target_spec_enum! {
pub enum RustcAbi {
/// On x86-32 only: make use of SSE and SSE2 for ABI purposes.
X86Sse2 = "x86-sse2",
/// On x86-32/64 only: do not use any FPU or SIMD registers for the ABI.
X86Softfloat = "x86-softfloat",
/// On x86-32/64 and S390x: do not use any FPU or SIMD registers for the ABI.
Softfloat = "softfloat", "x86-softfloat",
}
parse_error_type = "rustc abi";
@ -1460,6 +1460,7 @@ supported_targets! {
("powerpc64le-unknown-linux-gnu", powerpc64le_unknown_linux_gnu),
("powerpc64le-unknown-linux-musl", powerpc64le_unknown_linux_musl),
("s390x-unknown-linux-gnu", s390x_unknown_linux_gnu),
("s390x-unknown-none-softfloat", s390x_unknown_none_softfloat),
("s390x-unknown-linux-musl", s390x_unknown_linux_musl),
("sparc-unknown-linux-gnu", sparc_unknown_linux_gnu),
("sparc64-unknown-linux-gnu", sparc64_unknown_linux_gnu),
@ -3204,10 +3205,10 @@ impl Target {
Arch::X86,
"`x86-sse2` ABI is only valid for x86-32 targets"
),
RustcAbi::X86Softfloat => check_matches!(
RustcAbi::Softfloat => check_matches!(
self.arch,
Arch::X86 | Arch::X86_64,
"`x86-softfloat` ABI is only valid for x86 targets"
Arch::X86 | Arch::X86_64 | Arch::S390x,
"`softfloat` ABI is only valid for x86 and s390x targets"
),
}
}

View file

@ -22,7 +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);
base.rustc_abi = Some(RustcAbi::Softfloat);
// Turn off DWARF. This fixes an lld warning, "section name .debug_frame is longer than 8
// characters and will use a non-standard string table". That section will not be created if

View file

@ -0,0 +1,39 @@
use rustc_abi::{Align, Endian};
use crate::spec::{
Abi, Arch, Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, RustcAbi, SanitizerSet,
StackProbeType, Target, TargetMetadata, TargetOptions,
};
pub(crate) fn target() -> Target {
let opts = TargetOptions {
abi: Abi::SoftFloat,
cpu: "z10".into(),
endian: Endian::Big,
features: "+soft-float,-vector".into(),
linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
linker: Some("rust-lld".into()),
max_atomic_width: Some(128),
min_global_align: Some(Align::from_bits(16).unwrap()),
panic_strategy: PanicStrategy::Abort,
relocation_model: RelocModel::Static,
rustc_abi: Some(RustcAbi::Softfloat),
stack_probes: StackProbeType::Inline,
supported_sanitizers: SanitizerSet::KERNELADDRESS,
..Default::default()
};
Target {
llvm_target: "s390x-unknown-linux-gnu".into(),
metadata: TargetMetadata {
description: Some("S390x Linux".into()),
host_tools: Some(false),
std: Some(false),
tier: Some(2),
},
arch: Arch::S390x,
data_layout: "E-S64-m:e-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64".into(),
options: opts,
pointer_width: 64,
}
}

View file

@ -20,7 +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),
rustc_abi: Some(RustcAbi::Softfloat),
features: "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-avx,-avx2,+soft-float".into(),
supported_sanitizers: SanitizerSet::KCFI | SanitizerSet::KERNELADDRESS,
disable_redzone: true,

View file

@ -27,7 +27,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);
base.rustc_abi = Some(RustcAbi::Softfloat);
Target {
llvm_target: "x86_64-unknown-windows".into(),

View file

@ -863,7 +863,7 @@ const IBMZ_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
("miscellaneous-extensions-3", Stable, &[]),
("miscellaneous-extensions-4", Stable, &[]),
("nnp-assist", Stable, &["vector"]),
("soft-float", Forbidden { reason: "currently unsupported ABI-configuration feature" }, &[]),
("soft-float", Forbidden { reason: "unsupported ABI-configuration feature" }, &[]),
("transactional-execution", Unstable(sym::s390x_target_feature), &[]),
("vector", Stable, &[]),
("vector-enhancements-1", Stable, &["vector"]),
@ -1117,7 +1117,7 @@ impl Target {
incompatible: &["soft-float"],
}
}
Some(RustcAbi::X86Softfloat) => {
Some(RustcAbi::Softfloat) => {
// 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!
@ -1137,7 +1137,7 @@ impl Target {
incompatible: &["soft-float"],
}
}
Some(RustcAbi::X86Softfloat) => {
Some(RustcAbi::Softfloat) => {
// 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!
@ -1237,11 +1237,27 @@ impl Target {
}
}
Arch::S390x => {
// We don't currently support a softfloat target on this architecture.
// As usual, we have to reject swapping the `soft-float` target feature.
// The "vector" target feature does not affect the ABI for floats
// because the vector and float registers overlap.
FeatureConstraints { required: &[], incompatible: &["soft-float"] }
// Same as x86, We use our own ABI indicator here;
// LLVM does not have anything native and will switch ABI based
// on the soft-float target feature.
// Every case should require or forbid `soft-float`!
// The "vector" target feature may only be used without soft-float
// because the float and vector registers overlap and the
// standard s390x C ABI may pass vectors via these registers.
match self.rustc_abi {
None => {
// Default hardfloat ABI.
FeatureConstraints { required: &[], incompatible: &["soft-float"] }
}
Some(RustcAbi::Softfloat) => {
// Softfloat ABI, requires corresponding target feature.
// llvm will switch to soft-float ABI just based on this feature.
FeatureConstraints { required: &["soft-float"], incompatible: &["vector"] }
}
Some(r) => {
panic!("invalid Rust ABI for s390x: {r:?}");
}
}
}
Arch::Avr => {
// SRAM is minimum requirement for C/C++ in both avr-gcc and Clang,