1use std::sync::LazyLock;
4
5use hir_def::attr::Attrs;
6use hir_def::tt;
7use intern::{Symbol, sym};
8use rustc_hash::{FxHashMap, FxHashSet};
9
10#[derive(Debug, Default)]
11pub struct TargetFeatures {
12 pub(crate) enabled: FxHashSet<Symbol>,
13}
14
15impl TargetFeatures {
16 pub fn from_attrs(attrs: &Attrs) -> Self {
17 let mut result = TargetFeatures::from_attrs_no_implications(attrs);
18 result.expand_implications();
19 result
20 }
21
22 fn expand_implications(&mut self) {
23 let all_implications = LazyLock::force(&TARGET_FEATURE_IMPLICATIONS);
24 let mut queue = self.enabled.iter().cloned().collect::<Vec<_>>();
25 while let Some(feature) = queue.pop() {
26 if let Some(implications) = all_implications.get(&feature) {
27 for implication in implications {
28 if self.enabled.insert(implication.clone()) {
29 queue.push(implication.clone());
30 }
31 }
32 }
33 }
34 }
35
36 pub(crate) fn from_attrs_no_implications(attrs: &Attrs) -> Self {
38 let enabled = attrs
39 .by_key(sym::target_feature)
40 .tt_values()
41 .filter_map(|tt| match tt.token_trees().flat_tokens() {
42 [
43 tt::TokenTree::Leaf(tt::Leaf::Ident(enable_ident)),
44 tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct { char: '=', .. })),
45 tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
46 kind: tt::LitKind::Str,
47 symbol: features,
48 ..
49 })),
50 ] if enable_ident.sym == sym::enable => Some(features),
51 _ => None,
52 })
53 .flat_map(|features| features.as_str().split(',').map(Symbol::intern))
54 .collect();
55 Self { enabled }
56 }
57}
58
59static TARGET_FEATURE_IMPLICATIONS: LazyLock<FxHashMap<Symbol, Box<[Symbol]>>> =
64 LazyLock::new(|| {
65 let mut result = FxHashMap::<Symbol, FxHashSet<Symbol>>::default();
66 for &(feature_str, implications) in TARGET_FEATURE_IMPLICATIONS_RAW {
67 let feature = Symbol::intern(feature_str);
68 let implications = implications.iter().copied().map(Symbol::intern);
69 result.entry(feature).or_default().extend(implications);
73 }
74 let mut result = result
75 .into_iter()
76 .map(|(feature, implications)| (feature, Box::from_iter(implications)))
77 .collect::<FxHashMap<_, _>>();
78 result.shrink_to_fit();
79 result
80 });
81
82const TARGET_FEATURE_IMPLICATIONS_RAW: &[(&str, &[&str])] = &[
84 ("aes", &["neon"]),
86 ("dotprod", &["neon"]),
87 ("fp-armv8", &["vfp4"]),
88 ("fp16", &["neon"]),
89 ("i8mm", &["neon"]),
90 ("neon", &["vfp3"]),
91 ("sha2", &["neon"]),
92 ("v6", &["v5te"]),
93 ("v6k", &["v6"]),
94 ("v6t2", &["v6k", "thumb2"]),
95 ("v7", &["v6t2"]),
96 ("v8", &["v7"]),
97 ("vfp3", &["vfp2", "d32"]),
98 ("vfp4", &["vfp3"]),
99 ("aes", &["neon"]),
101 ("dotprod", &["neon"]),
102 ("dpb2", &["dpb"]),
103 ("f32mm", &["sve"]),
104 ("f64mm", &["sve"]),
105 ("fcma", &["neon"]),
106 ("fhm", &["fp16"]),
107 ("fp16", &["neon"]),
108 ("fp8", &["faminmax", "lut", "bf16"]),
109 ("fp8dot2", &["fp8dot4"]),
110 ("fp8dot4", &["fp8fma"]),
111 ("fp8fma", &["fp8"]),
112 ("jsconv", &["neon"]),
113 ("lse128", &["lse"]),
114 ("rcpc2", &["rcpc"]),
115 ("rcpc3", &["rcpc2"]),
116 ("rdm", &["neon"]),
117 ("sha2", &["neon"]),
118 ("sha3", &["sha2"]),
119 ("sm4", &["neon"]),
120 ("sme", &["bf16"]),
121 ("sme-b16b16", &["bf16", "sme2", "sve-b16b16"]),
122 ("sme-f16f16", &["sme2"]),
123 ("sme-f64f64", &["sme"]),
124 ("sme-f8f16", &["sme-f8f32"]),
125 ("sme-f8f32", &["sme2", "fp8"]),
126 ("sme-fa64", &["sme", "sve2"]),
127 ("sme-i16i64", &["sme"]),
128 ("sme2", &["sme"]),
129 ("sme2p1", &["sme2"]),
130 ("ssve-fp8dot2", &["ssve-fp8dot4"]),
131 ("ssve-fp8dot4", &["ssve-fp8fma"]),
132 ("ssve-fp8fma", &["sme2", "fp8"]),
133 ("sve", &["neon"]),
134 ("sve-b16b16", &["bf16"]),
135 ("sve2", &["sve"]),
136 ("sve2-aes", &["sve2", "aes"]),
137 ("sve2-bitperm", &["sve2"]),
138 ("sve2-sha3", &["sve2", "sha3"]),
139 ("sve2-sm4", &["sve2", "sm4"]),
140 ("sve2p1", &["sve2"]),
141 ("v8.1a", &["crc", "lse", "rdm", "pan", "lor", "vh"]),
142 ("v8.2a", &["v8.1a", "ras", "dpb"]),
143 ("v8.3a", &["v8.2a", "rcpc", "paca", "pacg", "jsconv"]),
144 ("v8.4a", &["v8.3a", "dotprod", "dit", "flagm"]),
145 ("v8.5a", &["v8.4a", "ssbs", "sb", "dpb2", "bti"]),
146 ("v8.6a", &["v8.5a", "bf16", "i8mm"]),
147 ("v8.7a", &["v8.6a", "wfxt"]),
148 ("v8.8a", &["v8.7a", "hbc", "mops"]),
149 ("v8.9a", &["v8.8a", "cssc"]),
150 ("v9.1a", &["v9a", "v8.6a"]),
151 ("v9.2a", &["v9.1a", "v8.7a"]),
152 ("v9.3a", &["v9.2a", "v8.8a"]),
153 ("v9.4a", &["v9.3a", "v8.9a"]),
154 ("v9.5a", &["v9.4a"]),
155 ("v9a", &["v8.5a", "sve2"]),
156 ("aes", &["sse2"]),
158 ("amx-bf16", &["amx-tile"]),
159 ("amx-complex", &["amx-tile"]),
160 ("amx-fp16", &["amx-tile"]),
161 ("amx-int8", &["amx-tile"]),
162 ("avx", &["sse4.2"]),
163 ("avx2", &["avx"]),
164 ("avx512bf16", &["avx512bw"]),
165 ("avx512bitalg", &["avx512bw"]),
166 ("avx512bw", &["avx512f"]),
167 ("avx512cd", &["avx512f"]),
168 ("avx512dq", &["avx512f"]),
169 ("avx512f", &["avx2", "fma", "f16c"]),
170 ("avx512fp16", &["avx512bw", "avx512vl", "avx512dq"]),
171 ("avx512ifma", &["avx512f"]),
172 ("avx512vbmi", &["avx512bw"]),
173 ("avx512vbmi2", &["avx512bw"]),
174 ("avx512vl", &["avx512f"]),
175 ("avx512vnni", &["avx512f"]),
176 ("avx512vp2intersect", &["avx512f"]),
177 ("avx512vpopcntdq", &["avx512f"]),
178 ("avxifma", &["avx2"]),
179 ("avxneconvert", &["avx2"]),
180 ("avxvnni", &["avx2"]),
181 ("avxvnniint16", &["avx2"]),
182 ("avxvnniint8", &["avx2"]),
183 ("f16c", &["avx"]),
184 ("fma", &["avx"]),
185 ("gfni", &["sse2"]),
186 ("kl", &["sse2"]),
187 ("pclmulqdq", &["sse2"]),
188 ("sha", &["sse2"]),
189 ("sha512", &["avx2"]),
190 ("sm3", &["avx"]),
191 ("sm4", &["avx2"]),
192 ("sse2", &["sse"]),
193 ("sse3", &["sse2"]),
194 ("sse4.1", &["ssse3"]),
195 ("sse4.2", &["sse4.1"]),
196 ("sse4a", &["sse3"]),
197 ("ssse3", &["sse3"]),
198 ("vaes", &["avx2", "aes"]),
199 ("vpclmulqdq", &["avx", "pclmulqdq"]),
200 ("widekl", &["kl"]),
201 ("xop", &["avx", "sse4a"]),
202 ("xsavec", &["xsave"]),
203 ("xsaveopt", &["xsave"]),
204 ("xsaves", &["xsave"]),
205 ("hvx-length128b", &["hvx"]),
207 ("power10-vector", &["power9-vector"]),
209 ("power8-altivec", &["altivec"]),
210 ("power8-crypto", &["power8-altivec"]),
211 ("power8-vector", &["vsx", "power8-altivec"]),
212 ("power9-altivec", &["power8-altivec"]),
213 ("power9-vector", &["power8-vector", "power9-altivec"]),
214 ("vsx", &["altivec"]),
215 ("a", &["zaamo", "zalrsc"]),
218 ("d", &["f"]),
219 ("zabha", &["zaamo"]),
220 ("zdinx", &["zfinx"]),
221 ("zfh", &["zfhmin"]),
222 ("zfhmin", &["f"]),
223 ("zhinx", &["zhinxmin"]),
224 ("zhinxmin", &["zfinx"]),
225 ("zk", &["zkn", "zkr", "zkt"]),
226 ("zkn", &["zbkb", "zbkc", "zbkx", "zkne", "zknd", "zknh"]),
227 ("zks", &["zbkb", "zbkc", "zbkx", "zksed", "zksh"]),
228 ("relaxed-simd", &["simd128"]),
230 ("alu32", &[]),
232 ("10e60", &["7e10"]),
234 ("2e3", &["e2"]),
235 ("3e3r2", &["3e3r1", "doloop"]),
236 ("3e3r3", &["doloop"]),
237 ("3e7", &["2e3"]),
238 ("7e10", &["3e7"]),
239 ("e1", &["elrw"]),
240 ("e2", &["e2"]),
241 ("mp", &["2e3"]),
242 ("mp1e2", &["3e7"]),
243 ("d", &["f"]),
245 ("lasx", &["lsx"]),
246 ("lsx", &["d"]),
247 ("nnp-assist", &["vector"]),
249 ("vector-enhancements-1", &["vector"]),
250 ("vector-enhancements-2", &["vector-enhancements-1"]),
251 ("vector-packed-decimal", &["vector"]),
252 ("vector-packed-decimal-enhancement", &["vector-packed-decimal"]),
253 ("vector-packed-decimal-enhancement-2", &["vector-packed-decimal-enhancement"]),
254 ("isa-68010", &["isa-68000"]),
257 ("isa-68020", &["isa-68010"]),
258 ("isa-68030", &["isa-68020"]),
259 ("isa-68040", &["isa-68030", "isa-68882"]),
260 ("isa-68060", &["isa-68040"]),
261 ("isa-68882", &["isa-68881"]),
262];
263