mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Add implied target features to target_feature attribute
This commit is contained in:
parent
6696447f78
commit
74653b61a6
@ -646,22 +646,6 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is a workaround for a LLVM bug that doesn't implicitly enable
|
|
||||||
// `simd128` when `relaxed-simd` is.
|
|
||||||
// See <https://github.com/llvm/llvm-project/pull/99803>, which didn't make
|
|
||||||
// it into a released version of LLVM yet.
|
|
||||||
//
|
|
||||||
// This doesn't use the "implicit target feature" system because it is only
|
|
||||||
// used for function attributes in other targets, which fixes this bug as
|
|
||||||
// well on the function attribute level.
|
|
||||||
if sess.target.families.contains(&"wasm".into()) {
|
|
||||||
if features.iter().any(|f| f == "+relaxed-simd")
|
|
||||||
&& !features.iter().any(|f| f == "+simd128")
|
|
||||||
{
|
|
||||||
features.push("+simd128".into());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if diagnostics && let Some(f) = check_tied_features(sess, &featsmap) {
|
if diagnostics && let Some(f) = check_tied_features(sess, &featsmap) {
|
||||||
sess.dcx().emit_err(TargetFeatureDisableOrEnable {
|
sess.dcx().emit_err(TargetFeatureDisableOrEnable {
|
||||||
features: f,
|
features: f,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use rustc_ast::ast;
|
use rustc_ast::ast;
|
||||||
use rustc_attr::InstructionSetAttr;
|
use rustc_attr::InstructionSetAttr;
|
||||||
use rustc_data_structures::fx::FxIndexSet;
|
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
|
||||||
use rustc_data_structures::unord::UnordMap;
|
use rustc_data_structures::unord::{UnordMap, UnordSet};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
|
use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
|
||||||
@ -30,6 +30,7 @@ pub fn from_target_feature(
|
|||||||
.emit();
|
.emit();
|
||||||
};
|
};
|
||||||
let rust_features = tcx.features();
|
let rust_features = tcx.features();
|
||||||
|
let mut added_target_features = Vec::new();
|
||||||
for item in list {
|
for item in list {
|
||||||
// Only `enable = ...` is accepted in the meta-item list.
|
// Only `enable = ...` is accepted in the meta-item list.
|
||||||
if !item.has_name(sym::enable) {
|
if !item.has_name(sym::enable) {
|
||||||
@ -44,7 +45,7 @@ pub fn from_target_feature(
|
|||||||
};
|
};
|
||||||
|
|
||||||
// We allow comma separation to enable multiple features.
|
// 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 Some(feature_gate) = supported_target_features.get(feature) else {
|
||||||
let msg = format!("the feature named `{feature}` is not valid for this target");
|
let msg = format!("the feature named `{feature}` is not valid for this target");
|
||||||
let mut err = tcx.dcx().struct_span_err(item.span(), msg);
|
let mut err = tcx.dcx().struct_span_err(item.span(), msg);
|
||||||
@ -98,13 +99,12 @@ pub fn from_target_feature(
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (feature, requires) in tcx.sess.target.implicit_target_features() {
|
// Add implied features
|
||||||
if target_features.iter().any(|f| f.as_str() == *feature)
|
for feature in added_target_features.iter() {
|
||||||
&& !target_features.iter().any(|f| f.as_str() == *requires)
|
target_features
|
||||||
{
|
.extend(tcx.implied_target_features(*feature).clone().into_sorted_stable_ord());
|
||||||
target_features.push(Symbol::intern(requires));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
target_features.extend(added_target_features)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Computes the set of target features used in a function for the purposes of
|
/// Computes the set of target features used in a function for the purposes of
|
||||||
@ -162,6 +162,28 @@ pub(crate) fn provide(providers: &mut Providers) {
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
implied_target_features: |tcx, feature| {
|
||||||
|
let implied_features = tcx
|
||||||
|
.sess
|
||||||
|
.target
|
||||||
|
.implied_target_features()
|
||||||
|
.iter()
|
||||||
|
.map(|(f, i)| (Symbol::intern(f), i))
|
||||||
|
.collect::<FxHashMap<_, _>>();
|
||||||
|
|
||||||
|
// implied target features have their own implied target features, so we traverse the
|
||||||
|
// map until there are no more features to add
|
||||||
|
let mut features = UnordSet::new();
|
||||||
|
let mut new_features = vec![feature];
|
||||||
|
while let Some(new_feature) = new_features.pop() {
|
||||||
|
if features.insert(new_feature) {
|
||||||
|
if let Some(implied_features) = implied_features.get(&new_feature) {
|
||||||
|
new_features.extend(implied_features.iter().copied().map(Symbol::intern))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
features
|
||||||
|
},
|
||||||
asm_target_features,
|
asm_target_features,
|
||||||
..*providers
|
..*providers
|
||||||
}
|
}
|
||||||
|
@ -2183,6 +2183,12 @@ rustc_queries! {
|
|||||||
desc { "looking up supported target features" }
|
desc { "looking up supported target features" }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
query implied_target_features(feature: Symbol) -> &'tcx UnordSet<Symbol> {
|
||||||
|
arena_cache
|
||||||
|
eval_always
|
||||||
|
desc { "looking up implied target features" }
|
||||||
|
}
|
||||||
|
|
||||||
query features_query(_: ()) -> &'tcx rustc_feature::Features {
|
query features_query(_: ()) -> &'tcx rustc_feature::Features {
|
||||||
feedable
|
feedable
|
||||||
desc { "looking up enabled feature gates" }
|
desc { "looking up enabled feature gates" }
|
||||||
|
@ -339,8 +339,6 @@ const WASM_ALLOWED_FEATURES: &[(&str, Stability)] = &[
|
|||||||
// tidy-alphabetical-end
|
// tidy-alphabetical-end
|
||||||
];
|
];
|
||||||
|
|
||||||
const WASM_IMPLICIT_FEATURES: &[(&str, &str)] = &[("relaxed-simd", "simd128")];
|
|
||||||
|
|
||||||
const BPF_ALLOWED_FEATURES: &[(&str, Stability)] = &[("alu32", Unstable(sym::bpf_target_feature))];
|
const BPF_ALLOWED_FEATURES: &[(&str, Stability)] = &[("alu32", Unstable(sym::bpf_target_feature))];
|
||||||
|
|
||||||
const CSKY_ALLOWED_FEATURES: &[(&str, Stability)] = &[
|
const CSKY_ALLOWED_FEATURES: &[(&str, Stability)] = &[
|
||||||
@ -411,6 +409,54 @@ const IBMZ_ALLOWED_FEATURES: &[(&str, Stability)] = &[
|
|||||||
// tidy-alphabetical-end
|
// tidy-alphabetical-end
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const X86_IMPLIED_FEATURES: &[(&str, &[&str])] = &[
|
||||||
|
// tidy-alphabetical-start
|
||||||
|
("aes", &["sse2"]),
|
||||||
|
("avx", &["sse4.2"]),
|
||||||
|
("avx2", &["avx"]),
|
||||||
|
("f16c", &["avx"]),
|
||||||
|
("fma", &["avx"]),
|
||||||
|
("pclmulqdq", &["sse2"]),
|
||||||
|
("sha", &["sse2"]),
|
||||||
|
("sse2", &["sse"]),
|
||||||
|
("sse3", &["sse2"]),
|
||||||
|
("sse4.1", &["ssse3"]),
|
||||||
|
("sse4.2", &["sse4.1"]),
|
||||||
|
("ssse3", &["sse3"]),
|
||||||
|
// tidy-alphabetical-end
|
||||||
|
];
|
||||||
|
|
||||||
|
const AARCH64_IMPLIED_FEATURES: &[(&str, &[&str])] = &[
|
||||||
|
// tidy-alphabetical-start
|
||||||
|
("aes", &["neon"]),
|
||||||
|
("f32mm", &["sve"]),
|
||||||
|
("f64mm", &["sve"]),
|
||||||
|
("fcma", &["neon"]),
|
||||||
|
("fhm", &["fp16"]),
|
||||||
|
("fp16", &["neon"]),
|
||||||
|
("jsconv", &["neon"]),
|
||||||
|
("rcpc2", &["rcpc"]),
|
||||||
|
("sha2", &["neon"]),
|
||||||
|
("sha3", &["sha2"]),
|
||||||
|
("sm4", &["neon"]),
|
||||||
|
("sve", &["fp16"]),
|
||||||
|
("sve2", &["sve"]),
|
||||||
|
("sve2-aes", &["sve2", "aes"]),
|
||||||
|
("sve2-bitperm", &["sve2"]),
|
||||||
|
("sve2-sha3", &["sve2", "sha3"]),
|
||||||
|
("sve2-sm4", &["sve2", "sm4"]),
|
||||||
|
// tidy-alphabetical-end
|
||||||
|
];
|
||||||
|
|
||||||
|
const RISCV_IMPLIED_FEATURES: &[(&str, &[&str])] = &[
|
||||||
|
// tidy-alphabetical-start
|
||||||
|
("zb", &["zba", "zbc", "zbs"]),
|
||||||
|
("zk", &["zkn", "zkr", "zks", "zkt", "zbkb", "zbkc", "zkbx"]),
|
||||||
|
("zkn", &["zknd", "zkne", "zknh", "zbkb", "zbkc", "zkbx"]),
|
||||||
|
("zks", &["zksed", "zksh", "zbkb", "zbkc", "zkbx"]),
|
||||||
|
// tidy-alphabetical-end
|
||||||
|
];
|
||||||
|
|
||||||
/// When rustdoc is running, provide a list of all known features so that all their respective
|
/// When rustdoc is running, provide a list of all known features so that all their respective
|
||||||
/// primitives may be documented.
|
/// primitives may be documented.
|
||||||
///
|
///
|
||||||
@ -458,11 +504,11 @@ impl super::spec::Target {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a list of target features. Each items first target feature
|
pub fn implied_target_features(&self) -> &'static [(&'static str, &'static [&'static str])] {
|
||||||
/// implicitly enables the second one.
|
|
||||||
pub fn implicit_target_features(&self) -> &'static [(&'static str, &'static str)] {
|
|
||||||
match &*self.arch {
|
match &*self.arch {
|
||||||
"wasm32" | "wasm64" => WASM_IMPLICIT_FEATURES,
|
"aarch4" => AARCH64_IMPLIED_FEATURES,
|
||||||
|
"riscv32" | "riscv64" => RISCV_IMPLIED_FEATURES,
|
||||||
|
"x86" | "x86_64" => X86_IMPLIED_FEATURES,
|
||||||
_ => &[],
|
_ => &[],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
24
tests/ui/target-feature/implied-features.rs
Normal file
24
tests/ui/target-feature/implied-features.rs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
//@ only-x86_64
|
||||||
|
//@ run-pass
|
||||||
|
#![feature(target_feature_11)]
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
#[target_feature(enable = "ssse3")]
|
||||||
|
fn call_ssse3() {}
|
||||||
|
|
||||||
|
#[target_feature(enable = "avx")]
|
||||||
|
fn call_avx() {}
|
||||||
|
|
||||||
|
#[target_feature(enable = "avx2")]
|
||||||
|
fn test_avx2() {
|
||||||
|
call_ssse3();
|
||||||
|
call_avx();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[target_feature(enable = "fma")]
|
||||||
|
fn test_fma() {
|
||||||
|
call_ssse3();
|
||||||
|
call_avx();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
Loading…
Reference in New Issue
Block a user