Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions compiler/rustc_target/src/spec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1006,6 +1006,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 PowerPC only: build for SPE.
PowerPcSpe = "powerpc-spe",
/// On x86-32/64, aarch64, and S390x: do not use any FPU or SIMD registers for the ABI.
Softfloat = "softfloat", "x86-softfloat",
}
Expand Down Expand Up @@ -3445,13 +3447,15 @@ impl Target {
"`llvm_abiname` is unused on PowerPC"
);
check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on PowerPC");
check!(self.rustc_abi.is_none(), "`rustc_abi` is unused on PowerPC");
// FIXME: Check that `target_abi` matches the actually configured ABI (with or
// without SPE).
check_matches!(
(&self.rustc_abi, &self.cfg_abi),
(Some(RustcAbi::PowerPcSpe), CfgAbi::Spe)
| (None, CfgAbi::Unspecified | CfgAbi::Other(_)),
"invalid PowerPC Rust-specific ABI and `cfg(target_abi)` combination:\n\
Rust-specific ABI: {:?}\n\
cfg(target_abi): {}",
self.rustc_abi,
self.cfg_abi,
CfgAbi::Spe | CfgAbi::Unspecified | CfgAbi::Other(_),
"invalid `target_abi` for PowerPC"
);
}
Arch::PowerPC64 => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use rustc_abi::Endian;

use crate::spec::{
Arch, Cc, CfgAbi, LinkerFlavor, Lld, StackProbeType, Target, TargetMetadata, TargetOptions,
base,
Arch, Cc, CfgAbi, LinkerFlavor, Lld, RustcAbi, StackProbeType, Target, TargetMetadata,
TargetOptions, base,
};

pub(crate) fn target() -> Target {
Expand All @@ -24,8 +24,9 @@ pub(crate) fn target() -> Target {
arch: Arch::PowerPC,
options: TargetOptions {
cfg_abi: CfgAbi::Spe,
rustc_abi: Some(RustcAbi::PowerPcSpe),
endian: Endian::Big,
features: "+secure-plt,+msync".into(),
features: "+secure-plt,+msync,+spe".into(),
mcount: "_mcount".into(),
..base
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use rustc_abi::Endian;

use crate::spec::{
Arch, Cc, CfgAbi, LinkerFlavor, Lld, StackProbeType, Target, TargetMetadata, TargetOptions,
base,
Arch, Cc, CfgAbi, LinkerFlavor, Lld, RustcAbi, StackProbeType, Target, TargetMetadata,
TargetOptions, base,
};

pub(crate) fn target() -> Target {
Expand All @@ -24,8 +24,9 @@ pub(crate) fn target() -> Target {
arch: Arch::PowerPC,
options: TargetOptions {
cfg_abi: CfgAbi::Spe,
rustc_abi: Some(RustcAbi::PowerPcSpe),
endian: Endian::Big,
features: "+msync".into(),
features: "+msync,+spe".into(),
mcount: "_mcount".into(),
..base
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use rustc_abi::Endian;

use crate::spec::{
Arch, Cc, CfgAbi, LinkerFlavor, Lld, StackProbeType, Target, TargetMetadata, TargetOptions,
base,
Arch, Cc, CfgAbi, LinkerFlavor, Lld, RustcAbi, StackProbeType, Target, TargetMetadata,
TargetOptions, base,
};

pub(crate) fn target() -> Target {
Expand All @@ -24,9 +24,10 @@ pub(crate) fn target() -> Target {
arch: Arch::PowerPC,
options: TargetOptions {
cfg_abi: CfgAbi::Spe,
rustc_abi: Some(RustcAbi::PowerPcSpe),
endian: Endian::Big,
// feature msync would disable instruction 'fsync' which is not supported by fsl_p1p2
features: "+secure-plt,+msync".into(),
features: "+secure-plt,+msync,+spe".into(),
..base
},
}
Expand Down
54 changes: 45 additions & 9 deletions compiler/rustc_target/src/target_features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,16 @@ const HEXAGON_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
static POWERPC_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
// tidy-alphabetical-start
("altivec", Unstable(sym::powerpc_target_feature), &[]),
(
"efpu2",
Forbidden { reason: "unsupported ABI-configuration feature", hard_error: false },
&[],
),
(
"hard-float",
Forbidden { reason: "unsupported ABI-configuration feature", hard_error: false },
&[],
),
("msync", Unstable(sym::powerpc_target_feature), &[]),
("partword-atomics", Unstable(sym::powerpc_target_feature), &[]),
("power8-altivec", Unstable(sym::powerpc_target_feature), &["altivec"]),
Expand All @@ -581,6 +591,7 @@ static POWERPC_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
("power9-vector", Unstable(sym::powerpc_target_feature), &["power8-vector", "power9-altivec"]),
("power10-vector", Unstable(sym::powerpc_target_feature), &["power9-vector"]),
("quadword-atomics", Unstable(sym::powerpc_target_feature), &[]),
("spe", Forbidden { reason: "unsupported ABI-configuration feature", hard_error: false }, &[]),
("vsx", Unstable(sym::powerpc_target_feature), &["altivec"]),
// tidy-alphabetical-end
];
Expand Down Expand Up @@ -1136,12 +1147,12 @@ impl Target {
/// the first list contains target features that must be enabled for ABI reasons,
/// and the second list contains target feature that must be disabled for ABI reasons.
///
/// These features are automatically appended to whatever the target spec sets as default
/// features for the target.
/// These features are checked against the target features reported by LLVM based on
/// `-Ctarget-cpu` and `-Ctarget-features`. Constraint violations result in a warning.
///
/// All features enabled/disabled via `-Ctarget-features` and `#[target_features]` are checked
/// against this. We also check any implied features, based on the information above. If LLVM
/// implicitly enables more implied features than we do, that could bypass this check!
/// We also check features enabled via `#[target_features]` (and here, constraint violations
/// emit a hard error), including features enabled indirectly via implications -- but if LLVM
/// considers more features to be implied than we do, that could bypass this check!
pub fn abi_required_features(&self) -> FeatureConstraints {
const NOTHING: FeatureConstraints = FeatureConstraints { required: &[], incompatible: &[] };
// Some architectures don't have a clean explicit ABI designation; instead, the ABI is
Expand Down Expand Up @@ -1172,6 +1183,7 @@ impl Target {
// LLVM handles the rest.
FeatureConstraints { required: &["soft-float"], incompatible: &[] }
}
_ => unreachable!(),
}
}
Arch::X86_64 => {
Expand All @@ -1192,7 +1204,7 @@ impl Target {
// LLVM handles the rest.
FeatureConstraints { required: &["soft-float"], incompatible: &[] }
}
Some(r) => panic!("invalid Rust ABI for x86_64: {r:?}"),
_ => unreachable!(),
}
}
Arch::Arm => {
Expand Down Expand Up @@ -1229,7 +1241,7 @@ impl Target {
// `FeatureConstraints` uses Rust feature names, hence only "neon" shows up.
FeatureConstraints { required: &["neon"], incompatible: &[] }
}
Some(r) => panic!("invalid Rust ABI for aarch64: {r:?}"),
_ => unreachable!(),
}
}
Arch::RiscV32 | Arch::RiscV64 => {
Expand Down Expand Up @@ -1306,12 +1318,36 @@ impl Target {
// 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:?}");
_ => unreachable!(),
}
}
Arch::PowerPC => {
// The main ABI-relevant target features are "hard-float" and "spe". We use our own
// ABI indicator here.
match self.rustc_abi {
None => {
// Default hardfloat ABI.
FeatureConstraints { required: &["hard-float"], incompatible: &["spe"] }
}
Some(RustcAbi::PowerPcSpe) => {
// We reject "efpu2" since that seems to *disable* the f64 registers in
// LLVM, which seems likely to affect the ABI.
FeatureConstraints {
required: &["hard-float", "spe"],
incompatible: &["efpu2"],
Copy link
Copy Markdown
Member Author

@RalfJung RalfJung May 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure what to do with efpu2. LLVM has this:

      // EFPU2 APU only supports f32
      if (!Subtarget.hasEFPU2())
        addRegisterClass(MVT::f64, &PPC::SPERCRegClass);

So looks like toggling that target feature will affect the ABI of f64 values. If that is correct, we have to force it always-on or always-off.

it looks like efpu2 implies spe but not the other way around. Great negative feature you have there LLVM, adding a feature removes a register class...

View changes since the review

}
}
_ => unreachable!(),
}
}
Arch::PowerPC64 => {
// There's no SPE for PowerPC64, and we currently don't support any soft-float
// targets. (If we ever add one, we need to match on `RustcAbi::Softfloat` similar
// to other targets above.)
FeatureConstraints { required: &["hard-float"], incompatible: &["spe"] }
}
Arch::Avr => {
// We only support one ABI on AVR at the moment.
// SRAM is minimum requirement for C/C++ in both avr-gcc and Clang,
// and backends of them only support assembly for devices have no SRAM.
// See the discussion in https://github.com/rust-lang/rust/pull/146900 for more.
Expand Down
Loading