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 88655c9b22a61..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,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 }, 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..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,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 }, 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..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,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 }, } diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index b009c42eb2302..dc3d85120a422 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -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"]), @@ -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 ]; @@ -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 @@ -1172,6 +1183,7 @@ impl Target { // LLVM handles the rest. FeatureConstraints { required: &["soft-float"], incompatible: &[] } } + _ => unreachable!(), } } Arch::X86_64 => { @@ -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 => { @@ -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 => { @@ -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"], + } } + _ => 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.