1use 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 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
47static 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 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
70const TARGET_FEATURE_IMPLICATIONS_RAW: &[(&str, &[&str])] = &[
72 ("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 ("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 ("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", &["avx", "sse4a"]),
190 ("xsavec", &["xsave"]),
191 ("xsaveopt", &["xsave"]),
192 ("xsaves", &["xsave"]),
193 ("hvx-length128b", &["hvx"]),
195 ("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 ("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 ("relaxed-simd", &["simd128"]),
218 ("alu32", &[]),
220 ("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 ("d", &["f"]),
233 ("lasx", &["lsx"]),
234 ("lsx", &["d"]),
235 ("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 ("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