From a72f0b03c86e5fd7763396e51ebaf1f5609c73f3 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 28 May 2026 23:53:17 +0200 Subject: [PATCH 1/3] powerpc: warn against incorrect values for ABI-relevant target features --- compiler/rustc_target/src/target_features.rs | 25 ++++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index b009c42eb2302..e63b05592f80f 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -572,6 +572,11 @@ const HEXAGON_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ static POWERPC_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-start ("altivec", Unstable(sym::powerpc_target_feature), &[]), + ( + "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"]), @@ -581,6 +586,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 ]; @@ -1136,12 +1142,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 @@ -1311,7 +1317,16 @@ impl Target { } } } + Arch::PowerPC | Arch::PowerPC64 => { + // The main ABI-relevant target features are "hard-float" and "spe". There is also + // "efpu2" but that seems only relevant when "spe" is enabled. If we ever add a + // soft-float variant, it looks like we have to mark "altivec" as incompatible -- + // unlike other targets, it looks like enabling "altivec" will have LLVM use + // different registers for float types even if "hard-float" is off. + 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. From ba1d939227b6cac688c3befc95a6bba3d4b141f7 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sun, 21 Sep 2025 14:39:07 +0900 Subject: [PATCH 2/3] rustc_target: Use +spe for powerpcspe targets --- .../src/spec/targets/powerpc_unknown_linux_gnuspe.rs | 2 +- .../src/spec/targets/powerpc_unknown_linux_muslspe.rs | 2 +- .../rustc_target/src/spec/targets/powerpc_wrs_vxworks_spe.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnuspe.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnuspe.rs index 88655c9b22a61..cafb7037c0544 100644 --- a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnuspe.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnuspe.rs @@ -25,7 +25,7 @@ pub(crate) fn target() -> Target { options: TargetOptions { cfg_abi: CfgAbi::Spe, endian: Endian::Big, - features: "+secure-plt,+msync".into(), + features: "+secure-plt,+msync,+spe".into(), mcount: "_mcount".into(), ..base }, diff --git a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_muslspe.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_muslspe.rs index c61ceab6bd394..c9427adf8dce5 100644 --- a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_muslspe.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_muslspe.rs @@ -25,7 +25,7 @@ pub(crate) fn target() -> Target { options: TargetOptions { cfg_abi: CfgAbi::Spe, endian: Endian::Big, - features: "+msync".into(), + features: "+msync,+spe".into(), mcount: "_mcount".into(), ..base }, diff --git a/compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks_spe.rs b/compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks_spe.rs index 8f7aaa025bcc1..0a9760d6d1bd7 100644 --- a/compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks_spe.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks_spe.rs @@ -26,7 +26,7 @@ pub(crate) fn target() -> Target { cfg_abi: CfgAbi::Spe, 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 }, } From af52abf7de980152382e7f13fe2566df79366592 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 30 May 2026 10:40:56 +0200 Subject: [PATCH 3/3] explicitly track SPE ABI for PowerPC --- compiler/rustc_target/src/spec/mod.rs | 14 ++++--- .../targets/powerpc_unknown_linux_gnuspe.rs | 5 ++- .../targets/powerpc_unknown_linux_muslspe.rs | 5 ++- .../spec/targets/powerpc_wrs_vxworks_spe.rs | 5 ++- compiler/rustc_target/src/target_features.rs | 41 ++++++++++++++----- 5 files changed, 49 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index d6a9e27c46553..6771591124caa 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -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", } @@ -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 => { diff --git a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnuspe.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnuspe.rs index cafb7037c0544..d2d374d608595 100644 --- a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnuspe.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnuspe.rs @@ -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 { @@ -24,6 +24,7 @@ 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,+spe".into(), mcount: "_mcount".into(), diff --git a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_muslspe.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_muslspe.rs index c9427adf8dce5..e7b6593a7dc54 100644 --- a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_muslspe.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_muslspe.rs @@ -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 { @@ -24,6 +24,7 @@ pub(crate) fn target() -> Target { arch: Arch::PowerPC, options: TargetOptions { cfg_abi: CfgAbi::Spe, + rustc_abi: Some(RustcAbi::PowerPcSpe), endian: Endian::Big, features: "+msync,+spe".into(), mcount: "_mcount".into(), diff --git a/compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks_spe.rs b/compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks_spe.rs index 0a9760d6d1bd7..8be9ed4c2aceb 100644 --- a/compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks_spe.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks_spe.rs @@ -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 { @@ -24,6 +24,7 @@ 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,+spe".into(), diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index e63b05592f80f..dc3d85120a422 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -572,6 +572,11 @@ 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 }, @@ -1178,6 +1183,7 @@ impl Target { // LLVM handles the rest. FeatureConstraints { required: &["soft-float"], incompatible: &[] } } + _ => unreachable!(), } } Arch::X86_64 => { @@ -1198,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 => { @@ -1235,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 => { @@ -1312,17 +1318,32 @@ 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"], + } + } + _ => unreachable!(), } } - Arch::PowerPC | Arch::PowerPC64 => { - // The main ABI-relevant target features are "hard-float" and "spe". There is also - // "efpu2" but that seems only relevant when "spe" is enabled. If we ever add a - // soft-float variant, it looks like we have to mark "altivec" as incompatible -- - // unlike other targets, it looks like enabling "altivec" will have LLVM use - // different registers for float types even if "hard-float" is off. + 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 => {