From 4843153a0aba7c49b1e6780a40f90e93c9a57b6e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 2 Sep 2024 11:45:59 +0200 Subject: [PATCH] mark some target features as 'forbidden' so they cannot be (un)set For now, this is just a warning, but should become a hard error in the future --- messages.ftl | 11 ++++++-- src/errors.rs | 13 ++++++++++ src/gcc_util.rs | 69 ++++++++++++++++++++++++++++++------------------- src/lib.rs | 3 ++- 4 files changed, 66 insertions(+), 30 deletions(-) diff --git a/messages.ftl b/messages.ftl index bbae59ea7a5..26ddc5732dd 100644 --- a/messages.ftl +++ b/messages.ftl @@ -8,6 +8,9 @@ codegen_gcc_invalid_minimum_alignment = codegen_gcc_lto_not_supported = LTO is not supported. You may get a linker error. +codegen_gcc_forbidden_ctarget_feature = + target feature `{$feature}` cannot be toggled with `-Ctarget-feature` + codegen_gcc_unwinding_inline_asm = GCC backend does not support unwinding from inline asm @@ -24,11 +27,15 @@ codegen_gcc_lto_dylib = lto cannot be used for `dylib` crate type without `-Zdyl codegen_gcc_lto_bitcode_from_rlib = failed to get bitcode from object file for LTO ({$gcc_err}) codegen_gcc_unknown_ctarget_feature = - unknown feature specified for `-Ctarget-feature`: `{$feature}` - .note = it is still passed through to the codegen backend + unknown and unstable feature specified for `-Ctarget-feature`: `{$feature}` + .note = it is still passed through to the codegen backend, but use of this feature might be unsound and the behavior of this feature can change in the future .possible_feature = you might have meant: `{$rust_feature}` .consider_filing_feature_request = consider filing a feature request +codegen_gcc_unstable_ctarget_feature = + unstable feature specified for `-Ctarget-feature`: `{$feature}` + .note = this feature is not stably supported; its behavior can change in the future + codegen_gcc_missing_features = add the missing features in a `target_feature` attribute diff --git a/src/errors.rs b/src/errors.rs index dc1895f437b..7a586b5b04c 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -17,6 +17,19 @@ pub(crate) struct UnknownCTargetFeature<'a> { pub rust_feature: PossibleFeature<'a>, } +#[derive(Diagnostic)] +#[diag(codegen_gcc_unstable_ctarget_feature)] +#[note] +pub(crate) struct UnstableCTargetFeature<'a> { + pub feature: &'a str, +} + +#[derive(Diagnostic)] +#[diag(codegen_gcc_forbidden_ctarget_feature)] +pub(crate) struct ForbiddenCTargetFeature<'a> { + pub feature: &'a str, +} + #[derive(Subdiagnostic)] pub(crate) enum PossibleFeature<'a> { #[help(codegen_gcc_possible_feature)] diff --git a/src/gcc_util.rs b/src/gcc_util.rs index 3104088e0d5..65279c9495a 100644 --- a/src/gcc_util.rs +++ b/src/gcc_util.rs @@ -5,10 +5,13 @@ use rustc_codegen_ssa::errors::TargetFeatureDisableOrEnable; use rustc_data_structures::fx::FxHashMap; use rustc_middle::bug; use rustc_session::Session; -use rustc_target::target_features::RUSTC_SPECIFIC_FEATURES; +use rustc_target::target_features::{RUSTC_SPECIFIC_FEATURES, Stability}; use smallvec::{SmallVec, smallvec}; -use crate::errors::{PossibleFeature, UnknownCTargetFeature, UnknownCTargetFeaturePrefix}; +use crate::errors::{ + ForbiddenCTargetFeature, PossibleFeature, UnknownCTargetFeature, UnknownCTargetFeaturePrefix, + UnstableCTargetFeature, +}; /// The list of GCC features computed from CLI flags (`-Ctarget-cpu`, `-Ctarget-feature`, /// `--target` and similar). @@ -43,7 +46,7 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec Vec { + let rust_feature = + known_features.iter().find_map(|&(rust_feature, _, _)| { + let gcc_features = to_gcc_features(sess, rust_feature); + if gcc_features.contains(&feature) + && !gcc_features.contains(&rust_feature) + { + Some(rust_feature) + } else { + None + } + }); + let unknown_feature = if let Some(rust_feature) = rust_feature { + UnknownCTargetFeature { + feature, + rust_feature: PossibleFeature::Some { rust_feature }, + } + } else { + UnknownCTargetFeature { feature, rust_feature: PossibleFeature::None } + }; + sess.dcx().emit_warn(unknown_feature); + } + Some((_, Stability::Stable, _)) => {} + Some((_, Stability::Unstable(_), _)) => { + // An unstable feature. Warn about using it. + sess.dcx().emit_warn(UnstableCTargetFeature { feature }); + } + Some((_, Stability::Forbidden { .. }, _)) => { + sess.dcx().emit_err(ForbiddenCTargetFeature { feature }); + } + } + // FIXME(nagisa): figure out how to not allocate a full hashset here. featsmap.insert(feature, enable_disable == '+'); } - // rustc-specific features do not get passed down to GCC… - if RUSTC_SPECIFIC_FEATURES.contains(&feature) { - return None; - } // ... otherwise though 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 diff --git a/src/lib.rs b/src/lib.rs index 7486eefeb85..f70dc94b267 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -491,8 +491,9 @@ pub fn target_features( ) -> Vec { // TODO(antoyo): use global_gcc_features. sess.target - .supported_target_features() + .rust_target_features() .iter() + .filter(|(_, gate, _)| gate.is_supported()) .filter_map(|&(feature, gate, _)| { if sess.is_nightly_build() || allow_unstable || gate.is_stable() { Some(feature)