hir_ty/
target_feature.rs

1//! Stuff for handling `#[target_feature]` (needed for unsafe check).
2
3use std::borrow::Cow;
4use std::sync::LazyLock;
5
6use hir_def::FunctionId;
7use hir_def::attrs::AttrFlags;
8use intern::Symbol;
9use rustc_hash::{FxHashMap, FxHashSet};
10
11use crate::db::HirDatabase;
12
13#[derive(Debug, Default, Clone)]
14pub struct TargetFeatures<'db> {
15    pub(crate) enabled: Cow<'db, FxHashSet<Symbol>>,
16}
17
18impl<'db> TargetFeatures<'db> {
19    pub fn from_fn(db: &'db dyn HirDatabase, owner: FunctionId) -> Self {
20        let mut result = TargetFeatures::from_fn_no_implications(db, owner);
21        result.expand_implications();
22        result
23    }
24
25    fn expand_implications(&mut self) {
26        let all_implications = LazyLock::force(&TARGET_FEATURE_IMPLICATIONS);
27        let enabled = self.enabled.to_mut();
28        let mut queue = enabled.iter().cloned().collect::<Vec<_>>();
29        while let Some(feature) = queue.pop() {
30            if let Some(implications) = all_implications.get(&feature) {
31                for implication in implications {
32                    if enabled.insert(implication.clone()) {
33                        queue.push(implication.clone());
34                    }
35                }
36            }
37        }
38    }
39
40    /// Retrieves the target features from the attributes, and does not expand the target features implied by them.
41    pub(crate) fn from_fn_no_implications(db: &'db dyn HirDatabase, owner: FunctionId) -> Self {
42        let enabled = AttrFlags::target_features(db, owner);
43        Self { enabled: Cow::Borrowed(enabled) }
44    }
45}
46
47// List of the target features each target feature implies.
48// Ideally we'd depend on rustc for this, but rustc_target doesn't compile on stable,
49// and t-compiler prefers for it to stay this way.
50
51static TARGET_FEATURE_IMPLICATIONS: LazyLock<FxHashMap<Symbol, Box<[Symbol]>>> =
52    LazyLock::new(|| {
53        let mut result = FxHashMap::<Symbol, FxHashSet<Symbol>>::default();
54        for &(feature_str, implications) in TARGET_FEATURE_IMPLICATIONS_RAW {
55            let feature = Symbol::intern(feature_str);
56            let implications = implications.iter().copied().map(Symbol::intern);
57            // Some target features appear in two archs, e.g. Arm and x86.
58            // Sometimes they contain different implications, e.g. `aes`.
59            // We should probably choose by the active arch, but for now just merge them.
60            result.entry(feature).or_default().extend(implications);
61        }
62        let mut result = result
63            .into_iter()
64            .map(|(feature, implications)| (feature, Box::from_iter(implications)))
65            .collect::<FxHashMap<_, _>>();
66        result.shrink_to_fit();
67        result
68    });
69
70// spellchecker:off
71const TARGET_FEATURE_IMPLICATIONS_RAW: &[(&str, &[&str])] = &[
72    // Arm
73    ("aes", &["neon"]),
74    ("dotprod", &["neon"]),
75    ("fp-armv8", &["vfp4"]),
76    ("fp16", &["neon"]),
77    ("i8mm", &["neon"]),
78    ("neon", &["vfp3"]),
79    ("sha2", &["neon"]),
80    ("v6", &["v5te"]),
81    ("v6k", &["v6"]),
82    ("v6t2", &["v6k", "thumb2"]),
83    ("v7", &["v6t2"]),
84    ("v8", &["v7"]),
85    ("vfp3", &["vfp2", "d32"]),
86    ("vfp4", &["vfp3"]),
87    // Aarch64
88    ("aes", &["neon"]),
89    ("dotprod", &["neon"]),
90    ("dpb2", &["dpb"]),
91    ("f32mm", &["sve"]),
92    ("f64mm", &["sve"]),
93    ("fcma", &["neon"]),
94    ("fhm", &["fp16"]),
95    ("fp16", &["neon"]),
96    ("fp8", &["faminmax", "lut", "bf16"]),
97    ("fp8dot2", &["fp8dot4"]),
98    ("fp8dot4", &["fp8fma"]),
99    ("fp8fma", &["fp8"]),
100    ("jsconv", &["neon"]),
101    ("lse128", &["lse"]),
102    ("rcpc2", &["rcpc"]),
103    ("rcpc3", &["rcpc2"]),
104    ("rdm", &["neon"]),
105    ("sha2", &["neon"]),
106    ("sha3", &["sha2"]),
107    ("sm4", &["neon"]),
108    ("sme", &["bf16"]),
109    ("sme-b16b16", &["bf16", "sme2", "sve-b16b16"]),
110    ("sme-f16f16", &["sme2"]),
111    ("sme-f64f64", &["sme"]),
112    ("sme-f8f16", &["sme-f8f32"]),
113    ("sme-f8f32", &["sme2", "fp8"]),
114    ("sme-fa64", &["sme", "sve2"]),
115    ("sme-i16i64", &["sme"]),
116    ("sme2", &["sme"]),
117    ("sme2p1", &["sme2"]),
118    ("ssve-fp8dot2", &["ssve-fp8dot4"]),
119    ("ssve-fp8dot4", &["ssve-fp8fma"]),
120    ("ssve-fp8fma", &["sme2", "fp8"]),
121    ("sve", &["neon"]),
122    ("sve-b16b16", &["bf16"]),
123    ("sve2", &["sve"]),
124    ("sve2-aes", &["sve2", "aes"]),
125    ("sve2-bitperm", &["sve2"]),
126    ("sve2-sha3", &["sve2", "sha3"]),
127    ("sve2-sm4", &["sve2", "sm4"]),
128    ("sve2p1", &["sve2"]),
129    ("v8.1a", &["crc", "lse", "rdm", "pan", "lor", "vh"]),
130    ("v8.2a", &["v8.1a", "ras", "dpb"]),
131    ("v8.3a", &["v8.2a", "rcpc", "paca", "pacg", "jsconv"]),
132    ("v8.4a", &["v8.3a", "dotprod", "dit", "flagm"]),
133    ("v8.5a", &["v8.4a", "ssbs", "sb", "dpb2", "bti"]),
134    ("v8.6a", &["v8.5a", "bf16", "i8mm"]),
135    ("v8.7a", &["v8.6a", "wfxt"]),
136    ("v8.8a", &["v8.7a", "hbc", "mops"]),
137    ("v8.9a", &["v8.8a", "cssc"]),
138    ("v9.1a", &["v9a", "v8.6a"]),
139    ("v9.2a", &["v9.1a", "v8.7a"]),
140    ("v9.3a", &["v9.2a", "v8.8a"]),
141    ("v9.4a", &["v9.3a", "v8.9a"]),
142    ("v9.5a", &["v9.4a"]),
143    ("v9a", &["v8.5a", "sve2"]),
144    // x86
145    ("aes", &["sse2"]),
146    ("amx-bf16", &["amx-tile"]),
147    ("amx-complex", &["amx-tile"]),
148    ("amx-fp16", &["amx-tile"]),
149    ("amx-int8", &["amx-tile"]),
150    ("avx", &["sse4.2"]),
151    ("avx2", &["avx"]),
152    ("avx512bf16", &["avx512bw"]),
153    ("avx512bitalg", &["avx512bw"]),
154    ("avx512bw", &["avx512f"]),
155    ("avx512cd", &["avx512f"]),
156    ("avx512dq", &["avx512f"]),
157    ("avx512f", &["avx2", "fma", "f16c"]),
158    ("avx512fp16", &["avx512bw", "avx512vl", "avx512dq"]),
159    ("avx512ifma", &["avx512f"]),
160    ("avx512vbmi", &["avx512bw"]),
161    ("avx512vbmi2", &["avx512bw"]),
162    ("avx512vl", &["avx512f"]),
163    ("avx512vnni", &["avx512f"]),
164    ("avx512vp2intersect", &["avx512f"]),
165    ("avx512vpopcntdq", &["avx512f"]),
166    ("avxifma", &["avx2"]),
167    ("avxneconvert", &["avx2"]),
168    ("avxvnni", &["avx2"]),
169    ("avxvnniint16", &["avx2"]),
170    ("avxvnniint8", &["avx2"]),
171    ("f16c", &["avx"]),
172    ("fma", &["avx"]),
173    ("gfni", &["sse2"]),
174    ("kl", &["sse2"]),
175    ("pclmulqdq", &["sse2"]),
176    ("sha", &["sse2"]),
177    ("sha512", &["avx2"]),
178    ("sm3", &["avx"]),
179    ("sm4", &["avx2"]),
180    ("sse2", &["sse"]),
181    ("sse3", &["sse2"]),
182    ("sse4.1", &["ssse3"]),
183    ("sse4.2", &["sse4.1"]),
184    ("sse4a", &["sse3"]),
185    ("ssse3", &["sse3"]),
186    ("vaes", &["avx2", "aes"]),
187    ("vpclmulqdq", &["avx", "pclmulqdq"]),
188    ("widekl", &["kl"]),
189    ("xop", &[/*"fma4", */ "avx", "sse4a"]),
190    ("xsavec", &["xsave"]),
191    ("xsaveopt", &["xsave"]),
192    ("xsaves", &["xsave"]),
193    // Hexagon
194    ("hvx-length128b", &["hvx"]),
195    // PowerPC
196    ("power10-vector", &["power9-vector"]),
197    ("power8-altivec", &["altivec"]),
198    ("power8-crypto", &["power8-altivec"]),
199    ("power8-vector", &["vsx", "power8-altivec"]),
200    ("power9-altivec", &["power8-altivec"]),
201    ("power9-vector", &["power8-vector", "power9-altivec"]),
202    ("vsx", &["altivec"]),
203    // MIPS
204    // RISC-V
205    ("a", &["zaamo", "zalrsc"]),
206    ("d", &["f"]),
207    ("zabha", &["zaamo"]),
208    ("zdinx", &["zfinx"]),
209    ("zfh", &["zfhmin"]),
210    ("zfhmin", &["f"]),
211    ("zhinx", &["zhinxmin"]),
212    ("zhinxmin", &["zfinx"]),
213    ("zk", &["zkn", "zkr", "zkt"]),
214    ("zkn", &["zbkb", "zbkc", "zbkx", "zkne", "zknd", "zknh"]),
215    ("zks", &["zbkb", "zbkc", "zbkx", "zksed", "zksh"]),
216    // WASM
217    ("relaxed-simd", &["simd128"]),
218    // BPF
219    ("alu32", &[]),
220    // CSKY
221    ("10e60", &["7e10"]),
222    ("2e3", &["e2"]),
223    ("3e3r2", &["3e3r1", "doloop"]),
224    ("3e3r3", &["doloop"]),
225    ("3e7", &["2e3"]),
226    ("7e10", &["3e7"]),
227    ("e1", &["elrw"]),
228    ("e2", &["e2"]),
229    ("mp", &["2e3"]),
230    ("mp1e2", &["3e7"]),
231    // LoongArch
232    ("d", &["f"]),
233    ("lasx", &["lsx"]),
234    ("lsx", &["d"]),
235    // IBM Z
236    ("nnp-assist", &["vector"]),
237    ("vector-enhancements-1", &["vector"]),
238    ("vector-enhancements-2", &["vector-enhancements-1"]),
239    ("vector-packed-decimal", &["vector"]),
240    ("vector-packed-decimal-enhancement", &["vector-packed-decimal"]),
241    ("vector-packed-decimal-enhancement-2", &["vector-packed-decimal-enhancement"]),
242    // SPARC
243    // m68k
244    ("isa-68010", &["isa-68000"]),
245    ("isa-68020", &["isa-68010"]),
246    ("isa-68030", &["isa-68020"]),
247    ("isa-68040", &["isa-68030", "isa-68882"]),
248    ("isa-68060", &["isa-68040"]),
249    ("isa-68882", &["isa-68881"]),
250];
251// spellchecker:on