diff options
| author | Ralf Jung <post@ralfj.de> | 2025-01-05 10:34:33 +0100 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2025-01-05 10:46:30 +0100 |
| commit | 2e64b5352be9ec8b2a7b956c2be108394b85f4b0 (patch) | |
| tree | 1b266e63d96229182c200d2785455ca04a8e5092 | |
| parent | 43ede97ebf7d874c9076723840c945b051b10ee2 (diff) | |
| download | rust-2e64b5352be9ec8b2a7b956c2be108394b85f4b0.tar.gz rust-2e64b5352be9ec8b2a7b956c2be108394b85f4b0.zip | |
add dedicated type for ABI target feature constraints
| -rw-r--r-- | compiler/rustc_codegen_gcc/src/gcc_util.rs | 19 | ||||
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/llvm_util.rs | 17 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/target_features.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_target/src/spec/mod.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_target/src/target_features.rs | 28 |
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. |
