about summary refs log tree commit diff
path: root/compiler/rustc_codegen_gcc/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_codegen_gcc/src')
-rw-r--r--compiler/rustc_codegen_gcc/src/errors.rs26
-rw-r--r--compiler/rustc_codegen_gcc/src/gcc_util.rs123
-rw-r--r--compiler/rustc_codegen_gcc/src/lib.rs52
3 files changed, 40 insertions, 161 deletions
diff --git a/compiler/rustc_codegen_gcc/src/errors.rs b/compiler/rustc_codegen_gcc/src/errors.rs
index 7786be9ae5d..b7e7343460f 100644
--- a/compiler/rustc_codegen_gcc/src/errors.rs
+++ b/compiler/rustc_codegen_gcc/src/errors.rs
@@ -1,31 +1,7 @@
-use rustc_macros::{Diagnostic, Subdiagnostic};
+use rustc_macros::Diagnostic;
 use rustc_span::Span;
 
 #[derive(Diagnostic)]
-#[diag(codegen_gcc_unknown_ctarget_feature_prefix)]
-#[note]
-pub(crate) struct UnknownCTargetFeaturePrefix<'a> {
-    pub feature: &'a str,
-}
-
-#[derive(Diagnostic)]
-#[diag(codegen_gcc_unknown_ctarget_feature)]
-#[note]
-pub(crate) struct UnknownCTargetFeature<'a> {
-    pub feature: &'a str,
-    #[subdiagnostic]
-    pub rust_feature: PossibleFeature<'a>,
-}
-
-#[derive(Subdiagnostic)]
-pub(crate) enum PossibleFeature<'a> {
-    #[help(codegen_gcc_possible_feature)]
-    Some { rust_feature: &'a str },
-    #[help(codegen_gcc_consider_filing_feature_request)]
-    None,
-}
-
-#[derive(Diagnostic)]
 #[diag(codegen_gcc_unwinding_inline_asm)]
 pub(crate) struct UnwindingInlineAsm {
     #[primary_span]
diff --git a/compiler/rustc_codegen_gcc/src/gcc_util.rs b/compiler/rustc_codegen_gcc/src/gcc_util.rs
index 2e00d5fcb61..42ba40692b7 100644
--- a/compiler/rustc_codegen_gcc/src/gcc_util.rs
+++ b/compiler/rustc_codegen_gcc/src/gcc_util.rs
@@ -1,20 +1,12 @@
 #[cfg(feature = "master")]
 use gccjit::Context;
-use rustc_codegen_ssa::codegen_attrs::check_tied_features;
-use rustc_codegen_ssa::errors::TargetFeatureDisableOrEnable;
-use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::unord::UnordSet;
+use rustc_codegen_ssa::target_features;
 use rustc_session::Session;
-use rustc_session::features::{StabilityExt, retpoline_features_by_flags};
-use rustc_target::target_features::RUSTC_SPECIFIC_FEATURES;
 use smallvec::{SmallVec, smallvec};
 
-use crate::errors::{PossibleFeature, UnknownCTargetFeature, UnknownCTargetFeaturePrefix};
-
-fn gcc_features_by_flags(sess: &Session) -> Vec<&str> {
-    let mut features: Vec<&str> = Vec::new();
-    retpoline_features_by_flags(sess, &mut features);
-    features
+fn gcc_features_by_flags(sess: &Session, features: &mut Vec<String>) {
+    target_features::retpoline_features_by_flags(sess, features);
+    // FIXME: LLVM also sets +reserve-x18 here under some conditions.
 }
 
 /// The list of GCC features computed from CLI flags (`-Ctarget-cpu`, `-Ctarget-feature`,
@@ -44,98 +36,29 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri
     features.extend(sess.target.features.split(',').filter(|v| !v.is_empty()).map(String::from));
 
     // -Ctarget-features
-    let known_features = sess.target.rust_target_features();
-    let mut featsmap = FxHashMap::default();
-
-    // Compute implied features
-    let mut all_rust_features = vec![];
-    for feature in sess.opts.cg.target_feature.split(',').chain(gcc_features_by_flags(sess)) {
-        if let Some(feature) = feature.strip_prefix('+') {
-            all_rust_features.extend(
-                UnordSet::from(sess.target.implied_target_features(feature))
-                    .to_sorted_stable_ord()
-                    .iter()
-                    .map(|&&s| (true, s)),
-            )
-        } else if let Some(feature) = feature.strip_prefix('-') {
-            // FIXME: Why do we not remove implied features on "-" here?
-            // We do the equivalent above in `target_config`.
-            // See <https://github.com/rust-lang/rust/issues/134792>.
-            all_rust_features.push((false, feature));
-        } else if !feature.is_empty() && diagnostics {
-            sess.dcx().emit_warn(UnknownCTargetFeaturePrefix { feature });
-        }
-    }
-    // Remove features that are meant for rustc, not codegen.
-    all_rust_features.retain(|&(_, feature)| {
-        // Retain if it is not a rustc feature
-        !RUSTC_SPECIFIC_FEATURES.contains(&feature)
-    });
-
-    // Check feature validity.
-    if diagnostics {
-        for &(enable, feature) in &all_rust_features {
-            let feature_state = known_features.iter().find(|&&(v, _, _)| v == feature);
-            match feature_state {
-                None => {
-                    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, _)) => {
-                    stability.verify_feature_enabled_by_flag(sess, enable, feature);
-                }
-            }
-
-            // FIXME(nagisa): figure out how to not allocate a full hashset here.
-            featsmap.insert(feature, enable);
-        }
-    }
-
-    // Translate this into GCC features.
-    let feats =
-        all_rust_features.iter().flat_map(|&(enable, feature)| {
-            let enable_disable = if enable { '+' } else { '-' };
+    target_features::flag_to_backend_features(
+        sess,
+        diagnostics,
+        |feature| to_gcc_features(sess, feature),
+        |feature, enable| {
             // 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
             // different names when the GCC name and the Rust name differ.
-            to_gcc_features(sess, feature)
-                .iter()
-                .flat_map(|feat| to_gcc_features(sess, feat).into_iter())
-                .map(|feature| {
-                    if enable_disable == '-' {
-                        format!("-{}", feature)
-                    } else {
-                        feature.to_string()
-                    }
-                })
-                .collect::<Vec<_>>()
-        });
-    features.extend(feats);
-
-    if diagnostics && let Some(f) = check_tied_features(sess, &featsmap) {
-        sess.dcx().emit_err(TargetFeatureDisableOrEnable {
-            features: f,
-            span: None,
-            missing_features: None,
-        });
-    }
+            features.extend(
+                to_gcc_features(sess, feature)
+                    .iter()
+                    .flat_map(|feat| to_gcc_features(sess, feat).into_iter())
+                    .map(
+                        |feature| {
+                            if !enable { format!("-{}", feature) } else { feature.to_string() }
+                        },
+                    ),
+            );
+        },
+    );
+
+    gcc_features_by_flags(sess, &mut features);
 
     features
 }
diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs
index aa57655921d..a912678ef2a 100644
--- a/compiler/rustc_codegen_gcc/src/lib.rs
+++ b/compiler/rustc_codegen_gcc/src/lib.rs
@@ -102,6 +102,7 @@ use rustc_codegen_ssa::back::write::{
     CodegenContext, FatLtoInput, ModuleConfig, TargetMachineFactoryFn,
 };
 use rustc_codegen_ssa::base::codegen_crate;
+use rustc_codegen_ssa::target_features::cfg_target_feature;
 use rustc_codegen_ssa::traits::{CodegenBackend, ExtraBackendMethods, WriteBackendMethods};
 use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen, TargetConfig};
 use rustc_data_structures::fx::FxIndexMap;
@@ -476,42 +477,21 @@ fn to_gcc_opt_level(optlevel: Option<OptLevel>) -> OptimizationLevel {
 
 /// Returns the features that should be set in `cfg(target_feature)`.
 fn target_config(sess: &Session, target_info: &LockedTargetInfo) -> TargetConfig {
-    // TODO(antoyo): use global_gcc_features.
-    let f = |allow_unstable| {
-        sess.target
-            .rust_target_features()
-            .iter()
-            .filter_map(|&(feature, gate, _)| {
-                if allow_unstable
-                    || (gate.in_cfg()
-                        && (sess.is_nightly_build() || gate.requires_nightly().is_none()))
-                {
-                    Some(feature)
-                } else {
-                    None
-                }
-            })
-            .filter(|feature| {
-                // TODO: we disable Neon for now since we don't support the LLVM intrinsics for it.
-                if *feature == "neon" {
-                    return false;
-                }
-                target_info.cpu_supports(feature)
-                // cSpell:disable
-                /*
-                  adx, aes, avx, avx2, avx512bf16, avx512bitalg, avx512bw, avx512cd, avx512dq, avx512er, avx512f, avx512fp16, avx512ifma,
-                  avx512pf, avx512vbmi, avx512vbmi2, avx512vl, avx512vnni, avx512vp2intersect, avx512vpopcntdq,
-                  bmi1, bmi2, cmpxchg16b, ermsb, f16c, fma, fxsr, gfni, lzcnt, movbe, pclmulqdq, popcnt, rdrand, rdseed, rtm,
-                  sha, sse, sse2, sse3, sse4.1, sse4.2, sse4a, ssse3, tbm, vaes, vpclmulqdq, xsave, xsavec, xsaveopt, xsaves
-                */
-                // cSpell:enable
-            })
-            .map(Symbol::intern)
-            .collect()
-    };
-
-    let target_features = f(false);
-    let unstable_target_features = f(true);
+    let (unstable_target_features, target_features) = cfg_target_feature(sess, |feature| {
+        // TODO: we disable Neon for now since we don't support the LLVM intrinsics for it.
+        if feature == "neon" {
+            return false;
+        }
+        target_info.cpu_supports(feature)
+        // cSpell:disable
+        /*
+          adx, aes, avx, avx2, avx512bf16, avx512bitalg, avx512bw, avx512cd, avx512dq, avx512er, avx512f, avx512fp16, avx512ifma,
+          avx512pf, avx512vbmi, avx512vbmi2, avx512vl, avx512vnni, avx512vp2intersect, avx512vpopcntdq,
+          bmi1, bmi2, cmpxchg16b, ermsb, f16c, fma, fxsr, gfni, lzcnt, movbe, pclmulqdq, popcnt, rdrand, rdseed, rtm,
+          sha, sse, sse2, sse3, sse4.1, sse4.2, sse4a, ssse3, tbm, vaes, vpclmulqdq, xsave, xsavec, xsaveopt, xsaves
+        */
+        // cSpell:enable
+    });
 
     let has_reliable_f16 = target_info.supports_target_dependent_type(CType::Float16);
     let has_reliable_f128 = target_info.supports_target_dependent_type(CType::Float128);