From 69e279d529927431261dc8dca9d3544ca3c5c549 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 21 Nov 2025 10:15:19 +0000 Subject: [PATCH 1/3] Use rust rather than LLVM target features in the target spec This works better with non-LLVM codegen backends. --- compiler/rustc_codegen_gcc/src/gcc_util.rs | 14 +++-- compiler/rustc_codegen_llvm/src/llvm_util.rs | 55 ++++++++++--------- .../rustc_codegen_ssa/src/target_features.rs | 40 +++++++++++++- compiler/rustc_interface/src/util.rs | 4 +- .../src/spec/targets/aarch64_apple_ios.rs | 2 +- .../spec/targets/aarch64_apple_ios_macabi.rs | 2 +- .../src/spec/targets/aarch64_apple_ios_sim.rs | 2 +- .../src/spec/targets/aarch64_apple_tvos.rs | 2 +- .../spec/targets/aarch64_apple_tvos_sim.rs | 2 +- .../spec/targets/aarch64_apple_visionos.rs | 2 +- .../targets/aarch64_apple_visionos_sim.rs | 2 +- .../src/spec/targets/aarch64_apple_watchos.rs | 2 +- .../spec/targets/aarch64_apple_watchos_sim.rs | 2 +- .../spec/targets/aarch64_be_unknown_hermit.rs | 2 +- .../aarch64_be_unknown_none_softfloat.rs | 2 +- .../spec/targets/aarch64_kmc_solid_asp3.rs | 2 +- .../src/spec/targets/aarch64_linux_android.rs | 2 +- .../targets/aarch64_pc_windows_gnullvm.rs | 2 +- .../spec/targets/aarch64_pc_windows_msvc.rs | 2 +- .../spec/targets/aarch64_unknown_hermit.rs | 2 +- .../src/spec/targets/aarch64_unknown_none.rs | 2 +- .../targets/aarch64_unknown_none_softfloat.rs | 2 +- .../src/spec/targets/aarch64_unknown_nuttx.rs | 2 +- .../src/spec/targets/aarch64_unknown_teeos.rs | 2 +- .../spec/targets/aarch64_unknown_trusty.rs | 2 +- .../spec/targets/arm64_32_apple_watchos.rs | 2 +- .../src/spec/targets/arm64e_apple_ios.rs | 2 +- .../src/spec/targets/arm64e_apple_tvos.rs | 2 +- .../spec/targets/arm64ec_pc_windows_msvc.rs | 2 +- .../targets/x86_64_fortanix_unknown_sgx.rs | 2 +- .../src/spec/targets/x86_64_pc_windows_gnu.rs | 2 +- .../spec/targets/x86_64_pc_windows_gnullvm.rs | 2 +- .../spec/targets/x86_64_pc_windows_msvc.rs | 2 +- .../spec/targets/x86_64_unknown_fuchsia.rs | 2 +- .../src/spec/targets/x86_64_unknown_hermit.rs | 2 +- .../spec/targets/x86_64_uwp_windows_gnu.rs | 2 +- .../spec/targets/x86_64_uwp_windows_msvc.rs | 2 +- .../src/spec/targets/x86_64h_apple_darwin.rs | 2 +- 38 files changed, 110 insertions(+), 71 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/gcc_util.rs b/compiler/rustc_codegen_gcc/src/gcc_util.rs index e4e2dfdd5643b..c51763c3e7bb0 100644 --- a/compiler/rustc_codegen_gcc/src/gcc_util.rs +++ b/compiler/rustc_codegen_gcc/src/gcc_util.rs @@ -33,11 +33,7 @@ pub(crate) fn global_gcc_features(sess: &Session) -> Vec { // should be taken in cases like these. let mut features = vec![]; - // Features implied by an implicit or explicit `--target`. - features.extend(sess.target.features.split(',').filter(|v| !v.is_empty()).map(String::from)); - - // -Ctarget-features - target_features::flag_to_backend_features(sess, |feature, enable| { + let mut extend_backend_features = |feature: &str, enable: bool| { // We run through `to_gcc_features` when // passing requests down to GCC. This means that all in-language // features also work on the command line instead of having two @@ -48,7 +44,13 @@ pub(crate) fn global_gcc_features(sess: &Session) -> Vec { .flat_map(|feat| to_gcc_features(sess, feat).into_iter()) .map(|feature| if !enable { format!("-{}", feature) } else { feature.to_string() }), ); - }); + }; + + // Features implied by an implicit or explicit `--target`. + target_features::target_spec_to_backend_features(sess, &mut extend_backend_features); + + // -Ctarget-features + target_features::flag_to_backend_features(sess, extend_backend_features); gcc_features_by_flags(sess, &mut features); diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index b498448417f58..56f5836acfc34 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -626,6 +626,10 @@ pub(crate) fn target_cpu(sess: &Session) -> &str { /// The target features for compiler flags other than `-Ctarget-features`. fn llvm_features_by_flags(sess: &Session, features: &mut Vec) { + if wants_wasm_eh(sess) && sess.panic_strategy() == PanicStrategy::Unwind { + features.push("+exception-handling".into()); + } + target_features::retpoline_features_by_flags(sess, features); // -Zfixed-x18 @@ -691,36 +695,35 @@ pub(crate) fn global_llvm_features(sess: &Session, only_base_features: bool) -> Some(_) | None => {} }; - // Features implied by an implicit or explicit `--target`. - features.extend(sess.target.features.split(',').filter(|v| !v.is_empty()).map(String::from)); + let mut extend_backend_features = |feature: &str, enable: bool| { + let enable_disable = if enable { '+' } else { '-' }; + // We run through `to_llvm_features` when + // passing requests down to LLVM. This means that all in-language + // features also work on the command line instead of having two + // different names when the LLVM name and the Rust name differ. + let Some(llvm_feature) = to_llvm_features(sess, feature) else { return }; + + features.extend( + std::iter::once(format!("{}{}", enable_disable, llvm_feature.llvm_feature_name)).chain( + llvm_feature.dependencies.into_iter().filter_map(move |feat| { + match (enable, feat) { + (_, TargetFeatureFoldStrength::Both(f)) + | (true, TargetFeatureFoldStrength::EnableOnly(f)) => { + Some(format!("{enable_disable}{f}")) + } + _ => None, + } + }), + ), + ); + }; - if wants_wasm_eh(sess) && sess.panic_strategy() == PanicStrategy::Unwind { - features.push("+exception-handling".into()); - } + // Features implied by an implicit or explicit `--target`. + target_features::target_spec_to_backend_features(sess, &mut extend_backend_features); // -Ctarget-features if !only_base_features { - target_features::flag_to_backend_features(sess, |feature, enable| { - let enable_disable = if enable { '+' } else { '-' }; - // We run through `to_llvm_features` when - // passing requests down to LLVM. This means that all in-language - // features also work on the command line instead of having two - // different names when the LLVM name and the Rust name differ. - let Some(llvm_feature) = to_llvm_features(sess, feature) else { return }; - - features.extend( - std::iter::once(format!("{}{}", enable_disable, llvm_feature.llvm_feature_name)) - .chain(llvm_feature.dependencies.into_iter().filter_map(move |feat| { - match (enable, feat) { - (_, TargetFeatureFoldStrength::Both(f)) - | (true, TargetFeatureFoldStrength::EnableOnly(f)) => { - Some(format!("{enable_disable}{f}")) - } - _ => None, - } - })), - ) - }); + target_features::flag_to_backend_features(sess, extend_backend_features); } // We add this in the "base target" so that these show up in `sess.unstable_target_features`. diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index 3267eb1a15c73..6260952e89671 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -139,11 +139,12 @@ pub(crate) fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId, } } -/// Parse the value of `-Ctarget-feature`, also expanding implied features, -/// and call the closure for each (expanded) Rust feature. If the list contains +/// Parse the value of the target spec `features` field or `-Ctarget-feature`, also expanding +/// implied features, and call the closure for each (expanded) Rust feature. If the list contains /// a syntactically invalid item (not starting with `+`/`-`), the error callback is invoked. fn parse_rust_feature_flag<'a>( sess: &'a Session, + features: &'a str, err_callback: impl Fn(&'a str), mut callback: impl FnMut( /* base_feature */ &'a str, @@ -154,7 +155,7 @@ fn parse_rust_feature_flag<'a>( // A cache for the backwards implication map. let mut inverse_implied_features: Option>> = None; - for feature in sess.opts.cg.target_feature.split(',') { + for feature in features.split(',') { if let Some(base_feature) = feature.strip_prefix('+') { // Skip features that are not target features, but rustc features. if RUSTC_SPECIFIC_FEATURES.contains(&base_feature) { @@ -246,6 +247,7 @@ pub fn cfg_target_feature<'a, const N: usize>( // Add enabled and remove disabled features. parse_rust_feature_flag( sess, + &sess.opts.cg.target_feature, /* err_callback */ |feature| { sess.dcx().emit_warn(errors::UnknownCTargetFeaturePrefix { feature }); @@ -366,6 +368,37 @@ pub fn check_tied_features( None } +/// Translates the target spec `features` field into a backend target feature list. +/// +/// `extend_backend_features` extends the set of backend features (assumed to be in mutable state +/// accessible by that closure) to enable/disable the given Rust feature name. +pub fn target_spec_to_backend_features<'a>( + sess: &'a Session, + mut extend_backend_features: impl FnMut(&'a str, /* enable */ bool), +) { + // Compute implied features + let mut rust_features = vec![]; + parse_rust_feature_flag( + sess, + &sess.target.features, + /* err_callback */ + |feature| { + panic!("Target spec contains invalid feature {feature}"); + }, + |_base_feature, new_features, enable| { + // FIXME emit an error for unknown features like cfg_target_feature would for -Ctarget-feature + rust_features.extend( + UnordSet::from(new_features).to_sorted_stable_ord().iter().map(|&&s| (enable, s)), + ); + }, + ); + + // Add this to the backend features. + for (enable, feature) in rust_features { + extend_backend_features(feature, enable); + } +} + /// Translates the `-Ctarget-feature` flag into a backend target feature list. /// /// `extend_backend_features` extends the set of backend features (assumed to be in mutable state @@ -378,6 +411,7 @@ pub fn flag_to_backend_features<'a>( let mut rust_features = vec![]; parse_rust_feature_flag( sess, + &sess.opts.cg.target_feature, /* err_callback */ |_feature| { // Errors are already emitted in `cfg_target_feature`; avoid duplicates. diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 2e100a6215c09..60c7e5b6db037 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -370,8 +370,8 @@ impl CodegenBackend for DummyCodegenBackend { |feature| { // This is a standin for the list of features a backend is expected to enable. // It would be better to parse target.features instead and handle implied features, - // but target.features is a list of LLVM target features, not Rust target features. - // The dummy backend doesn't know the mapping between LLVM and Rust target features. + // but target.features doesn't contain features that are enabled by default for an + // architecture or target cpu. sess.target.abi_required_features().required.contains(&feature) }, ); diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs index e6c64add9ecb2..4b8356cc71ca6 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs @@ -16,7 +16,7 @@ pub(crate) fn target() -> Target { .into(), arch, options: TargetOptions { - features: "+neon,+fp-armv8,+apple-a7".into(), + features: "+neon,+apple-a7".into(), max_atomic_width: Some(128), supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs index 28d22e022c4e8..10d2dafb8db2b 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs @@ -16,7 +16,7 @@ pub(crate) fn target() -> Target { .into(), arch, options: TargetOptions { - features: "+neon,+fp-armv8,+apple-a12".into(), + features: "+neon,+apple-a12".into(), max_atomic_width: Some(128), supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::THREAD, ..opts diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs index 3b6a075588a85..351f8ef9eb9a5 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs @@ -16,7 +16,7 @@ pub(crate) fn target() -> Target { .into(), arch, options: TargetOptions { - features: "+neon,+fp-armv8,+apple-a7".into(), + features: "+neon,+apple-a7".into(), max_atomic_width: Some(128), supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs index b4e60f769b3bc..0916864ac4cc9 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs @@ -16,7 +16,7 @@ pub(crate) fn target() -> Target { .into(), arch, options: TargetOptions { - features: "+neon,+fp-armv8,+apple-a7".into(), + features: "+neon,+apple-a7".into(), max_atomic_width: Some(128), ..opts }, diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs index 0f2f73c50d0b2..2e18abdef3991 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs @@ -16,7 +16,7 @@ pub(crate) fn target() -> Target { .into(), arch, options: TargetOptions { - features: "+neon,+fp-armv8,+apple-a7".into(), + features: "+neon,+apple-a7".into(), max_atomic_width: Some(128), ..opts }, diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs index b7ddd58fbb323..b771b3ff10b99 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs @@ -16,7 +16,7 @@ pub(crate) fn target() -> Target { .into(), arch, options: TargetOptions { - features: "+neon,+fp-armv8,+apple-a16".into(), + features: "+neon,+apple-a16".into(), max_atomic_width: Some(128), supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD, ..opts diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs index 9ad313f149222..d4b4d94115b40 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs @@ -16,7 +16,7 @@ pub(crate) fn target() -> Target { .into(), arch, options: TargetOptions { - features: "+neon,+fp-armv8,+apple-a16".into(), + features: "+neon,+apple-a16".into(), max_atomic_width: Some(128), supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD, ..opts diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs index f0a5a616a6d2d..9f0a24ddd334d 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs @@ -16,7 +16,7 @@ pub(crate) fn target() -> Target { .into(), arch, options: TargetOptions { - features: "+v8a,+neon,+fp-armv8,+apple-a7".into(), + features: "+v8a,+neon,+apple-a7".into(), max_atomic_width: Some(128), dynamic_linking: false, position_independent_executables: true, diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs index db73687a715fc..fabf01d641c37 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs @@ -16,7 +16,7 @@ pub(crate) fn target() -> Target { .into(), arch, options: TargetOptions { - features: "+neon,+fp-armv8,+apple-a7".into(), + features: "+neon,+apple-a7".into(), max_atomic_width: Some(128), ..opts }, diff --git a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_hermit.rs b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_hermit.rs index 78ae0f55bb42e..7b63261330732 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_hermit.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_hermit.rs @@ -15,7 +15,7 @@ pub(crate) fn target() -> Target { arch: Arch::AArch64, data_layout: "E-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), options: TargetOptions { - features: "+v8a,+strict-align,+neon,+fp-armv8".into(), + features: "+v8a,+strict-align,+neon".into(), max_atomic_width: Some(128), stack_probes: StackProbeType::Inline, endian: Endian::Big, diff --git a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_none_softfloat.rs b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_none_softfloat.rs index 3b899b13d6d00..07512c01dc4a8 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_none_softfloat.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_none_softfloat.rs @@ -17,7 +17,7 @@ pub(crate) fn target() -> Target { abi: Abi::SoftFloat, linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), linker: Some("rust-lld".into()), - features: "+v8a,+strict-align,-neon,-fp-armv8".into(), + features: "+v8a,+strict-align,-neon".into(), relocation_model: RelocModel::Static, disable_redzone: true, max_atomic_width: Some(128), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_kmc_solid_asp3.rs b/compiler/rustc_target/src/spec/targets/aarch64_kmc_solid_asp3.rs index 77ed9a6b82c1a..b7709bd01340a 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_kmc_solid_asp3.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_kmc_solid_asp3.rs @@ -15,7 +15,7 @@ pub(crate) fn target() -> Target { arch: Arch::AArch64, options: TargetOptions { linker: Some("aarch64-kmc-elf-gcc".into()), - features: "+v8a,+neon,+fp-armv8".into(), + features: "+v8a,+neon".into(), relocation_model: RelocModel::Static, disable_redzone: true, max_atomic_width: Some(128), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs b/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs index 2bee1cf70b45d..3b158c13521ea 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs @@ -21,7 +21,7 @@ pub(crate) fn target() -> Target { max_atomic_width: Some(128), // As documented in https://developer.android.com/ndk/guides/cpu-features.html // the neon (ASIMD) and FP must exist on all android aarch64 targets. - features: "+v8a,+neon,+fp-armv8".into(), + features: "+v8a,+neon".into(), // the AAPCS64 expects use of non-leaf frame pointers per // https://github.com/ARM-software/abi-aa/blob/4492d1570eb70c8fd146623e0db65b2d241f12e7/aapcs64/aapcs64.rst#the-frame-pointer // and we tend to encounter interesting bugs in AArch64 unwinding code if we do not diff --git a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs index 7b3a234cd9e8e..fc1aa7241c6c9 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs @@ -3,7 +3,7 @@ use crate::spec::{Arch, FramePointer, Target, TargetMetadata, base}; pub(crate) fn target() -> Target { let mut base = base::windows_gnullvm::opts(); base.max_atomic_width = Some(128); - base.features = "+v8a,+neon,+fp-armv8".into(); + base.features = "+v8a,+neon".into(); base.linker = Some("aarch64-w64-mingw32-clang".into()); // Microsoft recommends enabling frame pointers on Arm64 Windows. diff --git a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs index 3453f1d6101b9..0d06bec21f4a4 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs @@ -3,7 +3,7 @@ use crate::spec::{Arch, FramePointer, Target, TargetMetadata, base}; pub(crate) fn target() -> Target { let mut base = base::windows_msvc::opts(); base.max_atomic_width = Some(128); - base.features = "+v8a,+neon,+fp-armv8".into(); + base.features = "+v8a,+neon".into(); // Microsoft recommends enabling frame pointers on Arm64 Windows. // From https://learn.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions?view=msvc-170#integer-registers diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_hermit.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_hermit.rs index 2cf5c2519d562..4ecbb73f7a4ec 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_hermit.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_hermit.rs @@ -13,7 +13,7 @@ pub(crate) fn target() -> Target { arch: Arch::AArch64, data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), options: TargetOptions { - features: "+v8a,+strict-align,+neon,+fp-armv8".into(), + features: "+v8a,+strict-align,+neon".into(), max_atomic_width: Some(128), stack_probes: StackProbeType::Inline, ..base::hermit::opts() diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs index ffb136366acc6..b6bc261cd0dfb 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs @@ -20,7 +20,7 @@ pub(crate) fn target() -> Target { LinkerFlavor::Gnu(Cc::No, Lld::No), &["--fix-cortex-a53-843419"], ), - features: "+v8a,+strict-align,+neon,+fp-armv8".into(), + features: "+v8a,+strict-align,+neon".into(), supported_sanitizers: SanitizerSet::KCFI | SanitizerSet::KERNELADDRESS, relocation_model: RelocModel::Static, disable_redzone: true, diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs index c0fd021497b65..8e1484774cdbd 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs @@ -16,7 +16,7 @@ pub(crate) fn target() -> Target { abi: Abi::SoftFloat, linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), linker: Some("rust-lld".into()), - features: "+v8a,+strict-align,-neon,-fp-armv8".into(), + features: "+v8a,+strict-align,-neon".into(), relocation_model: RelocModel::Static, disable_redzone: true, max_atomic_width: Some(128), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_nuttx.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nuttx.rs index b8618050074d3..19b7ebe036747 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_nuttx.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nuttx.rs @@ -20,7 +20,7 @@ pub(crate) fn target() -> Target { LinkerFlavor::Gnu(Cc::No, Lld::No), &["--fix-cortex-a53-843419"], ), - features: "+v8a,+strict-align,+neon,+fp-armv8".into(), + features: "+v8a,+strict-align,+neon".into(), supported_sanitizers: SanitizerSet::KCFI | SanitizerSet::KERNELADDRESS, relocation_model: RelocModel::Static, disable_redzone: true, diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_teeos.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_teeos.rs index 009f027ca24f5..b8f1bf1ca1a98 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_teeos.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_teeos.rs @@ -2,7 +2,7 @@ use crate::spec::{Arch, StackProbeType, Target, TargetMetadata, base}; pub(crate) fn target() -> Target { let mut base = base::teeos::opts(); - base.features = "+strict-align,+neon,+fp-armv8".into(); + base.features = "+strict-align,+neon".into(); base.max_atomic_width = Some(128); base.stack_probes = StackProbeType::Inline; diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_trusty.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_trusty.rs index 7dfa29787c86f..bacc99c64f161 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_trusty.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_trusty.rs @@ -18,7 +18,7 @@ pub(crate) fn target() -> Target { data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), arch: Arch::AArch64, options: TargetOptions { - features: "+neon,+fp-armv8,+reserve-x18".into(), + features: "+neon,+reserve-x18".into(), executables: true, max_atomic_width: Some(128), panic_strategy: PanicStrategy::Abort, diff --git a/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs b/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs index dab8cd157d2bd..a9fe6bf0efd25 100644 --- a/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs +++ b/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs @@ -16,7 +16,7 @@ pub(crate) fn target() -> Target { "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32".into(), arch, options: TargetOptions { - features: "+v8a,+neon,+fp-armv8,+apple-a7".into(), + features: "+v8a,+neon,+apple-a7".into(), max_atomic_width: Some(128), dynamic_linking: false, position_independent_executables: true, diff --git a/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs b/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs index 4ee4a16ab7476..396f0c347a086 100644 --- a/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs +++ b/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs @@ -16,7 +16,7 @@ pub(crate) fn target() -> Target { .into(), arch, options: TargetOptions { - features: "+neon,+fp-armv8,+apple-a12,+v8.3a,+pauth".into(), + features: "+neon,+apple-a12,+v8.3a,+paca,+pacg".into(), max_atomic_width: Some(128), supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD, ..opts diff --git a/compiler/rustc_target/src/spec/targets/arm64e_apple_tvos.rs b/compiler/rustc_target/src/spec/targets/arm64e_apple_tvos.rs index c09591be95f96..3cd120567a33f 100644 --- a/compiler/rustc_target/src/spec/targets/arm64e_apple_tvos.rs +++ b/compiler/rustc_target/src/spec/targets/arm64e_apple_tvos.rs @@ -16,7 +16,7 @@ pub(crate) fn target() -> Target { .into(), arch, options: TargetOptions { - features: "+neon,+fp-armv8,+apple-a12,+v8.3a,+pauth".into(), + features: "+neon,+apple-a12,+v8.3a,+paca,+pacg".into(), max_atomic_width: Some(128), ..opts }, diff --git a/compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs index aa31f53bf0fcb..b333f2891626c 100644 --- a/compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs @@ -5,7 +5,7 @@ use crate::spec::{ pub(crate) fn target() -> Target { let mut base = base::windows_msvc::opts(); base.max_atomic_width = Some(128); - base.features = "+v8a,+neon,+fp-armv8".into(); + base.features = "+v8a,+neon".into(); add_link_args( &mut base.late_link_args, LinkerFlavor::Msvc(Lld::No), diff --git a/compiler/rustc_target/src/spec/targets/x86_64_fortanix_unknown_sgx.rs b/compiler/rustc_target/src/spec/targets/x86_64_fortanix_unknown_sgx.rs index 290087d8cef66..cd074a468fd60 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_fortanix_unknown_sgx.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_fortanix_unknown_sgx.rs @@ -66,7 +66,7 @@ pub(crate) fn target() -> Target { max_atomic_width: Some(64), cpu: "x86-64".into(), plt_by_default: false, - features: "+rdrnd,+rdseed,+lvi-cfi,+lvi-load-hardening".into(), + features: "+rdrand,+rdseed,+lvi-cfi,+lvi-load-hardening".into(), llvm_args: cvs!["--x86-experimental-lvi-inline-asm-hardening"], position_independent_executables: true, pre_link_args, diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnu.rs index ba0882b8693b1..995bfd07071e4 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnu.rs @@ -3,7 +3,7 @@ use crate::spec::{Arch, Cc, LinkerFlavor, Lld, Target, TargetMetadata, base}; pub(crate) fn target() -> Target { let mut base = base::windows_gnu::opts(); base.cpu = "x86-64".into(); - base.features = "+cx16,+sse3,+sahf".into(); + base.features = "+cmpxchg16b,+sse3,+lahfsahf".into(); base.plt_by_default = false; // Use high-entropy 64 bit address space for ASLR base.add_pre_link_args( diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnullvm.rs index 0606d4508badc..de3c960bced9c 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnullvm.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnullvm.rs @@ -3,7 +3,7 @@ use crate::spec::{Arch, Cc, LinkerFlavor, Lld, Target, TargetMetadata, base}; pub(crate) fn target() -> Target { let mut base = base::windows_gnullvm::opts(); base.cpu = "x86-64".into(); - base.features = "+cx16,+sse3,+sahf".into(); + base.features = "+cmpxchg16b,+sse3,+lahfsahf".into(); base.plt_by_default = false; base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); base.max_atomic_width = Some(128); diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs index 1eecec8e6bde7..20b6e0701bffa 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs @@ -3,7 +3,7 @@ use crate::spec::{Arch, SanitizerSet, Target, TargetMetadata, base}; pub(crate) fn target() -> Target { let mut base = base::windows_msvc::opts(); base.cpu = "x86-64".into(); - base.features = "+cx16,+sse3,+sahf".into(); + base.features = "+cmpxchg16b,+sse3,+lahfsahf".into(); base.plt_by_default = false; base.max_atomic_width = Some(128); base.supported_sanitizers = SanitizerSet::ADDRESS; diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs index 0d92097ad456e..dbff5e30828a9 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs @@ -6,7 +6,7 @@ pub(crate) fn target() -> Target { base.plt_by_default = false; // See https://fuchsia.dev/fuchsia-src/contribute/governance/rfcs/0073_x86_64_platform_requirement, // which corresponds to x86-64-v2. - base.features = "+cx16,+sahf,+popcnt,+sse3,+sse4.1,+sse4.2,+ssse3".into(); + base.features = "+cmpxchg16b,+lahfsahf,+popcnt,+sse3,+sse4.1,+sse4.2,+ssse3".into(); base.max_atomic_width = Some(128); base.stack_probes = StackProbeType::Inline; base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::LEAK; diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_hermit.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_hermit.rs index ee191ac95ae71..d6630261e2343 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_hermit.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_hermit.rs @@ -15,7 +15,7 @@ pub(crate) fn target() -> Target { "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), options: TargetOptions { cpu: "x86-64".into(), - features: "+rdrnd,+rdseed".into(), + features: "+rdrand,+rdseed".into(), plt_by_default: false, max_atomic_width: Some(64), stack_probes: StackProbeType::Inline, diff --git a/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_gnu.rs index 96d1bd2764c8e..9d53ce0e1c803 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_gnu.rs @@ -3,7 +3,7 @@ use crate::spec::{Arch, Cc, LinkerFlavor, Lld, Target, TargetMetadata, base}; pub(crate) fn target() -> Target { let mut base = base::windows_uwp_gnu::opts(); base.cpu = "x86-64".into(); - base.features = "+cx16,+sse3,+sahf".into(); + base.features = "+cmpxchg16b,+sse3,+lahfsahf".into(); base.plt_by_default = false; // Use high-entropy 64 bit address space for ASLR base.add_pre_link_args( diff --git a/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_msvc.rs index 3be6abd3d9757..003bcf1e0ddff 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_msvc.rs @@ -3,7 +3,7 @@ use crate::spec::{Arch, Target, TargetMetadata, base}; pub(crate) fn target() -> Target { let mut base = base::windows_uwp_msvc::opts(); base.cpu = "x86-64".into(); - base.features = "+cx16,+sse3,+sahf".into(); + base.features = "+cmpxchg16b,+sse3,+lahfsahf".into(); base.plt_by_default = false; base.max_atomic_width = Some(128); diff --git a/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs index adc87378fc7ef..7f1fe485aa150 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs @@ -17,7 +17,7 @@ pub(crate) fn target() -> Target { // It would be nice if this were not the case, but fixing it seems tricky // (and given that the main use-case for this target is for use in universal // binaries, probably not that important). - opts.features = "-rdrnd,-aes,-pclmul,-rtm,-fsgsbase".into(); + opts.features = "-rdrand,-aes,-pclmulqdq,-rtm,-fsgsbase".into(); // Double-check that the `cpu` is what we expect (if it's not the list above // may need updating). assert_eq!( From 445e11e6760731a08cc50b3adbb4cb94bd04c61a Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 21 Nov 2025 14:08:10 +0000 Subject: [PATCH 2/3] Add entry for lahfsahf to GCC target feature mapping --- compiler/rustc_codegen_gcc/src/gcc_util.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_codegen_gcc/src/gcc_util.rs b/compiler/rustc_codegen_gcc/src/gcc_util.rs index c51763c3e7bb0..330b5ff6828d5 100644 --- a/compiler/rustc_codegen_gcc/src/gcc_util.rs +++ b/compiler/rustc_codegen_gcc/src/gcc_util.rs @@ -68,6 +68,7 @@ pub fn to_gcc_features<'a>(sess: &Session, s: &'a str) -> SmallVec<[&'a str; 2]> (&Arch::X86 | &Arch::X86_64, "rdrand") => smallvec!["rdrnd"], (&Arch::X86 | &Arch::X86_64, "bmi1") => smallvec!["bmi"], (&Arch::X86 | &Arch::X86_64, "cmpxchg16b") => smallvec!["cx16"], + (&Arch::X86 | &Arch::X86_64, "lahfsahf") => smallvec!["sahf"], (&Arch::X86 | &Arch::X86_64, "avx512vaes") => smallvec!["vaes"], (&Arch::X86 | &Arch::X86_64, "avx512gfni") => smallvec!["gfni"], (&Arch::X86 | &Arch::X86_64, "avx512vpclmulqdq") => smallvec!["vpclmulqdq"], From f44fbb336aed396534f66899bb0f73f2076811a4 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 21 Nov 2025 14:11:05 +0000 Subject: [PATCH 3/3] Update comment --- compiler/rustc_target/src/spec/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 1a71e344276a8..a8fc356c362c4 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -2248,8 +2248,8 @@ pub struct TargetOptions { pub need_explicit_cpu: bool, /// Default target features to pass to LLVM. These features overwrite /// `-Ctarget-cpu` but can be overwritten with `-Ctarget-features`. - /// Corresponds to `llc -mattr=$features`. - /// Note that these are LLVM feature names, not Rust feature names! + /// Corresponds to `llc -mattr=$llvm_features` where `$llvm_features` is the result of mapping + /// the Rust features in this field to LLVM features. /// /// Generally it is a bad idea to use negative target features because they often interact very /// poorly with how `-Ctarget-cpu` works. Instead, try to use a lower "base CPU" and enable the