diff options
| author | bors <bors@rust-lang.org> | 2024-12-13 19:43:00 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-12-13 19:43:00 +0000 |
| commit | 327c7ee4367ea587a49eff1d4715f462ab6db5f0 (patch) | |
| tree | 4bbfe65a25a371bb14a9dc73fbc61086fe19d288 /compiler/rustc_codegen_ssa | |
| parent | e217f949179d7337d0cae303881449360937211f (diff) | |
| parent | 60eca2c5758a736559a60b7552833d20b0895763 (diff) | |
| download | rust-327c7ee4367ea587a49eff1d4715f462ab6db5f0.tar.gz rust-327c7ee4367ea587a49eff1d4715f462ab6db5f0.zip | |
Auto merge of #133099 - RalfJung:forbidden-hardfloat-features, r=workingjubilee
forbid toggling x87 and fpregs on hard-float targets Part of https://github.com/rust-lang/rust/issues/116344, follow-up to https://github.com/rust-lang/rust/pull/129884: The `x87` target feature on x86 and the `fpregs` target feature on ARM must not be disabled on a hardfloat target, as that would change the float ABI. However, *enabling* `fpregs` on ARM is [explicitly requested](https://github.com/rust-lang/rust/issues/130988) as it seems to be useful. Therefore, we need to refine the distinction of "forbidden" target features and "allowed" target features: all (un)stable target features can determine on a per-target basis whether they should be allowed to be toggled or not. `fpregs` then checks whether the current target has the `soft-float` feature, and if yes, `fpregs` is permitted -- otherwise, it is not. (Same for `x87` on x86). Also fixes https://github.com/rust-lang/rust/issues/132351. Since `fpregs` and `x87` can be enabled on some builds and disabled on others, it would make sense that one can query it via `cfg`. Therefore, I made them behave in `cfg` like any other unstable target feature. The first commit prepares the infrastructure, but does not change behavior. The second commit then wires up `fpregs` and `x87` with that new infrastructure. r? `@workingjubilee`
Diffstat (limited to 'compiler/rustc_codegen_ssa')
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/target_features.rs | 53 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/traits/backend.rs | 4 |
2 files changed, 26 insertions, 31 deletions
diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index eee7cc75400..fa600ec7166 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -11,7 +11,7 @@ use rustc_middle::ty::TyCtxt; use rustc_session::parse::feature_err; use rustc_span::Span; use rustc_span::symbol::{Symbol, sym}; -use rustc_target::target_features::{self, Stability}; +use rustc_target::target_features; use crate::errors; @@ -20,7 +20,7 @@ use crate::errors; pub(crate) fn from_target_feature_attr( tcx: TyCtxt<'_>, attr: &ast::Attribute, - rust_target_features: &UnordMap<String, target_features::Stability>, + rust_target_features: &UnordMap<String, target_features::StabilityComputed>, target_features: &mut Vec<TargetFeature>, ) { let Some(list) = attr.meta_item_list() else { return }; @@ -63,32 +63,24 @@ pub(crate) fn from_target_feature_attr( return None; }; - // Only allow target features whose feature gates have been enabled. - let allowed = match stability { - Stability::Forbidden { .. } => false, - Stability::Stable => true, - Stability::Unstable(name) => rust_features.enabled(*name), - }; - if !allowed { - match stability { - Stability::Stable => unreachable!(), - &Stability::Unstable(lang_feature_name) => { - feature_err( - &tcx.sess, - lang_feature_name, - item.span(), - format!("the target feature `{feature}` is currently unstable"), - ) - .emit(); - } - Stability::Forbidden { reason } => { - tcx.dcx().emit_err(errors::ForbiddenTargetFeatureAttr { - span: item.span(), - feature, - reason, - }); - } - } + // Only allow target features whose feature gates have been enabled + // and which are permitted to be toggled. + if let Err(reason) = stability.allow_toggle() { + tcx.dcx().emit_err(errors::ForbiddenTargetFeatureAttr { + span: item.span(), + feature, + reason, + }); + } else if let Some(nightly_feature) = stability.requires_nightly() + && !rust_features.enabled(nightly_feature) + { + feature_err( + &tcx.sess, + nightly_feature, + item.span(), + format!("the target feature `{feature}` is currently unstable"), + ) + .emit(); } Some(Symbol::intern(feature)) })); @@ -156,18 +148,19 @@ pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { rust_target_features: |tcx, cnum| { assert_eq!(cnum, LOCAL_CRATE); + let target = &tcx.sess.target; if tcx.sess.opts.actually_rustdoc { // rustdoc needs to be able to document functions that use all the features, so // whitelist them all rustc_target::target_features::all_rust_features() - .map(|(a, b)| (a.to_string(), b)) + .map(|(a, b)| (a.to_string(), b.compute_toggleability(target))) .collect() } else { tcx.sess .target .rust_target_features() .iter() - .map(|&(a, b, _)| (a.to_string(), b)) + .map(|&(a, b, _)| (a.to_string(), b.compute_toggleability(target))) .collect() } }, diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs index 5b4a51fc301..4b17db2c49e 100644 --- a/compiler/rustc_codegen_ssa/src/traits/backend.rs +++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs @@ -45,7 +45,9 @@ pub trait CodegenBackend { fn print(&self, _req: &PrintRequest, _out: &mut String, _sess: &Session) {} - fn target_features(&self, _sess: &Session, _allow_unstable: bool) -> Vec<Symbol> { + /// Returns the features that should be set in `cfg(target_features)`. + /// RUSTC_SPECIFIC_FEATURES should be skipped here, those are handled outside codegen. + fn target_features_cfg(&self, _sess: &Session, _allow_unstable: bool) -> Vec<Symbol> { vec![] } |
