diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2024-08-07 20:28:16 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-08-07 20:28:16 +0200 |
| commit | 904f5795a0ffd4393ea0810d5e6efedd4b00e42c (patch) | |
| tree | 3b1f6ab81b3b6882c84e3a973e2866f4941c8e5a /compiler/rustc_codegen_ssa | |
| parent | 8d0066922b14cee3175e8c141e5e909fa6d9a6eb (diff) | |
| parent | 8818c9552821721e4be5c19832b4e3ac64090feb (diff) | |
| download | rust-904f5795a0ffd4393ea0810d5e6efedd4b00e42c.tar.gz rust-904f5795a0ffd4393ea0810d5e6efedd4b00e42c.zip | |
Rollup merge of #128221 - calebzulawski:implied-target-features, r=Amanieu
Add implied target features to target_feature attribute See [zulip](https://rust-lang.zulipchat.com/#narrow/stream/208962-t-libs.2Fstdarch/topic/Why.20would.20target-feature.20include.20implied.20features.3F) for some context. Adds implied target features, e.g. `#[target_feature(enable = "avx2")]` acts like `#[target_feature(enable = "avx2,avx,sse4.2,sse4.1...")]`. Fixes #128125, fixes #128426 The implied feature sets are taken from [the rust reference](https://doc.rust-lang.org/reference/attributes/codegen.html?highlight=target-fea#x86-or-x86_64), there are certainly more features and targets to add. Please feel free to reassign this to whoever should review it. r? ``@Amanieu``
Diffstat (limited to 'compiler/rustc_codegen_ssa')
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/target_features.rs | 41 |
1 files changed, 30 insertions, 11 deletions
diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index 127244a34f8..cf8f7fa25d8 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -1,11 +1,12 @@ use rustc_ast::ast; use rustc_attr::InstructionSetAttr; use rustc_data_structures::fx::FxIndexSet; -use rustc_data_structures::unord::UnordMap; +use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_errors::Applicability; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE}; use rustc_middle::bug; +use rustc_middle::middle::codegen_fn_attrs::TargetFeature; use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_session::parse::feature_err; @@ -18,7 +19,7 @@ pub fn from_target_feature( tcx: TyCtxt<'_>, attr: &ast::Attribute, supported_target_features: &UnordMap<String, Option<Symbol>>, - target_features: &mut Vec<Symbol>, + target_features: &mut Vec<TargetFeature>, ) { let Some(list) = attr.meta_item_list() else { return }; let bad_item = |span| { @@ -30,6 +31,7 @@ pub fn from_target_feature( .emit(); }; let rust_features = tcx.features(); + let mut added_target_features = Vec::new(); for item in list { // Only `enable = ...` is accepted in the meta-item list. if !item.has_name(sym::enable) { @@ -44,7 +46,7 @@ pub fn from_target_feature( }; // We allow comma separation to enable multiple features. - target_features.extend(value.as_str().split(',').filter_map(|feature| { + added_target_features.extend(value.as_str().split(',').filter_map(|feature| { let Some(feature_gate) = supported_target_features.get(feature) else { let msg = format!("the feature named `{feature}` is not valid for this target"); let mut err = tcx.dcx().struct_span_err(item.span(), msg); @@ -98,13 +100,26 @@ pub fn from_target_feature( })); } - for (feature, requires) in tcx.sess.target.implicit_target_features() { - if target_features.iter().any(|f| f.as_str() == *feature) - && !target_features.iter().any(|f| f.as_str() == *requires) - { - target_features.push(Symbol::intern(requires)); - } + // Add explicit features + target_features.extend( + added_target_features.iter().copied().map(|name| TargetFeature { name, implied: false }), + ); + + // Add implied features + let mut implied_target_features = UnordSet::new(); + for feature in added_target_features.iter() { + implied_target_features.extend(tcx.implied_target_features(*feature).clone()); } + for feature in added_target_features.iter() { + implied_target_features.remove(feature); + } + target_features.extend( + implied_target_features + .into_sorted_stable_ord() + .iter() + .copied() + .map(|name| TargetFeature { name, implied: true }), + ) } /// Computes the set of target features used in a function for the purposes of @@ -113,7 +128,7 @@ fn asm_target_features(tcx: TyCtxt<'_>, did: DefId) -> &FxIndexSet<Symbol> { let mut target_features = tcx.sess.unstable_target_features.clone(); if tcx.def_kind(did).has_codegen_attrs() { let attrs = tcx.codegen_fn_attrs(did); - target_features.extend(&attrs.target_features); + target_features.extend(attrs.target_features.iter().map(|feature| feature.name)); match attrs.instruction_set { None => {} Some(InstructionSetAttr::ArmA32) => { @@ -158,10 +173,14 @@ pub(crate) fn provide(providers: &mut Providers) { .target .supported_target_features() .iter() - .map(|&(a, b)| (a.to_string(), b.as_feature_name())) + .map(|&(a, b, _)| (a.to_string(), b.as_feature_name())) .collect() } }, + implied_target_features: |tcx, feature| { + UnordSet::from(tcx.sess.target.implied_target_features(std::iter::once(feature))) + .into_sorted_stable_ord() + }, asm_target_features, ..*providers } |
