]>
Commit | Line | Data |
---|---|---|
49aad941 | 1 | use crate::errors; |
9c376795 FG |
2 | use rustc_ast::ast; |
3 | use rustc_attr::InstructionSetAttr; | |
4 | use rustc_data_structures::fx::FxHashMap; | |
353b0b11 | 5 | use rustc_data_structures::fx::FxIndexSet; |
9c376795 | 6 | use rustc_errors::Applicability; |
9ffffee4 | 7 | use rustc_hir::def::DefKind; |
9c376795 FG |
8 | use rustc_hir::def_id::DefId; |
9 | use rustc_hir::def_id::LocalDefId; | |
29967ef6 | 10 | use rustc_hir::def_id::LOCAL_CRATE; |
49aad941 | 11 | use rustc_middle::query::Providers; |
353b0b11 | 12 | use rustc_middle::ty::TyCtxt; |
9c376795 | 13 | use rustc_session::parse::feature_err; |
29967ef6 XL |
14 | use rustc_session::Session; |
15 | use rustc_span::symbol::sym; | |
16 | use rustc_span::symbol::Symbol; | |
9c376795 | 17 | use rustc_span::Span; |
29967ef6 | 18 | |
5e7ed085 FG |
19 | /// Features that control behaviour of rustc, rather than the codegen. |
20 | pub const RUSTC_SPECIFIC_FEATURES: &[&str] = &["crt-static"]; | |
21 | ||
fc512014 XL |
22 | // When adding features to the below lists |
23 | // check whether they're named already elsewhere in rust | |
24 | // e.g. in stdarch and whether the given name matches LLVM's | |
25 | // if it doesn't, to_llvm_feature in llvm_util in rustc_codegen_llvm needs to be adapted | |
26 | ||
29967ef6 | 27 | const ARM_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[ |
2b03887a | 28 | // tidy-alphabetical-start |
29967ef6 | 29 | ("aclass", Some(sym::arm_target_feature)), |
2b03887a | 30 | ("aes", Some(sym::arm_target_feature)), |
29967ef6 XL |
31 | ("crc", Some(sym::arm_target_feature)), |
32 | ("crypto", Some(sym::arm_target_feature)), | |
2b03887a | 33 | ("d32", Some(sym::arm_target_feature)), |
3c0e092e | 34 | ("dotprod", Some(sym::arm_target_feature)), |
2b03887a FG |
35 | ("dsp", Some(sym::arm_target_feature)), |
36 | ("fp-armv8", Some(sym::arm_target_feature)), | |
37 | ("i8mm", Some(sym::arm_target_feature)), | |
38 | ("mclass", Some(sym::arm_target_feature)), | |
39 | ("neon", Some(sym::arm_target_feature)), | |
40 | ("rclass", Some(sym::arm_target_feature)), | |
41 | ("sha2", Some(sym::arm_target_feature)), | |
42 | // This is needed for inline assembly, but shouldn't be stabilized as-is | |
43 | // since it should be enabled per-function using #[instruction_set], not | |
44 | // #[target_feature]. | |
45 | ("thumb-mode", Some(sym::arm_target_feature)), | |
46 | ("thumb2", Some(sym::arm_target_feature)), | |
fe692bf9 | 47 | ("trustzone", Some(sym::arm_target_feature)), |
29967ef6 XL |
48 | ("v5te", Some(sym::arm_target_feature)), |
49 | ("v6", Some(sym::arm_target_feature)), | |
50 | ("v6k", Some(sym::arm_target_feature)), | |
51 | ("v6t2", Some(sym::arm_target_feature)), | |
52 | ("v7", Some(sym::arm_target_feature)), | |
53 | ("v8", Some(sym::arm_target_feature)), | |
54 | ("vfp2", Some(sym::arm_target_feature)), | |
55 | ("vfp3", Some(sym::arm_target_feature)), | |
56 | ("vfp4", Some(sym::arm_target_feature)), | |
fe692bf9 | 57 | ("virtualization", Some(sym::arm_target_feature)), |
2b03887a | 58 | // tidy-alphabetical-end |
29967ef6 XL |
59 | ]; |
60 | ||
61 | const AARCH64_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[ | |
2b03887a FG |
62 | // tidy-alphabetical-start |
63 | // FEAT_AES | |
64 | ("aes", None), | |
65 | // FEAT_BF16 | |
66 | ("bf16", None), | |
67 | // FEAT_BTI | |
68 | ("bti", None), | |
17df50a5 | 69 | // FEAT_CRC |
5e7ed085 | 70 | ("crc", None), |
17df50a5 | 71 | // FEAT_DIT |
5e7ed085 | 72 | ("dit", None), |
2b03887a FG |
73 | // FEAT_DotProd |
74 | ("dotprod", None), | |
17df50a5 | 75 | // FEAT_DPB |
5e7ed085 | 76 | ("dpb", None), |
17df50a5 | 77 | // FEAT_DPB2 |
5e7ed085 | 78 | ("dpb2", None), |
17df50a5 | 79 | // FEAT_F32MM |
5e7ed085 | 80 | ("f32mm", None), |
17df50a5 | 81 | // FEAT_F64MM |
5e7ed085 | 82 | ("f64mm", None), |
17df50a5 | 83 | // FEAT_FCMA |
5e7ed085 | 84 | ("fcma", None), |
2b03887a FG |
85 | // FEAT_FHM |
86 | ("fhm", None), | |
87 | // FEAT_FLAGM | |
88 | ("flagm", None), | |
89 | // FEAT_FP16 | |
90 | ("fp16", None), | |
91 | // FEAT_FRINTTS | |
92 | ("frintts", None), | |
93 | // FEAT_I8MM | |
94 | ("i8mm", None), | |
95 | // FEAT_JSCVT | |
96 | ("jsconv", None), | |
97 | // FEAT_LOR | |
98 | ("lor", None), | |
99 | // FEAT_LSE | |
100 | ("lse", None), | |
101 | // FEAT_MTE | |
102 | ("mte", None), | |
103 | // FEAT_AdvSimd & FEAT_FP | |
104 | ("neon", None), | |
105 | // FEAT_PAUTH (address authentication) | |
106 | ("paca", None), | |
107 | // FEAT_PAUTH (generic authentication) | |
108 | ("pacg", None), | |
109 | // FEAT_PAN | |
110 | ("pan", None), | |
111 | // FEAT_PMUv3 | |
112 | ("pmuv3", None), | |
113 | // FEAT_RAND | |
114 | ("rand", None), | |
115 | // FEAT_RAS | |
116 | ("ras", None), | |
117 | // FEAT_RCPC | |
118 | ("rcpc", None), | |
119 | // FEAT_RCPC2 | |
120 | ("rcpc2", None), | |
121 | // FEAT_RDM | |
122 | ("rdm", None), | |
123 | // FEAT_SB | |
124 | ("sb", None), | |
17df50a5 | 125 | // FEAT_SHA1 & FEAT_SHA256 |
5e7ed085 | 126 | ("sha2", None), |
17df50a5 | 127 | // FEAT_SHA512 & FEAT_SHA3 |
5e7ed085 | 128 | ("sha3", None), |
17df50a5 | 129 | // FEAT_SM3 & FEAT_SM4 |
5e7ed085 | 130 | ("sm4", None), |
3c0e092e | 131 | // FEAT_SPE |
5e7ed085 | 132 | ("spe", None), |
2b03887a FG |
133 | // FEAT_SSBS |
134 | ("ssbs", None), | |
135 | // FEAT_SVE | |
136 | ("sve", None), | |
137 | // FEAT_SVE2 | |
138 | ("sve2", None), | |
139 | // FEAT_SVE2_AES | |
140 | ("sve2-aes", None), | |
141 | // FEAT_SVE2_BitPerm | |
142 | ("sve2-bitperm", None), | |
143 | // FEAT_SVE2_SHA3 | |
144 | ("sve2-sha3", None), | |
145 | // FEAT_SVE2_SM4 | |
146 | ("sve2-sm4", None), | |
147 | // FEAT_TME | |
148 | ("tme", None), | |
5e7ed085 FG |
149 | ("v8.1a", Some(sym::aarch64_ver_target_feature)), |
150 | ("v8.2a", Some(sym::aarch64_ver_target_feature)), | |
151 | ("v8.3a", Some(sym::aarch64_ver_target_feature)), | |
152 | ("v8.4a", Some(sym::aarch64_ver_target_feature)), | |
153 | ("v8.5a", Some(sym::aarch64_ver_target_feature)), | |
154 | ("v8.6a", Some(sym::aarch64_ver_target_feature)), | |
155 | ("v8.7a", Some(sym::aarch64_ver_target_feature)), | |
2b03887a FG |
156 | // FEAT_VHE |
157 | ("vh", None), | |
158 | // tidy-alphabetical-end | |
29967ef6 XL |
159 | ]; |
160 | ||
5e7ed085 FG |
161 | const AARCH64_TIED_FEATURES: &[&[&str]] = &[ |
162 | &["paca", "pacg"], // Together these represent `pauth` in LLVM | |
163 | ]; | |
5099ac24 | 164 | |
29967ef6 | 165 | const X86_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[ |
2b03887a | 166 | // tidy-alphabetical-start |
5e7ed085 | 167 | ("adx", None), |
29967ef6 XL |
168 | ("aes", None), |
169 | ("avx", None), | |
170 | ("avx2", None), | |
fc512014 XL |
171 | ("avx512bf16", Some(sym::avx512_target_feature)), |
172 | ("avx512bitalg", Some(sym::avx512_target_feature)), | |
29967ef6 XL |
173 | ("avx512bw", Some(sym::avx512_target_feature)), |
174 | ("avx512cd", Some(sym::avx512_target_feature)), | |
175 | ("avx512dq", Some(sym::avx512_target_feature)), | |
176 | ("avx512er", Some(sym::avx512_target_feature)), | |
177 | ("avx512f", Some(sym::avx512_target_feature)), | |
178 | ("avx512ifma", Some(sym::avx512_target_feature)), | |
179 | ("avx512pf", Some(sym::avx512_target_feature)), | |
180 | ("avx512vbmi", Some(sym::avx512_target_feature)), | |
fc512014 | 181 | ("avx512vbmi2", Some(sym::avx512_target_feature)), |
29967ef6 | 182 | ("avx512vl", Some(sym::avx512_target_feature)), |
fc512014 XL |
183 | ("avx512vnni", Some(sym::avx512_target_feature)), |
184 | ("avx512vp2intersect", Some(sym::avx512_target_feature)), | |
29967ef6 XL |
185 | ("avx512vpopcntdq", Some(sym::avx512_target_feature)), |
186 | ("bmi1", None), | |
187 | ("bmi2", None), | |
9ffffee4 | 188 | ("cmpxchg16b", None), |
29967ef6 | 189 | ("ermsb", Some(sym::ermsb_target_feature)), |
9c376795 | 190 | ("f16c", None), |
29967ef6 XL |
191 | ("fma", None), |
192 | ("fxsr", None), | |
487cf647 | 193 | ("gfni", Some(sym::avx512_target_feature)), |
29967ef6 | 194 | ("lzcnt", None), |
353b0b11 | 195 | ("movbe", None), |
29967ef6 XL |
196 | ("pclmulqdq", None), |
197 | ("popcnt", None), | |
198 | ("rdrand", None), | |
199 | ("rdseed", None), | |
200 | ("rtm", Some(sym::rtm_target_feature)), | |
201 | ("sha", None), | |
202 | ("sse", None), | |
203 | ("sse2", None), | |
204 | ("sse3", None), | |
205 | ("sse4.1", None), | |
206 | ("sse4.2", None), | |
207 | ("sse4a", Some(sym::sse4a_target_feature)), | |
208 | ("ssse3", None), | |
209 | ("tbm", Some(sym::tbm_target_feature)), | |
487cf647 FG |
210 | ("vaes", Some(sym::avx512_target_feature)), |
211 | ("vpclmulqdq", Some(sym::avx512_target_feature)), | |
29967ef6 XL |
212 | ("xsave", None), |
213 | ("xsavec", None), | |
214 | ("xsaveopt", None), | |
215 | ("xsaves", None), | |
2b03887a | 216 | // tidy-alphabetical-end |
29967ef6 XL |
217 | ]; |
218 | ||
219 | const HEXAGON_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[ | |
2b03887a | 220 | // tidy-alphabetical-start |
29967ef6 XL |
221 | ("hvx", Some(sym::hexagon_target_feature)), |
222 | ("hvx-length128b", Some(sym::hexagon_target_feature)), | |
2b03887a | 223 | // tidy-alphabetical-end |
29967ef6 XL |
224 | ]; |
225 | ||
226 | const POWERPC_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[ | |
2b03887a | 227 | // tidy-alphabetical-start |
29967ef6 | 228 | ("altivec", Some(sym::powerpc_target_feature)), |
487cf647 | 229 | ("power10-vector", Some(sym::powerpc_target_feature)), |
29967ef6 | 230 | ("power8-altivec", Some(sym::powerpc_target_feature)), |
29967ef6 | 231 | ("power8-vector", Some(sym::powerpc_target_feature)), |
2b03887a | 232 | ("power9-altivec", Some(sym::powerpc_target_feature)), |
29967ef6 XL |
233 | ("power9-vector", Some(sym::powerpc_target_feature)), |
234 | ("vsx", Some(sym::powerpc_target_feature)), | |
2b03887a | 235 | // tidy-alphabetical-end |
29967ef6 XL |
236 | ]; |
237 | ||
f2b60f7d | 238 | const MIPS_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[ |
2b03887a | 239 | // tidy-alphabetical-start |
f2b60f7d FG |
240 | ("fp64", Some(sym::mips_target_feature)), |
241 | ("msa", Some(sym::mips_target_feature)), | |
242 | ("virt", Some(sym::mips_target_feature)), | |
2b03887a | 243 | // tidy-alphabetical-end |
f2b60f7d | 244 | ]; |
29967ef6 XL |
245 | |
246 | const RISCV_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[ | |
2b03887a | 247 | // tidy-alphabetical-start |
29967ef6 XL |
248 | ("a", Some(sym::riscv_target_feature)), |
249 | ("c", Some(sym::riscv_target_feature)), | |
29967ef6 XL |
250 | ("d", Some(sym::riscv_target_feature)), |
251 | ("e", Some(sym::riscv_target_feature)), | |
2b03887a FG |
252 | ("f", Some(sym::riscv_target_feature)), |
253 | ("m", Some(sym::riscv_target_feature)), | |
353b0b11 | 254 | ("relax", Some(sym::riscv_target_feature)), |
49aad941 | 255 | ("unaligned-scalar-mem", Some(sym::riscv_target_feature)), |
5e7ed085 | 256 | ("v", Some(sym::riscv_target_feature)), |
f2b60f7d FG |
257 | ("zba", Some(sym::riscv_target_feature)), |
258 | ("zbb", Some(sym::riscv_target_feature)), | |
259 | ("zbc", Some(sym::riscv_target_feature)), | |
5e7ed085 FG |
260 | ("zbkb", Some(sym::riscv_target_feature)), |
261 | ("zbkc", Some(sym::riscv_target_feature)), | |
262 | ("zbkx", Some(sym::riscv_target_feature)), | |
2b03887a FG |
263 | ("zbs", Some(sym::riscv_target_feature)), |
264 | ("zdinx", Some(sym::riscv_target_feature)), | |
265 | ("zfh", Some(sym::riscv_target_feature)), | |
266 | ("zfhmin", Some(sym::riscv_target_feature)), | |
267 | ("zfinx", Some(sym::riscv_target_feature)), | |
268 | ("zhinx", Some(sym::riscv_target_feature)), | |
269 | ("zhinxmin", Some(sym::riscv_target_feature)), | |
270 | ("zk", Some(sym::riscv_target_feature)), | |
271 | ("zkn", Some(sym::riscv_target_feature)), | |
5e7ed085 FG |
272 | ("zknd", Some(sym::riscv_target_feature)), |
273 | ("zkne", Some(sym::riscv_target_feature)), | |
274 | ("zknh", Some(sym::riscv_target_feature)), | |
5e7ed085 | 275 | ("zkr", Some(sym::riscv_target_feature)), |
5e7ed085 | 276 | ("zks", Some(sym::riscv_target_feature)), |
2b03887a FG |
277 | ("zksed", Some(sym::riscv_target_feature)), |
278 | ("zksh", Some(sym::riscv_target_feature)), | |
5e7ed085 | 279 | ("zkt", Some(sym::riscv_target_feature)), |
2b03887a | 280 | // tidy-alphabetical-end |
29967ef6 XL |
281 | ]; |
282 | ||
283 | const WASM_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[ | |
2b03887a | 284 | // tidy-alphabetical-start |
29967ef6 | 285 | ("atomics", Some(sym::wasm_target_feature)), |
923072b8 | 286 | ("bulk-memory", Some(sym::wasm_target_feature)), |
fe692bf9 | 287 | ("exception-handling", Some(sym::wasm_target_feature)), |
487cf647 | 288 | ("multivalue", Some(sym::wasm_target_feature)), |
923072b8 | 289 | ("mutable-globals", Some(sym::wasm_target_feature)), |
2b03887a | 290 | ("nontrapping-fptoint", Some(sym::wasm_target_feature)), |
923072b8 | 291 | ("reference-types", Some(sym::wasm_target_feature)), |
9ffffee4 | 292 | ("relaxed-simd", Some(sym::wasm_target_feature)), |
064997fb | 293 | ("sign-ext", Some(sym::wasm_target_feature)), |
2b03887a FG |
294 | ("simd128", None), |
295 | // tidy-alphabetical-end | |
29967ef6 XL |
296 | ]; |
297 | ||
17df50a5 XL |
298 | const BPF_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[("alu32", Some(sym::bpf_target_feature))]; |
299 | ||
29967ef6 XL |
300 | /// When rustdoc is running, provide a list of all known features so that all their respective |
301 | /// primitives may be documented. | |
302 | /// | |
303 | /// IMPORTANT: If you're adding another feature list above, make sure to add it to this iterator! | |
304 | pub fn all_known_features() -> impl Iterator<Item = (&'static str, Option<Symbol>)> { | |
305 | std::iter::empty() | |
306 | .chain(ARM_ALLOWED_FEATURES.iter()) | |
307 | .chain(AARCH64_ALLOWED_FEATURES.iter()) | |
308 | .chain(X86_ALLOWED_FEATURES.iter()) | |
309 | .chain(HEXAGON_ALLOWED_FEATURES.iter()) | |
310 | .chain(POWERPC_ALLOWED_FEATURES.iter()) | |
311 | .chain(MIPS_ALLOWED_FEATURES.iter()) | |
312 | .chain(RISCV_ALLOWED_FEATURES.iter()) | |
313 | .chain(WASM_ALLOWED_FEATURES.iter()) | |
17df50a5 | 314 | .chain(BPF_ALLOWED_FEATURES.iter()) |
29967ef6 XL |
315 | .cloned() |
316 | } | |
317 | ||
318 | pub fn supported_target_features(sess: &Session) -> &'static [(&'static str, Option<Symbol>)] { | |
319 | match &*sess.target.arch { | |
320 | "arm" => ARM_ALLOWED_FEATURES, | |
321 | "aarch64" => AARCH64_ALLOWED_FEATURES, | |
322 | "x86" | "x86_64" => X86_ALLOWED_FEATURES, | |
323 | "hexagon" => HEXAGON_ALLOWED_FEATURES, | |
324 | "mips" | "mips64" => MIPS_ALLOWED_FEATURES, | |
325 | "powerpc" | "powerpc64" => POWERPC_ALLOWED_FEATURES, | |
326 | "riscv32" | "riscv64" => RISCV_ALLOWED_FEATURES, | |
cdc7bbd5 | 327 | "wasm32" | "wasm64" => WASM_ALLOWED_FEATURES, |
17df50a5 | 328 | "bpf" => BPF_ALLOWED_FEATURES, |
29967ef6 XL |
329 | _ => &[], |
330 | } | |
331 | } | |
332 | ||
5099ac24 FG |
333 | pub fn tied_target_features(sess: &Session) -> &'static [&'static [&'static str]] { |
334 | match &*sess.target.arch { | |
335 | "aarch64" => AARCH64_TIED_FEATURES, | |
336 | _ => &[], | |
337 | } | |
338 | } | |
339 | ||
9c376795 FG |
340 | pub fn from_target_feature( |
341 | tcx: TyCtxt<'_>, | |
342 | attr: &ast::Attribute, | |
343 | supported_target_features: &FxHashMap<String, Option<Symbol>>, | |
344 | target_features: &mut Vec<Symbol>, | |
345 | ) { | |
346 | let Some(list) = attr.meta_item_list() else { return }; | |
347 | let bad_item = |span| { | |
348 | let msg = "malformed `target_feature` attribute input"; | |
349 | let code = "enable = \"..\""; | |
350 | tcx.sess | |
351 | .struct_span_err(span, msg) | |
352 | .span_suggestion(span, "must be of the form", code, Applicability::HasPlaceholders) | |
353 | .emit(); | |
29967ef6 | 354 | }; |
9c376795 FG |
355 | let rust_features = tcx.features(); |
356 | for item in list { | |
357 | // Only `enable = ...` is accepted in the meta-item list. | |
358 | if !item.has_name(sym::enable) { | |
359 | bad_item(item.span()); | |
360 | continue; | |
361 | } | |
362 | ||
363 | // Must be of the form `enable = "..."` (a string). | |
364 | let Some(value) = item.value_str() else { | |
365 | bad_item(item.span()); | |
366 | continue; | |
367 | }; | |
368 | ||
369 | // We allow comma separation to enable multiple features. | |
370 | target_features.extend(value.as_str().split(',').filter_map(|feature| { | |
371 | let Some(feature_gate) = supported_target_features.get(feature) else { | |
372 | let msg = | |
373 | format!("the feature named `{}` is not valid for this target", feature); | |
49aad941 | 374 | let mut err = tcx.sess.struct_span_err(item.span(), msg); |
9c376795 FG |
375 | err.span_label( |
376 | item.span(), | |
377 | format!("`{}` is not valid for this target", feature), | |
378 | ); | |
379 | if let Some(stripped) = feature.strip_prefix('+') { | |
380 | let valid = supported_target_features.contains_key(stripped); | |
381 | if valid { | |
382 | err.help("consider removing the leading `+` in the feature name"); | |
383 | } | |
384 | } | |
385 | err.emit(); | |
386 | return None; | |
387 | }; | |
388 | ||
389 | // Only allow features whose feature gates have been enabled. | |
390 | let allowed = match feature_gate.as_ref().copied() { | |
391 | Some(sym::arm_target_feature) => rust_features.arm_target_feature, | |
392 | Some(sym::hexagon_target_feature) => rust_features.hexagon_target_feature, | |
393 | Some(sym::powerpc_target_feature) => rust_features.powerpc_target_feature, | |
394 | Some(sym::mips_target_feature) => rust_features.mips_target_feature, | |
395 | Some(sym::riscv_target_feature) => rust_features.riscv_target_feature, | |
396 | Some(sym::avx512_target_feature) => rust_features.avx512_target_feature, | |
397 | Some(sym::sse4a_target_feature) => rust_features.sse4a_target_feature, | |
398 | Some(sym::tbm_target_feature) => rust_features.tbm_target_feature, | |
399 | Some(sym::wasm_target_feature) => rust_features.wasm_target_feature, | |
9c376795 FG |
400 | Some(sym::rtm_target_feature) => rust_features.rtm_target_feature, |
401 | Some(sym::ermsb_target_feature) => rust_features.ermsb_target_feature, | |
402 | Some(sym::bpf_target_feature) => rust_features.bpf_target_feature, | |
403 | Some(sym::aarch64_ver_target_feature) => rust_features.aarch64_ver_target_feature, | |
404 | Some(name) => bug!("unknown target feature gate {}", name), | |
405 | None => true, | |
406 | }; | |
407 | if !allowed { | |
408 | feature_err( | |
409 | &tcx.sess.parse_sess, | |
410 | feature_gate.unwrap(), | |
411 | item.span(), | |
49aad941 | 412 | format!("the target feature `{}` is currently unstable", feature), |
9c376795 FG |
413 | ) |
414 | .emit(); | |
415 | } | |
416 | Some(Symbol::intern(feature)) | |
417 | })); | |
418 | } | |
419 | } | |
420 | ||
421 | /// Computes the set of target features used in a function for the purposes of | |
422 | /// inline assembly. | |
353b0b11 | 423 | fn asm_target_features(tcx: TyCtxt<'_>, did: DefId) -> &FxIndexSet<Symbol> { |
9c376795 FG |
424 | let mut target_features = tcx.sess.unstable_target_features.clone(); |
425 | if tcx.def_kind(did).has_codegen_attrs() { | |
426 | let attrs = tcx.codegen_fn_attrs(did); | |
427 | target_features.extend(&attrs.target_features); | |
428 | match attrs.instruction_set { | |
429 | None => {} | |
430 | Some(InstructionSetAttr::ArmA32) => { | |
431 | target_features.remove(&sym::thumb_mode); | |
432 | } | |
433 | Some(InstructionSetAttr::ArmT32) => { | |
434 | target_features.insert(sym::thumb_mode); | |
435 | } | |
436 | } | |
437 | } | |
438 | ||
439 | tcx.arena.alloc(target_features) | |
440 | } | |
441 | ||
442 | /// Checks the function annotated with `#[target_feature]` is not a safe | |
443 | /// trait method implementation, reporting an error if it is. | |
444 | pub fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId, attr_span: Span) { | |
9ffffee4 FG |
445 | if let DefKind::AssocFn = tcx.def_kind(id) { |
446 | let parent_id = tcx.local_parent(id); | |
353b0b11 | 447 | if let DefKind::Trait | DefKind::Impl { of_trait: true } = tcx.def_kind(parent_id) { |
49aad941 FG |
448 | tcx.sess.emit_err(errors::TargetFeatureSafeTrait { |
449 | span: attr_span, | |
450 | def: tcx.def_span(id), | |
451 | }); | |
9c376795 FG |
452 | } |
453 | } | |
454 | } | |
455 | ||
456 | pub(crate) fn provide(providers: &mut Providers) { | |
457 | *providers = Providers { | |
458 | supported_target_features: |tcx, cnum| { | |
459 | assert_eq!(cnum, LOCAL_CRATE); | |
460 | if tcx.sess.opts.actually_rustdoc { | |
461 | // rustdoc needs to be able to document functions that use all the features, so | |
462 | // whitelist them all | |
463 | all_known_features().map(|(a, b)| (a.to_string(), b)).collect() | |
464 | } else { | |
465 | supported_target_features(tcx.sess) | |
466 | .iter() | |
467 | .map(|&(a, b)| (a.to_string(), b)) | |
468 | .collect() | |
469 | } | |
470 | }, | |
471 | asm_target_features, | |
472 | ..*providers | |
473 | } | |
29967ef6 | 474 | } |