Skip to content

Commit

Permalink
Merge pull request rust-lang#19223 from ChayimFriedman2/implied-targe…
Browse files Browse the repository at this point in the history
…t-feature

fix: Support target features implications in target_feature 1.1
  • Loading branch information
Veykril authored Feb 25, 2025
2 parents 3bb49be + 7c5524c commit 8925544
Show file tree
Hide file tree
Showing 5 changed files with 272 additions and 36 deletions.
2 changes: 2 additions & 0 deletions .typos.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ extend-ignore-re = [
"INOUT",
"optin",
"=Pn",
# ignore `// spellchecker:off` until `// spellchecker:on`
"(?s)(#|//)\\s*spellchecker:off.*?\\n\\s*(#|//)\\s*spellchecker:on",
]

[default.extend-words]
Expand Down
6 changes: 3 additions & 3 deletions crates/hir-ty/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ mod inhabitedness;
mod interner;
mod lower;
mod mapping;
mod target_feature;
mod tls;
mod utils;

Expand Down Expand Up @@ -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::{
Expand Down
261 changes: 261 additions & 0 deletions crates/hir-ty/src/target_feature.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,261 @@
//! 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
});

// spellchecker:off
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"]),
];
// spellchecker:on
37 changes: 5 additions & 32 deletions crates/hir-ty/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand All @@ -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(
Expand Down Expand Up @@ -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,
Expand All @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion crates/ide-diagnostics/src/handlers/missing_unsafe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -854,7 +854,7 @@ fn main() {
#[target_feature(enable = "avx")]
fn foo() {}
#[target_feature(enable = "avx,avx2")]
#[target_feature(enable = "avx2")]
fn bar() {
foo();
}
Expand Down

0 comments on commit 8925544

Please sign in to comment.