]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_codegen_ssa/src/target_features.rs
New upstream version 1.72.1+dfsg1
[rustc.git] / compiler / rustc_codegen_ssa / src / target_features.rs
CommitLineData
49aad941 1use crate::errors;
9c376795
FG
2use rustc_ast::ast;
3use rustc_attr::InstructionSetAttr;
4use rustc_data_structures::fx::FxHashMap;
353b0b11 5use rustc_data_structures::fx::FxIndexSet;
9c376795 6use rustc_errors::Applicability;
9ffffee4 7use rustc_hir::def::DefKind;
9c376795
FG
8use rustc_hir::def_id::DefId;
9use rustc_hir::def_id::LocalDefId;
29967ef6 10use rustc_hir::def_id::LOCAL_CRATE;
49aad941 11use rustc_middle::query::Providers;
353b0b11 12use rustc_middle::ty::TyCtxt;
9c376795 13use rustc_session::parse::feature_err;
29967ef6
XL
14use rustc_session::Session;
15use rustc_span::symbol::sym;
16use rustc_span::symbol::Symbol;
9c376795 17use rustc_span::Span;
29967ef6 18
5e7ed085
FG
19/// Features that control behaviour of rustc, rather than the codegen.
20pub 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 27const 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
61const 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
161const AARCH64_TIED_FEATURES: &[&[&str]] = &[
162 &["paca", "pacg"], // Together these represent `pauth` in LLVM
163];
5099ac24 164
29967ef6 165const 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
219const 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
226const 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 238const 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
246const 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
283const 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
298const 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!
304pub 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
318pub 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
333pub 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
340pub 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 423fn 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.
444pub 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
456pub(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}