mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 11:20:54 +00:00
Support target features implications in target_feature 1.1
We vendor the list of implications, which isn't nice, but t-compiler doesn't want to make rustc_target available to us.
This commit is contained in:
parent
3bb49be89a
commit
87ed04bac0
@ -36,6 +36,7 @@ mod inhabitedness;
|
||||
mod interner;
|
||||
mod lower;
|
||||
mod mapping;
|
||||
mod target_feature;
|
||||
mod tls;
|
||||
mod utils;
|
||||
|
||||
@ -107,10 +108,9 @@ pub use mapping::{
|
||||
to_foreign_def_id, to_placeholder_idx,
|
||||
};
|
||||
pub use method_resolution::check_orphan_rules;
|
||||
pub use target_feature::TargetFeatures;
|
||||
pub use traits::TraitEnvironment;
|
||||
pub use utils::{
|
||||
all_super_traits, direct_super_traits, is_fn_unsafe_to_call, TargetFeatures, Unsafety,
|
||||
};
|
||||
pub use utils::{all_super_traits, direct_super_traits, is_fn_unsafe_to_call, Unsafety};
|
||||
pub use variance::Variance;
|
||||
|
||||
pub use chalk_ir::{
|
||||
|
259
crates/hir-ty/src/target_feature.rs
Normal file
259
crates/hir-ty/src/target_feature.rs
Normal file
@ -0,0 +1,259 @@
|
||||
//! Stuff for handling `#[target_feature]` (needed for unsafe check).
|
||||
|
||||
use std::sync::LazyLock;
|
||||
|
||||
use hir_def::attr::Attrs;
|
||||
use hir_def::tt;
|
||||
use intern::{sym, Symbol};
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct TargetFeatures {
|
||||
pub(crate) enabled: FxHashSet<Symbol>,
|
||||
}
|
||||
|
||||
impl TargetFeatures {
|
||||
pub fn from_attrs(attrs: &Attrs) -> Self {
|
||||
let mut result = TargetFeatures::from_attrs_no_implications(attrs);
|
||||
result.expand_implications();
|
||||
result
|
||||
}
|
||||
|
||||
fn expand_implications(&mut self) {
|
||||
let all_implications = LazyLock::force(&TARGET_FEATURE_IMPLICATIONS);
|
||||
let mut queue = self.enabled.iter().cloned().collect::<Vec<_>>();
|
||||
while let Some(feature) = queue.pop() {
|
||||
if let Some(implications) = all_implications.get(&feature) {
|
||||
for implication in implications {
|
||||
if self.enabled.insert(implication.clone()) {
|
||||
queue.push(implication.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieves the target features from the attributes, and does not expand the target features implied by them.
|
||||
pub(crate) fn from_attrs_no_implications(attrs: &Attrs) -> Self {
|
||||
let enabled = attrs
|
||||
.by_key(&sym::target_feature)
|
||||
.tt_values()
|
||||
.filter_map(|tt| {
|
||||
match tt.token_trees().flat_tokens() {
|
||||
[
|
||||
tt::TokenTree::Leaf(tt::Leaf::Ident(enable_ident)),
|
||||
tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct { char: '=', .. })),
|
||||
tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal { kind: tt::LitKind::Str, symbol: features, .. })),
|
||||
] if enable_ident.sym == sym::enable => Some(features),
|
||||
_ => None,
|
||||
}
|
||||
})
|
||||
.flat_map(|features| features.as_str().split(',').map(Symbol::intern))
|
||||
.collect();
|
||||
Self { enabled }
|
||||
}
|
||||
}
|
||||
|
||||
// List of the target features each target feature implies.
|
||||
// Ideally we'd depend on rustc for this, but rustc_target doesn't compile on stable,
|
||||
// and t-compiler prefers for it to stay this way.
|
||||
|
||||
static TARGET_FEATURE_IMPLICATIONS: LazyLock<FxHashMap<Symbol, Box<[Symbol]>>> =
|
||||
LazyLock::new(|| {
|
||||
let mut result = FxHashMap::<Symbol, FxHashSet<Symbol>>::default();
|
||||
for &(feature_str, implications) in TARGET_FEATURE_IMPLICATIONS_RAW {
|
||||
let feature = Symbol::intern(feature_str);
|
||||
let implications = implications.iter().copied().map(Symbol::intern);
|
||||
// Some target features appear in two archs, e.g. Arm and x86.
|
||||
// Sometimes they contain different implications, e.g. `aes`.
|
||||
// We should probably choose by the active arch, but for now just merge them.
|
||||
result.entry(feature).or_default().extend(implications);
|
||||
}
|
||||
let mut result = result
|
||||
.into_iter()
|
||||
.map(|(feature, implications)| (feature, Box::from_iter(implications)))
|
||||
.collect::<FxHashMap<_, _>>();
|
||||
result.shrink_to_fit();
|
||||
result
|
||||
});
|
||||
|
||||
const TARGET_FEATURE_IMPLICATIONS_RAW: &[(&str, &[&str])] = &[
|
||||
// Arm
|
||||
("aes", &["neon"]),
|
||||
("dotprod", &["neon"]),
|
||||
("fp-armv8", &["vfp4"]),
|
||||
("fp16", &["neon"]),
|
||||
("i8mm", &["neon"]),
|
||||
("neon", &["vfp3"]),
|
||||
("sha2", &["neon"]),
|
||||
("v6", &["v5te"]),
|
||||
("v6k", &["v6"]),
|
||||
("v6t2", &["v6k", "thumb2"]),
|
||||
("v7", &["v6t2"]),
|
||||
("v8", &["v7"]),
|
||||
("vfp3", &["vfp2", "d32"]),
|
||||
("vfp4", &["vfp3"]),
|
||||
// Aarch64
|
||||
("aes", &["neon"]),
|
||||
("dotprod", &["neon"]),
|
||||
("dpb2", &["dpb"]),
|
||||
("f32mm", &["sve"]),
|
||||
("f64mm", &["sve"]),
|
||||
("fcma", &["neon"]),
|
||||
("fhm", &["fp16"]),
|
||||
("fp16", &["neon"]),
|
||||
("fp8", &["faminmax", "lut", "bf16"]),
|
||||
("fp8dot2", &["fp8dot4"]),
|
||||
("fp8dot4", &["fp8fma"]),
|
||||
("fp8fma", &["fp8"]),
|
||||
("jsconv", &["neon"]),
|
||||
("lse128", &["lse"]),
|
||||
("rcpc2", &["rcpc"]),
|
||||
("rcpc3", &["rcpc2"]),
|
||||
("rdm", &["neon"]),
|
||||
("sha2", &["neon"]),
|
||||
("sha3", &["sha2"]),
|
||||
("sm4", &["neon"]),
|
||||
("sme", &["bf16"]),
|
||||
("sme-b16b16", &["bf16", "sme2", "sve-b16b16"]),
|
||||
("sme-f16f16", &["sme2"]),
|
||||
("sme-f64f64", &["sme"]),
|
||||
("sme-f8f16", &["sme-f8f32"]),
|
||||
("sme-f8f32", &["sme2", "fp8"]),
|
||||
("sme-fa64", &["sme", "sve2"]),
|
||||
("sme-i16i64", &["sme"]),
|
||||
("sme2", &["sme"]),
|
||||
("sme2p1", &["sme2"]),
|
||||
("ssve-fp8dot2", &["ssve-fp8dot4"]),
|
||||
("ssve-fp8dot4", &["ssve-fp8fma"]),
|
||||
("ssve-fp8fma", &["sme2", "fp8"]),
|
||||
("sve", &["neon"]),
|
||||
("sve-b16b16", &["bf16"]),
|
||||
("sve2", &["sve"]),
|
||||
("sve2-aes", &["sve2", "aes"]),
|
||||
("sve2-bitperm", &["sve2"]),
|
||||
("sve2-sha3", &["sve2", "sha3"]),
|
||||
("sve2-sm4", &["sve2", "sm4"]),
|
||||
("sve2p1", &["sve2"]),
|
||||
("v8.1a", &["crc", "lse", "rdm", "pan", "lor", "vh"]),
|
||||
("v8.2a", &["v8.1a", "ras", "dpb"]),
|
||||
("v8.3a", &["v8.2a", "rcpc", "paca", "pacg", "jsconv"]),
|
||||
("v8.4a", &["v8.3a", "dotprod", "dit", "flagm"]),
|
||||
("v8.5a", &["v8.4a", "ssbs", "sb", "dpb2", "bti"]),
|
||||
("v8.6a", &["v8.5a", "bf16", "i8mm"]),
|
||||
("v8.7a", &["v8.6a", "wfxt"]),
|
||||
("v8.8a", &["v8.7a", "hbc", "mops"]),
|
||||
("v8.9a", &["v8.8a", "cssc"]),
|
||||
("v9.1a", &["v9a", "v8.6a"]),
|
||||
("v9.2a", &["v9.1a", "v8.7a"]),
|
||||
("v9.3a", &["v9.2a", "v8.8a"]),
|
||||
("v9.4a", &["v9.3a", "v8.9a"]),
|
||||
("v9.5a", &["v9.4a"]),
|
||||
("v9a", &["v8.5a", "sve2"]),
|
||||
// x86
|
||||
("aes", &["sse2"]),
|
||||
("amx-bf16", &["amx-tile"]),
|
||||
("amx-complex", &["amx-tile"]),
|
||||
("amx-fp16", &["amx-tile"]),
|
||||
("amx-int8", &["amx-tile"]),
|
||||
("avx", &["sse4.2"]),
|
||||
("avx2", &["avx"]),
|
||||
("avx512bf16", &["avx512bw"]),
|
||||
("avx512bitalg", &["avx512bw"]),
|
||||
("avx512bw", &["avx512f"]),
|
||||
("avx512cd", &["avx512f"]),
|
||||
("avx512dq", &["avx512f"]),
|
||||
("avx512f", &["avx2", "fma", "f16c"]),
|
||||
("avx512fp16", &["avx512bw", "avx512vl", "avx512dq"]),
|
||||
("avx512ifma", &["avx512f"]),
|
||||
("avx512vbmi", &["avx512bw"]),
|
||||
("avx512vbmi2", &["avx512bw"]),
|
||||
("avx512vl", &["avx512f"]),
|
||||
("avx512vnni", &["avx512f"]),
|
||||
("avx512vp2intersect", &["avx512f"]),
|
||||
("avx512vpopcntdq", &["avx512f"]),
|
||||
("avxifma", &["avx2"]),
|
||||
("avxneconvert", &["avx2"]),
|
||||
("avxvnni", &["avx2"]),
|
||||
("avxvnniint16", &["avx2"]),
|
||||
("avxvnniint8", &["avx2"]),
|
||||
("f16c", &["avx"]),
|
||||
("fma", &["avx"]),
|
||||
("gfni", &["sse2"]),
|
||||
("kl", &["sse2"]),
|
||||
("pclmulqdq", &["sse2"]),
|
||||
("sha", &["sse2"]),
|
||||
("sha512", &["avx2"]),
|
||||
("sm3", &["avx"]),
|
||||
("sm4", &["avx2"]),
|
||||
("sse2", &["sse"]),
|
||||
("sse3", &["sse2"]),
|
||||
("sse4.1", &["ssse3"]),
|
||||
("sse4.2", &["sse4.1"]),
|
||||
("sse4a", &["sse3"]),
|
||||
("ssse3", &["sse3"]),
|
||||
("vaes", &["avx2", "aes"]),
|
||||
("vpclmulqdq", &["avx", "pclmulqdq"]),
|
||||
("widekl", &["kl"]),
|
||||
("xop", &[/*"fma4", */ "avx", "sse4a"]),
|
||||
("xsavec", &["xsave"]),
|
||||
("xsaveopt", &["xsave"]),
|
||||
("xsaves", &["xsave"]),
|
||||
// Hexagon
|
||||
("hvx-length128b", &["hvx"]),
|
||||
// PowerPC
|
||||
("power10-vector", &["power9-vector"]),
|
||||
("power8-altivec", &["altivec"]),
|
||||
("power8-crypto", &["power8-altivec"]),
|
||||
("power8-vector", &["vsx", "power8-altivec"]),
|
||||
("power9-altivec", &["power8-altivec"]),
|
||||
("power9-vector", &["power8-vector", "power9-altivec"]),
|
||||
("vsx", &["altivec"]),
|
||||
// MIPS
|
||||
// RISC-V
|
||||
("a", &["zaamo", "zalrsc"]),
|
||||
("d", &["f"]),
|
||||
("zabha", &["zaamo"]),
|
||||
("zdinx", &["zfinx"]),
|
||||
("zfh", &["zfhmin"]),
|
||||
("zfhmin", &["f"]),
|
||||
("zhinx", &["zhinxmin"]),
|
||||
("zhinxmin", &["zfinx"]),
|
||||
("zk", &["zkn", "zkr", "zkt"]),
|
||||
("zkn", &["zbkb", "zbkc", "zbkx", "zkne", "zknd", "zknh"]),
|
||||
("zks", &["zbkb", "zbkc", "zbkx", "zksed", "zksh"]),
|
||||
// WASM
|
||||
("relaxed-simd", &["simd128"]),
|
||||
// BPF
|
||||
("alu32", &[]),
|
||||
// CSKY
|
||||
("10e60", &["7e10"]),
|
||||
("2e3", &["e2"]),
|
||||
("3e3r2", &["3e3r1", "doloop"]),
|
||||
("3e3r3", &["doloop"]),
|
||||
("3e7", &["2e3"]),
|
||||
("7e10", &["3e7"]),
|
||||
("e1", &["elrw"]),
|
||||
("e2", &["e2"]),
|
||||
("mp", &["2e3"]),
|
||||
("mp1e2", &["3e7"]),
|
||||
// LoongArch
|
||||
("d", &["f"]),
|
||||
("lasx", &["lsx"]),
|
||||
("lsx", &["d"]),
|
||||
// IBM Z
|
||||
("nnp-assist", &["vector"]),
|
||||
("vector-enhancements-1", &["vector"]),
|
||||
("vector-enhancements-2", &["vector-enhancements-1"]),
|
||||
("vector-packed-decimal", &["vector"]),
|
||||
("vector-packed-decimal-enhancement", &["vector-packed-decimal"]),
|
||||
("vector-packed-decimal-enhancement-2", &["vector-packed-decimal-enhancement"]),
|
||||
// SPARC
|
||||
// m68k
|
||||
("isa-68010", &["isa-68000"]),
|
||||
("isa-68020", &["isa-68010"]),
|
||||
("isa-68030", &["isa-68020"]),
|
||||
("isa-68040", &["isa-68030", "isa-68882"]),
|
||||
("isa-68060", &["isa-68040"]),
|
||||
("isa-68882", &["isa-68881"]),
|
||||
];
|
@ -9,18 +9,16 @@ use chalk_ir::{
|
||||
DebruijnIndex,
|
||||
};
|
||||
use hir_def::{
|
||||
attr::Attrs,
|
||||
db::DefDatabase,
|
||||
generics::{WherePredicate, WherePredicateTypeTarget},
|
||||
lang_item::LangItem,
|
||||
resolver::{HasResolver, TypeNs},
|
||||
tt,
|
||||
type_ref::{TraitBoundModifier, TypeRef},
|
||||
EnumId, EnumVariantId, FunctionId, Lookup, OpaqueInternableThing, TraitId, TypeAliasId,
|
||||
TypeOrConstParamId,
|
||||
};
|
||||
use hir_expand::name::Name;
|
||||
use intern::{sym, Symbol};
|
||||
use intern::sym;
|
||||
use rustc_abi::TargetDataLayout;
|
||||
use rustc_hash::FxHashSet;
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
@ -32,8 +30,8 @@ use crate::{
|
||||
db::HirDatabase,
|
||||
layout::{Layout, TagEncoding},
|
||||
mir::pad16,
|
||||
ChalkTraitId, Const, ConstScalar, GenericArg, Interner, Substitution, TraitRef, TraitRefExt,
|
||||
Ty, WhereClause,
|
||||
ChalkTraitId, Const, ConstScalar, GenericArg, Interner, Substitution, TargetFeatures, TraitRef,
|
||||
TraitRefExt, Ty, WhereClause,
|
||||
};
|
||||
|
||||
pub(crate) fn fn_traits(
|
||||
@ -267,32 +265,6 @@ impl<'a> ClosureSubst<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct TargetFeatures {
|
||||
enabled: FxHashSet<Symbol>,
|
||||
}
|
||||
|
||||
impl TargetFeatures {
|
||||
pub fn from_attrs(attrs: &Attrs) -> Self {
|
||||
let enabled = attrs
|
||||
.by_key(&sym::target_feature)
|
||||
.tt_values()
|
||||
.filter_map(|tt| {
|
||||
match tt.token_trees().flat_tokens() {
|
||||
[
|
||||
tt::TokenTree::Leaf(tt::Leaf::Ident(enable_ident)),
|
||||
tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct { char: '=', .. })),
|
||||
tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal { kind: tt::LitKind::Str, symbol: features, .. })),
|
||||
] if enable_ident.sym == sym::enable => Some(features),
|
||||
_ => None,
|
||||
}
|
||||
})
|
||||
.flat_map(|features| features.as_str().split(',').map(Symbol::intern))
|
||||
.collect();
|
||||
Self { enabled }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum Unsafety {
|
||||
Safe,
|
||||
@ -314,7 +286,8 @@ pub fn is_fn_unsafe_to_call(
|
||||
|
||||
if data.has_target_feature() {
|
||||
// RFC 2396 <https://rust-lang.github.io/rfcs/2396-target-feature-1.1.html>.
|
||||
let callee_target_features = TargetFeatures::from_attrs(&db.attrs(func.into()));
|
||||
let callee_target_features =
|
||||
TargetFeatures::from_attrs_no_implications(&db.attrs(func.into()));
|
||||
if !caller_target_features.enabled.is_superset(&callee_target_features.enabled) {
|
||||
return Unsafety::Unsafe;
|
||||
}
|
||||
|
@ -854,7 +854,7 @@ fn main() {
|
||||
#[target_feature(enable = "avx")]
|
||||
fn foo() {}
|
||||
|
||||
#[target_feature(enable = "avx,avx2")]
|
||||
#[target_feature(enable = "avx2")]
|
||||
fn bar() {
|
||||
foo();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user