about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2025-01-05 10:34:33 +0100
committerRalf Jung <post@ralfj.de>2025-01-05 10:46:30 +0100
commit2e64b5352be9ec8b2a7b956c2be108394b85f4b0 (patch)
tree1b266e63d96229182c200d2785455ca04a8e5092
parent43ede97ebf7d874c9076723840c945b051b10ee2 (diff)
downloadrust-2e64b5352be9ec8b2a7b956c2be108394b85f4b0.tar.gz
rust-2e64b5352be9ec8b2a7b956c2be108394b85f4b0.zip
add dedicated type for ABI target feature constraints
-rw-r--r--compiler/rustc_codegen_gcc/src/gcc_util.rs19
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm_util.rs17
-rw-r--r--compiler/rustc_codegen_ssa/src/target_features.rs4
-rw-r--r--compiler/rustc_target/src/spec/mod.rs8
-rw-r--r--compiler/rustc_target/src/target_features.rs28
5 files changed, 45 insertions, 31 deletions
diff --git a/compiler/rustc_codegen_gcc/src/gcc_util.rs b/compiler/rustc_codegen_gcc/src/gcc_util.rs
index e9dfb4e4cf4..1994a2a3c53 100644
--- a/compiler/rustc_codegen_gcc/src/gcc_util.rs
+++ b/compiler/rustc_codegen_gcc/src/gcc_util.rs
@@ -47,9 +47,9 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri
 
     // Ensure that all ABI-required features are enabled, and the ABI-forbidden ones
     // are disabled.
-    let (abi_enable, abi_disable) = sess.target.abi_required_features();
-    let abi_enable_set = FxHashSet::from_iter(abi_enable.iter().copied());
-    let abi_disable_set = FxHashSet::from_iter(abi_disable.iter().copied());
+    let abi_feature_constraints = sess.target.abi_required_features();
+    let abi_incompatible_set =
+        FxHashSet::from_iter(abi_feature_constraints.incompatible.iter().copied());
 
     // Compute implied features
     let mut all_rust_features = vec![];
@@ -72,7 +72,7 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri
             }
         }
     }
-    // Remove features that are meant for rustc, not LLVM.
+    // 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)
@@ -121,7 +121,7 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri
 
             // Ensure that the features we enable/disable are compatible with the ABI.
             if enable {
-                if abi_disable_set.contains(feature) {
+                if abi_incompatible_set.contains(feature) {
                     sess.dcx().emit_warn(ForbiddenCTargetFeature {
                         feature,
                         enabled: "enabled",
@@ -131,8 +131,7 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri
             } else {
                 // FIXME: we have to request implied features here since
                 // negative features do not handle implied features above.
-                #[allow(rustc::potential_query_instability)] // order does not matter
-                for &required in abi_enable_set.iter() {
+                for &required in abi_feature_constraints.required.iter() {
                     let implied = sess.target.implied_target_features(std::iter::once(required));
                     if implied.contains(feature) {
                         sess.dcx().emit_warn(ForbiddenCTargetFeature {
@@ -158,7 +157,11 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri
     // still override it... that's unsound, but more compatible with past behavior.
     all_rust_features.splice(
         0..0,
-        abi_enable.iter().map(|&f| (true, f)).chain(abi_disable.iter().map(|&f| (false, f))),
+        abi_feature_constraints
+            .required
+            .iter()
+            .map(|&f| (true, f))
+            .chain(abi_feature_constraints.incompatible.iter().map(|&f| (false, f))),
     );
 
     // Translate this into GCC features.
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index 6ec09b29649..e18e91e569f 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -669,9 +669,9 @@ pub(crate) fn global_llvm_features(
 
         // Ensure that all ABI-required features are enabled, and the ABI-forbidden ones
         // are disabled.
-        let (abi_enable, abi_disable) = sess.target.abi_required_features();
-        let abi_enable_set = FxHashSet::from_iter(abi_enable.iter().copied());
-        let abi_disable_set = FxHashSet::from_iter(abi_disable.iter().copied());
+        let abi_feature_constraints = sess.target.abi_required_features();
+        let abi_incompatible_set =
+            FxHashSet::from_iter(abi_feature_constraints.incompatible.iter().copied());
 
         // Compute implied features
         let mut all_rust_features = vec![];
@@ -745,7 +745,7 @@ pub(crate) fn global_llvm_features(
 
                 // Ensure that the features we enable/disable are compatible with the ABI.
                 if enable {
-                    if abi_disable_set.contains(feature) {
+                    if abi_incompatible_set.contains(feature) {
                         sess.dcx().emit_warn(ForbiddenCTargetFeature {
                             feature,
                             enabled: "enabled",
@@ -755,8 +755,7 @@ pub(crate) fn global_llvm_features(
                 } else {
                     // FIXME: we have to request implied features here since
                     // negative features do not handle implied features above.
-                    #[allow(rustc::potential_query_instability)] // order does not matter
-                    for &required in abi_enable_set.iter() {
+                    for &required in abi_feature_constraints.required.iter() {
                         let implied =
                             sess.target.implied_target_features(std::iter::once(required));
                         if implied.contains(feature) {
@@ -783,7 +782,11 @@ pub(crate) fn global_llvm_features(
         // still override it... that's unsound, but more compatible with past behavior.
         all_rust_features.splice(
             0..0,
-            abi_enable.iter().map(|&f| (true, f)).chain(abi_disable.iter().map(|&f| (false, f))),
+            abi_feature_constraints
+                .required
+                .iter()
+                .map(|&f| (true, f))
+                .chain(abi_feature_constraints.incompatible.iter().map(|&f| (false, f))),
         );
 
         // Translate this into LLVM features.
diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs
index 61eeae630ed..d8b9bdb55da 100644
--- a/compiler/rustc_codegen_ssa/src/target_features.rs
+++ b/compiler/rustc_codegen_ssa/src/target_features.rs
@@ -32,7 +32,7 @@ pub(crate) fn from_target_feature_attr(
             .emit();
     };
     let rust_features = tcx.features();
-    let (_abi_enable, abi_disable) = tcx.sess.target.abi_required_features();
+    let abi_feature_constraints = tcx.sess.target.abi_required_features();
     for item in list {
         // Only `enable = ...` is accepted in the meta-item list.
         if !item.has_name(sym::enable) {
@@ -87,7 +87,7 @@ pub(crate) fn from_target_feature_attr(
                     // But ensure the ABI does not forbid enabling this.
                     // Here we do assume that LLVM doesn't add even more implied features
                     // we don't know about, at least no features that would have ABI effects!
-                    if abi_disable.contains(&name.as_str()) {
+                    if abi_feature_constraints.incompatible.contains(&name.as_str()) {
                         tcx.dcx().emit_err(errors::ForbiddenTargetFeatureAttr {
                             span: item.span(),
                             feature: name.as_str(),
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 28011f632b3..9d439b3d832 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -3242,8 +3242,8 @@ impl Target {
                 }
             }
             // Check that we don't mis-set any of the ABI-relevant features.
-            let (abi_enable, abi_disable) = self.abi_required_features();
-            for feat in abi_enable {
+            let abi_feature_constraints = self.abi_required_features();
+            for feat in abi_feature_constraints.required {
                 // The feature might be enabled by default so we can't *require* it to show up.
                 // But it must not be *disabled*.
                 if features_disabled.contains(feat) {
@@ -3252,8 +3252,8 @@ impl Target {
                     ));
                 }
             }
-            for feat in abi_disable {
-                // The feature might be disable by default so we can't *require* it to show up.
+            for feat in abi_feature_constraints.incompatible {
+                // The feature might be disabled by default so we can't *require* it to show up.
                 // But it must not be *enabled*.
                 if features_enabled.contains(feat) {
                     return Err(format!(
diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs
index 142ac0ff3d3..f594d20f928 100644
--- a/compiler/rustc_target/src/target_features.rs
+++ b/compiler/rustc_target/src/target_features.rs
@@ -669,6 +669,14 @@ const CSKY_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[(
 const LOONGARCH_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] =
     &[(128, "lsx"), (256, "lasx")];
 
+#[derive(Copy, Clone, Debug)]
+pub struct FeatureConstraints {
+    /// Features that must be enabled.
+    pub required: &'static [&'static str],
+    /// Features that must be disabled.
+    pub incompatible: &'static [&'static str],
+}
+
 impl Target {
     pub fn rust_target_features(&self) -> &'static [(&'static str, Stability, ImpliedFeatures)] {
         match &*self.arch {
@@ -749,8 +757,8 @@ impl Target {
     /// 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!
-    pub fn abi_required_features(&self) -> (&'static [&'static str], &'static [&'static str]) {
-        const NOTHING: (&'static [&'static str], &'static [&'static str]) = (&[], &[]);
+    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
         // defined by target features. When that is the case, those target features must be
         // "forbidden" in the list above to ensure that there is a consistent answer to the
@@ -763,7 +771,7 @@ impl Target {
                     NOTHING
                 } else {
                     // Hardfloat ABI. x87 must be enabled.
-                    (&["x87"], &[])
+                    FeatureConstraints { required: &["x87"], incompatible: &[] }
                 }
             }
             "x86_64" => {
@@ -773,7 +781,7 @@ impl Target {
                     NOTHING
                 } else {
                     // Hardfloat ABI. x87 and SSE2 must be enabled.
-                    (&["x87", "sse2"], &[])
+                    FeatureConstraints { required: &["x87", "sse2"], incompatible: &[] }
                 }
             }
             "arm" => {
@@ -786,7 +794,7 @@ impl Target {
                     }
                     FloatAbi::Hard => {
                         // Must have `fpregs` and must not have `soft-float`.
-                        (&["fpregs"], &["soft-float"])
+                        FeatureConstraints { required: &["fpregs"], incompatible: &["soft-float"] }
                     }
                 }
             }
@@ -803,7 +811,7 @@ impl Target {
                     _ => {
                         // Everything else is assumed to use a hardfloat ABI. neon and fp-armv8 must be enabled.
                         // These are Rust feature names and we use "neon" to control both of them.
-                        (&["neon"], &[])
+                        FeatureConstraints { required: &["neon"], incompatible: &[] }
                     }
                 }
             }
@@ -813,15 +821,15 @@ impl Target {
                 match &*self.llvm_abiname {
                     "ilp32d" | "lp64d" => {
                         // Requires d (which implies f), incompatible with e.
-                        (&["d"], &["e"])
+                        FeatureConstraints { required: &["d"], incompatible: &["e"] }
                     }
                     "ilp32f" | "lp64f" => {
                         // Requires f, incompatible with e.
-                        (&["f"], &["e"])
+                        FeatureConstraints { required: &["f"], incompatible: &["e"] }
                     }
                     "ilp32" | "lp64" => {
                         // Requires nothing, incompatible with e.
-                        (&[], &["e"])
+                        FeatureConstraints { required: &[], incompatible: &["e"] }
                     }
                     "ilp32e" => {
                         // ilp32e is documented to be incompatible with features that need aligned
@@ -832,7 +840,7 @@ impl Target {
                         // Note that the `e` feature is not required: the ABI treats the extra
                         // registers as caller-save, so it is safe to use them only in some parts of
                         // a program while the rest doesn't know they even exist.
-                        (&[], &["d"])
+                        FeatureConstraints { required: &[], incompatible: &["d"] }
                     }
                     "lp64e" => {
                         // As above, `e` is not required.