1 //===--- AArch64.cpp - Implement AArch64 target feature support -----------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements AArch64 TargetInfo objects.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "AArch64.h"
14 #include "clang/Basic/LangOptions.h"
15 #include "clang/Basic/TargetBuiltins.h"
16 #include "clang/Basic/TargetInfo.h"
17 #include "llvm/ADT/ArrayRef.h"
18 #include "llvm/ADT/StringExtras.h"
19 #include "llvm/ADT/StringSwitch.h"
20 #include "llvm/Support/AArch64TargetParser.h"
21 #include "llvm/Support/ARMTargetParserCommon.h"
22 #include <optional>
23
24 using namespace clang;
25 using namespace clang::targets;
26
27 static constexpr Builtin::Info BuiltinInfo[] = {
28 #define BUILTIN(ID, TYPE, ATTRS) \
29 {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
30 #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
31 {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
32 #include "clang/Basic/BuiltinsNEON.def"
33
34 #define BUILTIN(ID, TYPE, ATTRS) \
35 {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
36 #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
37 {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
38 #include "clang/Basic/BuiltinsSVE.def"
39
40 #define BUILTIN(ID, TYPE, ATTRS) \
41 {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
42 #define LANGBUILTIN(ID, TYPE, ATTRS, LANG) \
43 {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, LANG},
44 #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
45 {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
46 #define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \
47 {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::HEADER, LANGS},
48 #include "clang/Basic/BuiltinsAArch64.def"
49 };
50
setArchFeatures()51 void AArch64TargetInfo::setArchFeatures() {
52 if (*ArchInfo == llvm::AArch64::ARMV8R) {
53 HasDotProd = true;
54 HasDIT = true;
55 HasFlagM = true;
56 HasRCPC = true;
57 FPU |= NeonMode;
58 HasCCPP = true;
59 HasCRC = true;
60 HasLSE = true;
61 HasRDM = true;
62 } else if (ArchInfo->Version.getMajor() == 8) {
63 if (ArchInfo->Version.getMinor() >= 7u) {
64 HasWFxT = true;
65 }
66 if (ArchInfo->Version.getMinor() >= 6u) {
67 HasBFloat16 = true;
68 HasMatMul = true;
69 }
70 if (ArchInfo->Version.getMinor() >= 5u) {
71 HasAlternativeNZCV = true;
72 HasFRInt3264 = true;
73 HasSSBS = true;
74 HasSB = true;
75 HasPredRes = true;
76 HasBTI = true;
77 }
78 if (ArchInfo->Version.getMinor() >= 4u) {
79 HasDotProd = true;
80 HasDIT = true;
81 HasFlagM = true;
82 }
83 if (ArchInfo->Version.getMinor() >= 3u) {
84 HasRCPC = true;
85 FPU |= NeonMode;
86 }
87 if (ArchInfo->Version.getMinor() >= 2u) {
88 HasCCPP = true;
89 }
90 if (ArchInfo->Version.getMinor() >= 1u) {
91 HasCRC = true;
92 HasLSE = true;
93 HasRDM = true;
94 }
95 } else if (ArchInfo->Version.getMajor() == 9) {
96 if (ArchInfo->Version.getMinor() >= 2u) {
97 HasWFxT = true;
98 }
99 if (ArchInfo->Version.getMinor() >= 1u) {
100 HasBFloat16 = true;
101 HasMatMul = true;
102 }
103 FPU |= SveMode;
104 HasSVE2 = true;
105 HasFullFP16 = true;
106 HasAlternativeNZCV = true;
107 HasFRInt3264 = true;
108 HasSSBS = true;
109 HasSB = true;
110 HasPredRes = true;
111 HasBTI = true;
112 HasDotProd = true;
113 HasDIT = true;
114 HasFlagM = true;
115 HasRCPC = true;
116 FPU |= NeonMode;
117 HasCCPP = true;
118 HasCRC = true;
119 HasLSE = true;
120 HasRDM = true;
121 }
122 }
123
AArch64TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)124 AArch64TargetInfo::AArch64TargetInfo(const llvm::Triple &Triple,
125 const TargetOptions &Opts)
126 : TargetInfo(Triple), ABI("aapcs") {
127 if (getTriple().isOSOpenBSD()) {
128 Int64Type = SignedLongLong;
129 IntMaxType = SignedLongLong;
130 } else {
131 if (!getTriple().isOSDarwin() && !getTriple().isOSNetBSD())
132 WCharType = UnsignedInt;
133
134 Int64Type = SignedLong;
135 IntMaxType = SignedLong;
136 }
137
138 // All AArch64 implementations support ARMv8 FP, which makes half a legal type.
139 HasLegalHalfType = true;
140 HalfArgsAndReturns = true;
141 HasFloat16 = true;
142 HasStrictFP = true;
143
144 if (Triple.isArch64Bit())
145 LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
146 else
147 LongWidth = LongAlign = PointerWidth = PointerAlign = 32;
148
149 MaxVectorAlign = 128;
150 MaxAtomicInlineWidth = 128;
151 MaxAtomicPromoteWidth = 128;
152
153 LongDoubleWidth = LongDoubleAlign = SuitableAlign = 128;
154 LongDoubleFormat = &llvm::APFloat::IEEEquad();
155
156 BFloat16Width = BFloat16Align = 16;
157 BFloat16Format = &llvm::APFloat::BFloat();
158
159 // Make __builtin_ms_va_list available.
160 HasBuiltinMSVaList = true;
161
162 // Make the SVE types available. Note that this deliberately doesn't
163 // depend on SveMode, since in principle it should be possible to turn
164 // SVE on and off within a translation unit. It should also be possible
165 // to compile the global declaration:
166 //
167 // __SVInt8_t *ptr;
168 //
169 // even without SVE.
170 HasAArch64SVETypes = true;
171
172 // {} in inline assembly are neon specifiers, not assembly variant
173 // specifiers.
174 NoAsmVariants = true;
175
176 // AAPCS gives rules for bitfields. 7.1.7 says: "The container type
177 // contributes to the alignment of the containing aggregate in the same way
178 // a plain (non bit-field) member of that type would, without exception for
179 // zero-sized or anonymous bit-fields."
180 assert(UseBitFieldTypeAlignment && "bitfields affect type alignment");
181 UseZeroLengthBitfieldAlignment = true;
182
183 // AArch64 targets default to using the ARM C++ ABI.
184 TheCXXABI.set(TargetCXXABI::GenericAArch64);
185
186 if (Triple.getOS() == llvm::Triple::Linux)
187 this->MCountName = "\01_mcount";
188 else if (Triple.getOS() == llvm::Triple::UnknownOS)
189 this->MCountName =
190 Opts.EABIVersion == llvm::EABI::GNU ? "\01_mcount" : "mcount";
191 }
192
getABI() const193 StringRef AArch64TargetInfo::getABI() const { return ABI; }
194
setABI(const std::string & Name)195 bool AArch64TargetInfo::setABI(const std::string &Name) {
196 if (Name != "aapcs" && Name != "darwinpcs")
197 return false;
198
199 ABI = Name;
200 return true;
201 }
202
validateBranchProtection(StringRef Spec,StringRef,BranchProtectionInfo & BPI,StringRef & Err) const203 bool AArch64TargetInfo::validateBranchProtection(StringRef Spec, StringRef,
204 BranchProtectionInfo &BPI,
205 StringRef &Err) const {
206 llvm::ARM::ParsedBranchProtection PBP;
207 if (!llvm::ARM::parseBranchProtection(Spec, PBP, Err))
208 return false;
209
210 BPI.SignReturnAddr =
211 llvm::StringSwitch<LangOptions::SignReturnAddressScopeKind>(PBP.Scope)
212 .Case("non-leaf", LangOptions::SignReturnAddressScopeKind::NonLeaf)
213 .Case("all", LangOptions::SignReturnAddressScopeKind::All)
214 .Default(LangOptions::SignReturnAddressScopeKind::None);
215
216 if (PBP.Key == "a_key")
217 BPI.SignKey = LangOptions::SignReturnAddressKeyKind::AKey;
218 else
219 BPI.SignKey = LangOptions::SignReturnAddressKeyKind::BKey;
220
221 BPI.BranchTargetEnforcement = PBP.BranchTargetEnforcement;
222 return true;
223 }
224
isValidCPUName(StringRef Name) const225 bool AArch64TargetInfo::isValidCPUName(StringRef Name) const {
226 return Name == "generic" ||
227 llvm::AArch64::parseCpu(Name).Arch != llvm::AArch64::INVALID;
228 }
229
setCPU(const std::string & Name)230 bool AArch64TargetInfo::setCPU(const std::string &Name) {
231 return isValidCPUName(Name);
232 }
233
fillValidCPUList(SmallVectorImpl<StringRef> & Values) const234 void AArch64TargetInfo::fillValidCPUList(
235 SmallVectorImpl<StringRef> &Values) const {
236 llvm::AArch64::fillValidCPUArchList(Values);
237 }
238
getTargetDefinesARMV81A(const LangOptions & Opts,MacroBuilder & Builder) const239 void AArch64TargetInfo::getTargetDefinesARMV81A(const LangOptions &Opts,
240 MacroBuilder &Builder) const {
241 Builder.defineMacro("__ARM_FEATURE_QRDMX", "1");
242 Builder.defineMacro("__ARM_FEATURE_ATOMICS", "1");
243 Builder.defineMacro("__ARM_FEATURE_CRC32", "1");
244 }
245
getTargetDefinesARMV82A(const LangOptions & Opts,MacroBuilder & Builder) const246 void AArch64TargetInfo::getTargetDefinesARMV82A(const LangOptions &Opts,
247 MacroBuilder &Builder) const {
248 // Also include the ARMv8.1 defines
249 getTargetDefinesARMV81A(Opts, Builder);
250 }
251
getTargetDefinesARMV83A(const LangOptions & Opts,MacroBuilder & Builder) const252 void AArch64TargetInfo::getTargetDefinesARMV83A(const LangOptions &Opts,
253 MacroBuilder &Builder) const {
254 Builder.defineMacro("__ARM_FEATURE_COMPLEX", "1");
255 Builder.defineMacro("__ARM_FEATURE_JCVT", "1");
256 Builder.defineMacro("__ARM_FEATURE_PAUTH", "1");
257 // Also include the Armv8.2 defines
258 getTargetDefinesARMV82A(Opts, Builder);
259 }
260
getTargetDefinesARMV84A(const LangOptions & Opts,MacroBuilder & Builder) const261 void AArch64TargetInfo::getTargetDefinesARMV84A(const LangOptions &Opts,
262 MacroBuilder &Builder) const {
263 // Also include the Armv8.3 defines
264 getTargetDefinesARMV83A(Opts, Builder);
265 }
266
getTargetDefinesARMV85A(const LangOptions & Opts,MacroBuilder & Builder) const267 void AArch64TargetInfo::getTargetDefinesARMV85A(const LangOptions &Opts,
268 MacroBuilder &Builder) const {
269 Builder.defineMacro("__ARM_FEATURE_FRINT", "1");
270 Builder.defineMacro("__ARM_FEATURE_BTI", "1");
271 // Also include the Armv8.4 defines
272 getTargetDefinesARMV84A(Opts, Builder);
273 }
274
getTargetDefinesARMV86A(const LangOptions & Opts,MacroBuilder & Builder) const275 void AArch64TargetInfo::getTargetDefinesARMV86A(const LangOptions &Opts,
276 MacroBuilder &Builder) const {
277 // Also include the Armv8.5 defines
278 // FIXME: Armv8.6 makes the following extensions mandatory:
279 // - __ARM_FEATURE_BF16
280 // - __ARM_FEATURE_MATMUL_INT8
281 // Handle them here.
282 getTargetDefinesARMV85A(Opts, Builder);
283 }
284
getTargetDefinesARMV87A(const LangOptions & Opts,MacroBuilder & Builder) const285 void AArch64TargetInfo::getTargetDefinesARMV87A(const LangOptions &Opts,
286 MacroBuilder &Builder) const {
287 // Also include the Armv8.6 defines
288 getTargetDefinesARMV86A(Opts, Builder);
289 }
290
getTargetDefinesARMV88A(const LangOptions & Opts,MacroBuilder & Builder) const291 void AArch64TargetInfo::getTargetDefinesARMV88A(const LangOptions &Opts,
292 MacroBuilder &Builder) const {
293 // Also include the Armv8.7 defines
294 getTargetDefinesARMV87A(Opts, Builder);
295 }
296
getTargetDefinesARMV89A(const LangOptions & Opts,MacroBuilder & Builder) const297 void AArch64TargetInfo::getTargetDefinesARMV89A(const LangOptions &Opts,
298 MacroBuilder &Builder) const {
299 // Also include the Armv8.8 defines
300 getTargetDefinesARMV88A(Opts, Builder);
301 }
302
getTargetDefinesARMV9A(const LangOptions & Opts,MacroBuilder & Builder) const303 void AArch64TargetInfo::getTargetDefinesARMV9A(const LangOptions &Opts,
304 MacroBuilder &Builder) const {
305 // Armv9-A maps to Armv8.5-A
306 getTargetDefinesARMV85A(Opts, Builder);
307 }
308
getTargetDefinesARMV91A(const LangOptions & Opts,MacroBuilder & Builder) const309 void AArch64TargetInfo::getTargetDefinesARMV91A(const LangOptions &Opts,
310 MacroBuilder &Builder) const {
311 // Armv9.1-A maps to Armv8.6-A
312 getTargetDefinesARMV86A(Opts, Builder);
313 }
314
getTargetDefinesARMV92A(const LangOptions & Opts,MacroBuilder & Builder) const315 void AArch64TargetInfo::getTargetDefinesARMV92A(const LangOptions &Opts,
316 MacroBuilder &Builder) const {
317 // Armv9.2-A maps to Armv8.7-A
318 getTargetDefinesARMV87A(Opts, Builder);
319 }
320
getTargetDefinesARMV93A(const LangOptions & Opts,MacroBuilder & Builder) const321 void AArch64TargetInfo::getTargetDefinesARMV93A(const LangOptions &Opts,
322 MacroBuilder &Builder) const {
323 // Armv9.3-A maps to Armv8.8-A
324 getTargetDefinesARMV88A(Opts, Builder);
325 }
326
getTargetDefinesARMV94A(const LangOptions & Opts,MacroBuilder & Builder) const327 void AArch64TargetInfo::getTargetDefinesARMV94A(const LangOptions &Opts,
328 MacroBuilder &Builder) const {
329 // Armv9.4-A maps to Armv8.9-A
330 getTargetDefinesARMV89A(Opts, Builder);
331 }
332
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder) const333 void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts,
334 MacroBuilder &Builder) const {
335 // Target identification.
336 Builder.defineMacro("__aarch64__");
337 // For bare-metal.
338 if (getTriple().getOS() == llvm::Triple::UnknownOS &&
339 getTriple().isOSBinFormatELF())
340 Builder.defineMacro("__ELF__");
341
342 // Target properties.
343 if (!getTriple().isOSWindows() && getTriple().isArch64Bit()) {
344 Builder.defineMacro("_LP64");
345 Builder.defineMacro("__LP64__");
346 }
347
348 std::string CodeModel = getTargetOpts().CodeModel;
349 if (CodeModel == "default")
350 CodeModel = "small";
351 for (char &c : CodeModel)
352 c = toupper(c);
353 Builder.defineMacro("__AARCH64_CMODEL_" + CodeModel + "__");
354
355 // ACLE predefines. Many can only have one possible value on v8 AArch64.
356 Builder.defineMacro("__ARM_ACLE", "200");
357 Builder.defineMacro("__ARM_ARCH",
358 std::to_string(ArchInfo->Version.getMajor()));
359 Builder.defineMacro("__ARM_ARCH_PROFILE",
360 std::string("'") + (char)ArchInfo->Profile + "'");
361
362 Builder.defineMacro("__ARM_64BIT_STATE", "1");
363 Builder.defineMacro("__ARM_PCS_AAPCS64", "1");
364 Builder.defineMacro("__ARM_ARCH_ISA_A64", "1");
365
366 Builder.defineMacro("__ARM_FEATURE_CLZ", "1");
367 Builder.defineMacro("__ARM_FEATURE_FMA", "1");
368 Builder.defineMacro("__ARM_FEATURE_LDREX", "0xF");
369 Builder.defineMacro("__ARM_FEATURE_IDIV", "1"); // As specified in ACLE
370 Builder.defineMacro("__ARM_FEATURE_DIV"); // For backwards compatibility
371 Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN", "1");
372 Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING", "1");
373
374 Builder.defineMacro("__ARM_ALIGN_MAX_STACK_PWR", "4");
375
376 // 0xe implies support for half, single and double precision operations.
377 Builder.defineMacro("__ARM_FP", "0xE");
378
379 // PCS specifies this for SysV variants, which is all we support. Other ABIs
380 // may choose __ARM_FP16_FORMAT_ALTERNATIVE.
381 Builder.defineMacro("__ARM_FP16_FORMAT_IEEE", "1");
382 Builder.defineMacro("__ARM_FP16_ARGS", "1");
383
384 if (Opts.UnsafeFPMath)
385 Builder.defineMacro("__ARM_FP_FAST", "1");
386
387 Builder.defineMacro("__ARM_SIZEOF_WCHAR_T",
388 Twine(Opts.WCharSize ? Opts.WCharSize : 4));
389
390 Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM", Opts.ShortEnums ? "1" : "4");
391
392 if (FPU & NeonMode) {
393 Builder.defineMacro("__ARM_NEON", "1");
394 // 64-bit NEON supports half, single and double precision operations.
395 Builder.defineMacro("__ARM_NEON_FP", "0xE");
396 }
397
398 if (FPU & SveMode)
399 Builder.defineMacro("__ARM_FEATURE_SVE", "1");
400
401 if ((FPU & NeonMode) && (FPU & SveMode))
402 Builder.defineMacro("__ARM_NEON_SVE_BRIDGE", "1");
403
404 if (HasSVE2)
405 Builder.defineMacro("__ARM_FEATURE_SVE2", "1");
406
407 if (HasSVE2 && HasSVE2AES)
408 Builder.defineMacro("__ARM_FEATURE_SVE2_AES", "1");
409
410 if (HasSVE2 && HasSVE2BitPerm)
411 Builder.defineMacro("__ARM_FEATURE_SVE2_BITPERM", "1");
412
413 if (HasSVE2 && HasSVE2SHA3)
414 Builder.defineMacro("__ARM_FEATURE_SVE2_SHA3", "1");
415
416 if (HasSVE2 && HasSVE2SM4)
417 Builder.defineMacro("__ARM_FEATURE_SVE2_SM4", "1");
418
419 if (HasCRC)
420 Builder.defineMacro("__ARM_FEATURE_CRC32", "1");
421
422 if (HasRCPC)
423 Builder.defineMacro("__ARM_FEATURE_RCPC", "1");
424
425 if (HasFMV)
426 Builder.defineMacro("__HAVE_FUNCTION_MULTI_VERSIONING", "1");
427
428 // The __ARM_FEATURE_CRYPTO is deprecated in favor of finer grained feature
429 // macros for AES, SHA2, SHA3 and SM4
430 if (HasAES && HasSHA2)
431 Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1");
432
433 if (HasAES)
434 Builder.defineMacro("__ARM_FEATURE_AES", "1");
435
436 if (HasSHA2)
437 Builder.defineMacro("__ARM_FEATURE_SHA2", "1");
438
439 if (HasSHA3) {
440 Builder.defineMacro("__ARM_FEATURE_SHA3", "1");
441 Builder.defineMacro("__ARM_FEATURE_SHA512", "1");
442 }
443
444 if (HasSM4) {
445 Builder.defineMacro("__ARM_FEATURE_SM3", "1");
446 Builder.defineMacro("__ARM_FEATURE_SM4", "1");
447 }
448
449 if (HasPAuth)
450 Builder.defineMacro("__ARM_FEATURE_PAUTH", "1");
451
452 if (HasUnaligned)
453 Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1");
454
455 if ((FPU & NeonMode) && HasFullFP16)
456 Builder.defineMacro("__ARM_FEATURE_FP16_VECTOR_ARITHMETIC", "1");
457 if (HasFullFP16)
458 Builder.defineMacro("__ARM_FEATURE_FP16_SCALAR_ARITHMETIC", "1");
459
460 if (HasDotProd)
461 Builder.defineMacro("__ARM_FEATURE_DOTPROD", "1");
462
463 if (HasMTE)
464 Builder.defineMacro("__ARM_FEATURE_MEMORY_TAGGING", "1");
465
466 if (HasTME)
467 Builder.defineMacro("__ARM_FEATURE_TME", "1");
468
469 if (HasMatMul)
470 Builder.defineMacro("__ARM_FEATURE_MATMUL_INT8", "1");
471
472 if (HasLSE)
473 Builder.defineMacro("__ARM_FEATURE_ATOMICS", "1");
474
475 if (HasBFloat16) {
476 Builder.defineMacro("__ARM_FEATURE_BF16", "1");
477 Builder.defineMacro("__ARM_FEATURE_BF16_VECTOR_ARITHMETIC", "1");
478 Builder.defineMacro("__ARM_BF16_FORMAT_ALTERNATIVE", "1");
479 Builder.defineMacro("__ARM_FEATURE_BF16_SCALAR_ARITHMETIC", "1");
480 }
481
482 if ((FPU & SveMode) && HasBFloat16) {
483 Builder.defineMacro("__ARM_FEATURE_SVE_BF16", "1");
484 }
485
486 if ((FPU & SveMode) && HasMatmulFP64)
487 Builder.defineMacro("__ARM_FEATURE_SVE_MATMUL_FP64", "1");
488
489 if ((FPU & SveMode) && HasMatmulFP32)
490 Builder.defineMacro("__ARM_FEATURE_SVE_MATMUL_FP32", "1");
491
492 if ((FPU & SveMode) && HasMatMul)
493 Builder.defineMacro("__ARM_FEATURE_SVE_MATMUL_INT8", "1");
494
495 if ((FPU & NeonMode) && HasFP16FML)
496 Builder.defineMacro("__ARM_FEATURE_FP16_FML", "1");
497
498 if (Opts.hasSignReturnAddress()) {
499 // Bitmask:
500 // 0: Protection using the A key
501 // 1: Protection using the B key
502 // 2: Protection including leaf functions
503 unsigned Value = 0;
504
505 if (Opts.isSignReturnAddressWithAKey())
506 Value |= (1 << 0);
507 else
508 Value |= (1 << 1);
509
510 if (Opts.isSignReturnAddressScopeAll())
511 Value |= (1 << 2);
512
513 Builder.defineMacro("__ARM_FEATURE_PAC_DEFAULT", std::to_string(Value));
514 }
515
516 if (Opts.BranchTargetEnforcement)
517 Builder.defineMacro("__ARM_FEATURE_BTI_DEFAULT", "1");
518
519 if (HasLS64)
520 Builder.defineMacro("__ARM_FEATURE_LS64", "1");
521
522 if (HasRandGen)
523 Builder.defineMacro("__ARM_FEATURE_RNG", "1");
524
525 if (HasMOPS)
526 Builder.defineMacro("__ARM_FEATURE_MOPS", "1");
527
528 if (HasD128)
529 Builder.defineMacro("__ARM_FEATURE_SYSREG128", "1");
530
531 if (*ArchInfo == llvm::AArch64::ARMV8_1A)
532 getTargetDefinesARMV81A(Opts, Builder);
533 else if (*ArchInfo == llvm::AArch64::ARMV8_2A)
534 getTargetDefinesARMV82A(Opts, Builder);
535 else if (*ArchInfo == llvm::AArch64::ARMV8_3A)
536 getTargetDefinesARMV83A(Opts, Builder);
537 else if (*ArchInfo == llvm::AArch64::ARMV8_4A)
538 getTargetDefinesARMV84A(Opts, Builder);
539 else if (*ArchInfo == llvm::AArch64::ARMV8_5A)
540 getTargetDefinesARMV85A(Opts, Builder);
541 else if (*ArchInfo == llvm::AArch64::ARMV8_6A)
542 getTargetDefinesARMV86A(Opts, Builder);
543 else if (*ArchInfo == llvm::AArch64::ARMV8_7A)
544 getTargetDefinesARMV87A(Opts, Builder);
545 else if (*ArchInfo == llvm::AArch64::ARMV8_8A)
546 getTargetDefinesARMV88A(Opts, Builder);
547 else if (*ArchInfo == llvm::AArch64::ARMV8_9A)
548 getTargetDefinesARMV89A(Opts, Builder);
549 else if (*ArchInfo == llvm::AArch64::ARMV9A)
550 getTargetDefinesARMV9A(Opts, Builder);
551 else if (*ArchInfo == llvm::AArch64::ARMV9_1A)
552 getTargetDefinesARMV91A(Opts, Builder);
553 else if (*ArchInfo == llvm::AArch64::ARMV9_2A)
554 getTargetDefinesARMV92A(Opts, Builder);
555 else if (*ArchInfo == llvm::AArch64::ARMV9_3A)
556 getTargetDefinesARMV93A(Opts, Builder);
557 else if (*ArchInfo == llvm::AArch64::ARMV9_4A)
558 getTargetDefinesARMV94A(Opts, Builder);
559
560 // All of the __sync_(bool|val)_compare_and_swap_(1|2|4|8) builtins work.
561 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
562 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
563 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
564 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
565
566 // Allow detection of fast FMA support.
567 Builder.defineMacro("__FP_FAST_FMA", "1");
568 Builder.defineMacro("__FP_FAST_FMAF", "1");
569
570 // C/C++ operators work on both VLS and VLA SVE types
571 if (FPU & SveMode)
572 Builder.defineMacro("__ARM_FEATURE_SVE_VECTOR_OPERATORS", "2");
573
574 if (Opts.VScaleMin && Opts.VScaleMin == Opts.VScaleMax) {
575 Builder.defineMacro("__ARM_FEATURE_SVE_BITS", Twine(Opts.VScaleMin * 128));
576 }
577 }
578
getTargetBuiltins() const579 ArrayRef<Builtin::Info> AArch64TargetInfo::getTargetBuiltins() const {
580 return llvm::ArrayRef(BuiltinInfo, clang::AArch64::LastTSBuiltin -
581 Builtin::FirstTSBuiltin);
582 }
583
584 std::optional<std::pair<unsigned, unsigned>>
getVScaleRange(const LangOptions & LangOpts) const585 AArch64TargetInfo::getVScaleRange(const LangOptions &LangOpts) const {
586 if (LangOpts.VScaleMin || LangOpts.VScaleMax)
587 return std::pair<unsigned, unsigned>(
588 LangOpts.VScaleMin ? LangOpts.VScaleMin : 1, LangOpts.VScaleMax);
589
590 if (hasFeature("sve"))
591 return std::pair<unsigned, unsigned>(1, 16);
592
593 return std::nullopt;
594 }
595
multiVersionSortPriority(StringRef Name) const596 unsigned AArch64TargetInfo::multiVersionSortPriority(StringRef Name) const {
597 if (Name == "default")
598 return 0;
599 for (const auto &E : llvm::AArch64::Extensions)
600 if (Name == E.Name)
601 return E.FmvPriority;
602 return 0;
603 }
604
multiVersionFeatureCost() const605 unsigned AArch64TargetInfo::multiVersionFeatureCost() const {
606 // Take the maximum priority as per feature cost, so more features win.
607 return llvm::AArch64::ExtensionInfo::MaxFMVPriority;
608 }
609
getFeatureDepOptions(StringRef Name,std::string & FeatureVec) const610 bool AArch64TargetInfo::getFeatureDepOptions(StringRef Name,
611 std::string &FeatureVec) const {
612 FeatureVec = "";
613 for (const auto &E : llvm::AArch64::Extensions) {
614 if (Name == E.Name) {
615 FeatureVec = E.DependentFeatures;
616 break;
617 }
618 }
619 return FeatureVec != "";
620 }
621
validateCpuSupports(StringRef FeatureStr) const622 bool AArch64TargetInfo::validateCpuSupports(StringRef FeatureStr) const {
623 for (const auto &E : llvm::AArch64::Extensions)
624 if (FeatureStr == E.Name)
625 return true;
626 return false;
627 }
628
hasFeature(StringRef Feature) const629 bool AArch64TargetInfo::hasFeature(StringRef Feature) const {
630 return llvm::StringSwitch<bool>(Feature)
631 .Cases("aarch64", "arm64", "arm", true)
632 .Case("fmv", HasFMV)
633 .Cases("neon", "fp", "simd", FPU & NeonMode)
634 .Case("jscvt", HasJSCVT)
635 .Case("fcma", HasFCMA)
636 .Case("rng", HasRandGen)
637 .Case("flagm", HasFlagM)
638 .Case("flagm2", HasAlternativeNZCV)
639 .Case("fp16fml", HasFP16FML)
640 .Case("dotprod", HasDotProd)
641 .Case("sm4", HasSM4)
642 .Case("rdm", HasRDM)
643 .Case("lse", HasLSE)
644 .Case("crc", HasCRC)
645 .Case("sha2", HasSHA2)
646 .Case("sha3", HasSHA3)
647 .Cases("aes", "pmull", HasAES)
648 .Cases("fp16", "fullfp16", HasFullFP16)
649 .Case("dit", HasDIT)
650 .Case("dpb", HasCCPP)
651 .Case("dpb2", HasCCDP)
652 .Case("rcpc", HasRCPC)
653 .Case("frintts", HasFRInt3264)
654 .Case("i8mm", HasMatMul)
655 .Case("bf16", HasBFloat16)
656 .Case("sve", FPU & SveMode)
657 .Case("sve-bf16", FPU & SveMode && HasBFloat16)
658 .Case("sve-i8mm", FPU & SveMode && HasMatMul)
659 .Case("f32mm", FPU & SveMode && HasMatmulFP32)
660 .Case("f64mm", FPU & SveMode && HasMatmulFP64)
661 .Case("sve2", FPU & SveMode && HasSVE2)
662 .Case("sve2-pmull128", FPU & SveMode && HasSVE2AES)
663 .Case("sve2-bitperm", FPU & SveMode && HasSVE2BitPerm)
664 .Case("sve2-sha3", FPU & SveMode && HasSVE2SHA3)
665 .Case("sve2-sm4", FPU & SveMode && HasSVE2SM4)
666 .Case("sme", HasSME)
667 .Case("sme-f64f64", HasSMEF64)
668 .Case("sme-i16i64", HasSMEI64)
669 .Cases("memtag", "memtag2", HasMTE)
670 .Case("sb", HasSB)
671 .Case("predres", HasPredRes)
672 .Cases("ssbs", "ssbs2", HasSSBS)
673 .Case("bti", HasBTI)
674 .Cases("ls64", "ls64_v", "ls64_accdata", HasLS64)
675 .Case("wfxt", HasWFxT)
676 .Default(false);
677 }
678
setFeatureEnabled(llvm::StringMap<bool> & Features,StringRef Name,bool Enabled) const679 void AArch64TargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features,
680 StringRef Name, bool Enabled) const {
681 Features[Name] = Enabled;
682 // If the feature is an architecture feature (like v8.2a), add all previous
683 // architecture versions and any dependant target features.
684 const llvm::AArch64::ArchInfo &ArchInfo =
685 llvm::AArch64::ArchInfo::findBySubArch(Name);
686
687 if (ArchInfo == llvm::AArch64::INVALID)
688 return; // Not an architecure, nothing more to do.
689
690 // Disabling an architecture feature does not affect dependent features
691 if (!Enabled)
692 return;
693
694 for (const auto *OtherArch : llvm::AArch64::ArchInfos)
695 if (ArchInfo.implies(*OtherArch))
696 Features[OtherArch->getSubArch()] = true;
697
698 // Set any features implied by the architecture
699 uint64_t Extensions =
700 llvm::AArch64::getDefaultExtensions("generic", ArchInfo);
701 std::vector<StringRef> CPUFeats;
702 if (llvm::AArch64::getExtensionFeatures(Extensions, CPUFeats)) {
703 for (auto F : CPUFeats) {
704 assert(F[0] == '+' && "Expected + in target feature!");
705 Features[F.drop_front(1)] = true;
706 }
707 }
708 }
709
handleTargetFeatures(std::vector<std::string> & Features,DiagnosticsEngine & Diags)710 bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
711 DiagnosticsEngine &Diags) {
712 for (const auto &Feature : Features) {
713 if (Feature == "-neon")
714 HasNoNeon = true;
715 if (Feature == "-sve")
716 HasNoSVE = true;
717
718 if (Feature == "+neon" || Feature == "+fp-armv8")
719 FPU |= NeonMode;
720 if (Feature == "+jscvt") {
721 HasJSCVT = true;
722 FPU |= NeonMode;
723 }
724 if (Feature == "+fcma") {
725 HasFCMA = true;
726 FPU |= NeonMode;
727 }
728
729 if (Feature == "+sve") {
730 FPU |= NeonMode;
731 FPU |= SveMode;
732 HasFullFP16 = true;
733 }
734 if (Feature == "+sve2") {
735 FPU |= NeonMode;
736 FPU |= SveMode;
737 HasFullFP16 = true;
738 HasSVE2 = true;
739 }
740 if (Feature == "+sve2-aes") {
741 FPU |= NeonMode;
742 FPU |= SveMode;
743 HasFullFP16 = true;
744 HasSVE2 = true;
745 HasSVE2AES = true;
746 }
747 if (Feature == "+sve2-sha3") {
748 FPU |= NeonMode;
749 FPU |= SveMode;
750 HasFullFP16 = true;
751 HasSVE2 = true;
752 HasSVE2SHA3 = true;
753 }
754 if (Feature == "+sve2-sm4") {
755 FPU |= NeonMode;
756 FPU |= SveMode;
757 HasFullFP16 = true;
758 HasSVE2 = true;
759 HasSVE2SM4 = true;
760 }
761 if (Feature == "+sve2-bitperm") {
762 FPU |= NeonMode;
763 FPU |= SveMode;
764 HasFullFP16 = true;
765 HasSVE2 = true;
766 HasSVE2BitPerm = true;
767 }
768 if (Feature == "+f32mm") {
769 FPU |= NeonMode;
770 FPU |= SveMode;
771 HasFullFP16 = true;
772 HasMatmulFP32 = true;
773 }
774 if (Feature == "+f64mm") {
775 FPU |= NeonMode;
776 FPU |= SveMode;
777 HasFullFP16 = true;
778 HasMatmulFP64 = true;
779 }
780 if (Feature == "+sme") {
781 HasSME = true;
782 HasBFloat16 = true;
783 }
784 if (Feature == "+sme-f64f64") {
785 HasSME = true;
786 HasSMEF64 = true;
787 HasBFloat16 = true;
788 }
789 if (Feature == "+sme-i16i64") {
790 HasSME = true;
791 HasSMEI64 = true;
792 HasBFloat16 = true;
793 }
794 if (Feature == "+sb")
795 HasSB = true;
796 if (Feature == "+predres")
797 HasPredRes = true;
798 if (Feature == "+ssbs")
799 HasSSBS = true;
800 if (Feature == "+bti")
801 HasBTI = true;
802 if (Feature == "+wfxt")
803 HasWFxT = true;
804 if (Feature == "-fmv")
805 HasFMV = false;
806 if (Feature == "+crc")
807 HasCRC = true;
808 if (Feature == "+rcpc")
809 HasRCPC = true;
810 if (Feature == "+aes") {
811 FPU |= NeonMode;
812 HasAES = true;
813 }
814 if (Feature == "+sha2") {
815 FPU |= NeonMode;
816 HasSHA2 = true;
817 }
818 if (Feature == "+sha3") {
819 FPU |= NeonMode;
820 HasSHA2 = true;
821 HasSHA3 = true;
822 }
823 if (Feature == "+rdm") {
824 FPU |= NeonMode;
825 HasRDM = true;
826 }
827 if (Feature == "+dit")
828 HasDIT = true;
829 if (Feature == "+cccp")
830 HasCCPP = true;
831 if (Feature == "+ccdp") {
832 HasCCPP = true;
833 HasCCDP = true;
834 }
835 if (Feature == "+fptoint")
836 HasFRInt3264 = true;
837 if (Feature == "+sm4") {
838 FPU |= NeonMode;
839 HasSM4 = true;
840 }
841 if (Feature == "+strict-align")
842 HasUnaligned = false;
843 // All predecessor archs are added but select the latest one for ArchKind.
844 if (Feature == "+v8a" && ArchInfo->Version < llvm::AArch64::ARMV8A.Version)
845 ArchInfo = &llvm::AArch64::ARMV8A;
846 if (Feature == "+v8.1a" &&
847 ArchInfo->Version < llvm::AArch64::ARMV8_1A.Version)
848 ArchInfo = &llvm::AArch64::ARMV8_1A;
849 if (Feature == "+v8.2a" &&
850 ArchInfo->Version < llvm::AArch64::ARMV8_2A.Version)
851 ArchInfo = &llvm::AArch64::ARMV8_2A;
852 if (Feature == "+v8.3a" &&
853 ArchInfo->Version < llvm::AArch64::ARMV8_3A.Version)
854 ArchInfo = &llvm::AArch64::ARMV8_3A;
855 if (Feature == "+v8.4a" &&
856 ArchInfo->Version < llvm::AArch64::ARMV8_4A.Version)
857 ArchInfo = &llvm::AArch64::ARMV8_4A;
858 if (Feature == "+v8.5a" &&
859 ArchInfo->Version < llvm::AArch64::ARMV8_5A.Version)
860 ArchInfo = &llvm::AArch64::ARMV8_5A;
861 if (Feature == "+v8.6a" &&
862 ArchInfo->Version < llvm::AArch64::ARMV8_6A.Version)
863 ArchInfo = &llvm::AArch64::ARMV8_6A;
864 if (Feature == "+v8.7a" &&
865 ArchInfo->Version < llvm::AArch64::ARMV8_7A.Version)
866 ArchInfo = &llvm::AArch64::ARMV8_7A;
867 if (Feature == "+v8.8a" &&
868 ArchInfo->Version < llvm::AArch64::ARMV8_8A.Version)
869 ArchInfo = &llvm::AArch64::ARMV8_8A;
870 if (Feature == "+v8.9a" &&
871 ArchInfo->Version < llvm::AArch64::ARMV8_9A.Version)
872 ArchInfo = &llvm::AArch64::ARMV8_9A;
873 if (Feature == "+v9a" && ArchInfo->Version < llvm::AArch64::ARMV9A.Version)
874 ArchInfo = &llvm::AArch64::ARMV9A;
875 if (Feature == "+v9.1a" &&
876 ArchInfo->Version < llvm::AArch64::ARMV9_1A.Version)
877 ArchInfo = &llvm::AArch64::ARMV9_1A;
878 if (Feature == "+v9.2a" &&
879 ArchInfo->Version < llvm::AArch64::ARMV9_2A.Version)
880 ArchInfo = &llvm::AArch64::ARMV9_2A;
881 if (Feature == "+v9.3a" &&
882 ArchInfo->Version < llvm::AArch64::ARMV9_3A.Version)
883 ArchInfo = &llvm::AArch64::ARMV9_3A;
884 if (Feature == "+v9.4a" &&
885 ArchInfo->Version < llvm::AArch64::ARMV9_4A.Version)
886 ArchInfo = &llvm::AArch64::ARMV9_4A;
887 if (Feature == "+v8r")
888 ArchInfo = &llvm::AArch64::ARMV8R;
889 if (Feature == "+fullfp16") {
890 FPU |= NeonMode;
891 HasFullFP16 = true;
892 }
893 if (Feature == "+dotprod") {
894 FPU |= NeonMode;
895 HasDotProd = true;
896 }
897 if (Feature == "+fp16fml") {
898 FPU |= NeonMode;
899 HasFullFP16 = true;
900 HasFP16FML = true;
901 }
902 if (Feature == "+mte")
903 HasMTE = true;
904 if (Feature == "+tme")
905 HasTME = true;
906 if (Feature == "+pauth")
907 HasPAuth = true;
908 if (Feature == "+i8mm")
909 HasMatMul = true;
910 if (Feature == "+bf16")
911 HasBFloat16 = true;
912 if (Feature == "+lse")
913 HasLSE = true;
914 if (Feature == "+ls64")
915 HasLS64 = true;
916 if (Feature == "+rand")
917 HasRandGen = true;
918 if (Feature == "+flagm")
919 HasFlagM = true;
920 if (Feature == "+altnzcv") {
921 HasFlagM = true;
922 HasAlternativeNZCV = true;
923 }
924 if (Feature == "+mops")
925 HasMOPS = true;
926 if (Feature == "+d128")
927 HasD128 = true;
928 }
929
930 // Check features that are manually disabled by command line options.
931 // This needs to be checked after architecture-related features are handled,
932 // making sure they are properly disabled when required.
933 for (const auto &Feature : Features) {
934 if (Feature == "-d128")
935 HasD128 = false;
936 }
937
938 setDataLayout();
939 setArchFeatures();
940
941 if (HasNoNeon) {
942 FPU &= ~NeonMode;
943 FPU &= ~SveMode;
944 }
945 if (HasNoSVE)
946 FPU &= ~SveMode;
947
948 return true;
949 }
950
initFeatureMap(llvm::StringMap<bool> & Features,DiagnosticsEngine & Diags,StringRef CPU,const std::vector<std::string> & FeaturesVec) const951 bool AArch64TargetInfo::initFeatureMap(
952 llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
953 const std::vector<std::string> &FeaturesVec) const {
954 std::vector<std::string> UpdatedFeaturesVec;
955 // Parse the CPU and add any implied features.
956 const llvm::AArch64::ArchInfo &Arch = llvm::AArch64::parseCpu(CPU).Arch;
957 if (Arch != llvm::AArch64::INVALID) {
958 uint64_t Exts = llvm::AArch64::getDefaultExtensions(CPU, Arch);
959 std::vector<StringRef> CPUFeats;
960 llvm::AArch64::getExtensionFeatures(Exts, CPUFeats);
961 for (auto F : CPUFeats) {
962 assert((F[0] == '+' || F[0] == '-') && "Expected +/- in target feature!");
963 UpdatedFeaturesVec.push_back(F.str());
964 }
965 }
966
967 // Process target and dependent features. This is done in two loops collecting
968 // them into UpdatedFeaturesVec: first to add dependent '+'features,
969 // second to add target '+/-'features that can later disable some of
970 // features added on the first loop.
971 for (const auto &Feature : FeaturesVec)
972 if ((Feature[0] == '?' || Feature[0] == '+')) {
973 std::string Options;
974 if (AArch64TargetInfo::getFeatureDepOptions(Feature.substr(1), Options)) {
975 SmallVector<StringRef, 1> AttrFeatures;
976 StringRef(Options).split(AttrFeatures, ",");
977 for (auto F : AttrFeatures)
978 UpdatedFeaturesVec.push_back(F.str());
979 }
980 }
981 for (const auto &Feature : FeaturesVec)
982 if (Feature[0] == '+') {
983 std::string F;
984 llvm::AArch64::getFeatureOption(Feature, F);
985 UpdatedFeaturesVec.push_back(F);
986 } else if (Feature[0] != '?')
987 UpdatedFeaturesVec.push_back(Feature);
988
989 return TargetInfo::initFeatureMap(Features, Diags, CPU, UpdatedFeaturesVec);
990 }
991
992 // Parse AArch64 Target attributes, which are a comma separated list of:
993 // "arch=<arch>" - parsed to features as per -march=..
994 // "cpu=<cpu>" - parsed to features as per -mcpu=.., with CPU set to <cpu>
995 // "tune=<cpu>" - TuneCPU set to <cpu>
996 // "feature", "no-feature" - Add (or remove) feature.
997 // "+feature", "+nofeature" - Add (or remove) feature.
parseTargetAttr(StringRef Features) const998 ParsedTargetAttr AArch64TargetInfo::parseTargetAttr(StringRef Features) const {
999 ParsedTargetAttr Ret;
1000 if (Features == "default")
1001 return Ret;
1002 SmallVector<StringRef, 1> AttrFeatures;
1003 Features.split(AttrFeatures, ",");
1004 bool FoundArch = false;
1005
1006 auto SplitAndAddFeatures = [](StringRef FeatString,
1007 std::vector<std::string> &Features) {
1008 SmallVector<StringRef, 8> SplitFeatures;
1009 FeatString.split(SplitFeatures, StringRef("+"), -1, false);
1010 for (StringRef Feature : SplitFeatures) {
1011 StringRef FeatureName = llvm::AArch64::getArchExtFeature(Feature);
1012 if (!FeatureName.empty())
1013 Features.push_back(FeatureName.str());
1014 else
1015 // Pushing the original feature string to give a sema error later on
1016 // when they get checked.
1017 if (Feature.startswith("no"))
1018 Features.push_back("-" + Feature.drop_front(2).str());
1019 else
1020 Features.push_back("+" + Feature.str());
1021 }
1022 };
1023
1024 for (auto &Feature : AttrFeatures) {
1025 Feature = Feature.trim();
1026 if (Feature.startswith("fpmath="))
1027 continue;
1028
1029 if (Feature.startswith("branch-protection=")) {
1030 Ret.BranchProtection = Feature.split('=').second.trim();
1031 continue;
1032 }
1033
1034 if (Feature.startswith("arch=")) {
1035 if (FoundArch)
1036 Ret.Duplicate = "arch=";
1037 FoundArch = true;
1038 std::pair<StringRef, StringRef> Split =
1039 Feature.split("=").second.trim().split("+");
1040 const llvm::AArch64::ArchInfo &AI = llvm::AArch64::parseArch(Split.first);
1041
1042 // Parse the architecture version, adding the required features to
1043 // Ret.Features.
1044 if (AI == llvm::AArch64::INVALID)
1045 continue;
1046 Ret.Features.push_back(AI.ArchFeature.str());
1047 // Add any extra features, after the +
1048 SplitAndAddFeatures(Split.second, Ret.Features);
1049 } else if (Feature.startswith("cpu=")) {
1050 if (!Ret.CPU.empty())
1051 Ret.Duplicate = "cpu=";
1052 else {
1053 // Split the cpu string into "cpu=", "cortex-a710" and any remaining
1054 // "+feat" features.
1055 std::pair<StringRef, StringRef> Split =
1056 Feature.split("=").second.trim().split("+");
1057 Ret.CPU = Split.first;
1058 SplitAndAddFeatures(Split.second, Ret.Features);
1059 }
1060 } else if (Feature.startswith("tune=")) {
1061 if (!Ret.Tune.empty())
1062 Ret.Duplicate = "tune=";
1063 else
1064 Ret.Tune = Feature.split("=").second.trim();
1065 } else if (Feature.startswith("+")) {
1066 SplitAndAddFeatures(Feature, Ret.Features);
1067 } else if (Feature.startswith("no-")) {
1068 StringRef FeatureName =
1069 llvm::AArch64::getArchExtFeature(Feature.split("-").second);
1070 if (!FeatureName.empty())
1071 Ret.Features.push_back("-" + FeatureName.drop_front(1).str());
1072 else
1073 Ret.Features.push_back("-" + Feature.split("-").second.str());
1074 } else {
1075 // Try parsing the string to the internal target feature name. If it is
1076 // invalid, add the original string (which could already be an internal
1077 // name). These should be checked later by isValidFeatureName.
1078 StringRef FeatureName = llvm::AArch64::getArchExtFeature(Feature);
1079 if (!FeatureName.empty())
1080 Ret.Features.push_back(FeatureName.str());
1081 else
1082 Ret.Features.push_back("+" + Feature.str());
1083 }
1084 }
1085 return Ret;
1086 }
1087
hasBFloat16Type() const1088 bool AArch64TargetInfo::hasBFloat16Type() const {
1089 return true;
1090 }
1091
1092 TargetInfo::CallingConvCheckResult
checkCallingConvention(CallingConv CC) const1093 AArch64TargetInfo::checkCallingConvention(CallingConv CC) const {
1094 switch (CC) {
1095 case CC_C:
1096 case CC_Swift:
1097 case CC_SwiftAsync:
1098 case CC_PreserveMost:
1099 case CC_PreserveAll:
1100 case CC_OpenCLKernel:
1101 case CC_AArch64VectorCall:
1102 case CC_AArch64SVEPCS:
1103 case CC_Win64:
1104 return CCCR_OK;
1105 default:
1106 return CCCR_Warning;
1107 }
1108 }
1109
isCLZForZeroUndef() const1110 bool AArch64TargetInfo::isCLZForZeroUndef() const { return false; }
1111
getBuiltinVaListKind() const1112 TargetInfo::BuiltinVaListKind AArch64TargetInfo::getBuiltinVaListKind() const {
1113 return TargetInfo::AArch64ABIBuiltinVaList;
1114 }
1115
1116 const char *const AArch64TargetInfo::GCCRegNames[] = {
1117 // 32-bit Integer registers
1118 "w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7", "w8", "w9", "w10", "w11",
1119 "w12", "w13", "w14", "w15", "w16", "w17", "w18", "w19", "w20", "w21", "w22",
1120 "w23", "w24", "w25", "w26", "w27", "w28", "w29", "w30", "wsp",
1121
1122 // 64-bit Integer registers
1123 "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11",
1124 "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22",
1125 "x23", "x24", "x25", "x26", "x27", "x28", "fp", "lr", "sp",
1126
1127 // 32-bit floating point regsisters
1128 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11",
1129 "s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22",
1130 "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
1131
1132 // 64-bit floating point regsisters
1133 "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11",
1134 "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19", "d20", "d21", "d22",
1135 "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",
1136
1137 // Neon vector registers
1138 "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11",
1139 "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", "v20", "v21", "v22",
1140 "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31",
1141
1142 // SVE vector registers
1143 "z0", "z1", "z2", "z3", "z4", "z5", "z6", "z7", "z8", "z9", "z10",
1144 "z11", "z12", "z13", "z14", "z15", "z16", "z17", "z18", "z19", "z20", "z21",
1145 "z22", "z23", "z24", "z25", "z26", "z27", "z28", "z29", "z30", "z31",
1146
1147 // SVE predicate registers
1148 "p0", "p1", "p2", "p3", "p4", "p5", "p6", "p7", "p8", "p9", "p10",
1149 "p11", "p12", "p13", "p14", "p15"
1150 };
1151
getGCCRegNames() const1152 ArrayRef<const char *> AArch64TargetInfo::getGCCRegNames() const {
1153 return llvm::ArrayRef(GCCRegNames);
1154 }
1155
1156 const TargetInfo::GCCRegAlias AArch64TargetInfo::GCCRegAliases[] = {
1157 {{"w31"}, "wsp"},
1158 {{"x31"}, "sp"},
1159 // GCC rN registers are aliases of xN registers.
1160 {{"r0"}, "x0"},
1161 {{"r1"}, "x1"},
1162 {{"r2"}, "x2"},
1163 {{"r3"}, "x3"},
1164 {{"r4"}, "x4"},
1165 {{"r5"}, "x5"},
1166 {{"r6"}, "x6"},
1167 {{"r7"}, "x7"},
1168 {{"r8"}, "x8"},
1169 {{"r9"}, "x9"},
1170 {{"r10"}, "x10"},
1171 {{"r11"}, "x11"},
1172 {{"r12"}, "x12"},
1173 {{"r13"}, "x13"},
1174 {{"r14"}, "x14"},
1175 {{"r15"}, "x15"},
1176 {{"r16"}, "x16"},
1177 {{"r17"}, "x17"},
1178 {{"r18"}, "x18"},
1179 {{"r19"}, "x19"},
1180 {{"r20"}, "x20"},
1181 {{"r21"}, "x21"},
1182 {{"r22"}, "x22"},
1183 {{"r23"}, "x23"},
1184 {{"r24"}, "x24"},
1185 {{"r25"}, "x25"},
1186 {{"r26"}, "x26"},
1187 {{"r27"}, "x27"},
1188 {{"r28"}, "x28"},
1189 {{"r29", "x29"}, "fp"},
1190 {{"r30", "x30"}, "lr"},
1191 // The S/D/Q and W/X registers overlap, but aren't really aliases; we
1192 // don't want to substitute one of these for a different-sized one.
1193 };
1194
getGCCRegAliases() const1195 ArrayRef<TargetInfo::GCCRegAlias> AArch64TargetInfo::getGCCRegAliases() const {
1196 return llvm::ArrayRef(GCCRegAliases);
1197 }
1198
validateAsmConstraint(const char * & Name,TargetInfo::ConstraintInfo & Info) const1199 bool AArch64TargetInfo::validateAsmConstraint(
1200 const char *&Name, TargetInfo::ConstraintInfo &Info) const {
1201 switch (*Name) {
1202 default:
1203 return false;
1204 case 'w': // Floating point and SIMD registers (V0-V31)
1205 Info.setAllowsRegister();
1206 return true;
1207 case 'I': // Constant that can be used with an ADD instruction
1208 case 'J': // Constant that can be used with a SUB instruction
1209 case 'K': // Constant that can be used with a 32-bit logical instruction
1210 case 'L': // Constant that can be used with a 64-bit logical instruction
1211 case 'M': // Constant that can be used as a 32-bit MOV immediate
1212 case 'N': // Constant that can be used as a 64-bit MOV immediate
1213 case 'Y': // Floating point constant zero
1214 case 'Z': // Integer constant zero
1215 return true;
1216 case 'Q': // A memory reference with base register and no offset
1217 Info.setAllowsMemory();
1218 return true;
1219 case 'S': // A symbolic address
1220 Info.setAllowsRegister();
1221 return true;
1222 case 'U':
1223 if (Name[1] == 'p' && (Name[2] == 'l' || Name[2] == 'a')) {
1224 // SVE predicate registers ("Upa"=P0-15, "Upl"=P0-P7)
1225 Info.setAllowsRegister();
1226 Name += 2;
1227 return true;
1228 }
1229 // Ump: A memory address suitable for ldp/stp in SI, DI, SF and DF modes.
1230 // Utf: A memory address suitable for ldp/stp in TF mode.
1231 // Usa: An absolute symbolic address.
1232 // Ush: The high part (bits 32:12) of a pc-relative symbolic address.
1233
1234 // Better to return an error saying that it's an unrecognised constraint
1235 // even if this is a valid constraint in gcc.
1236 return false;
1237 case 'z': // Zero register, wzr or xzr
1238 Info.setAllowsRegister();
1239 return true;
1240 case 'x': // Floating point and SIMD registers (V0-V15)
1241 Info.setAllowsRegister();
1242 return true;
1243 case 'y': // SVE registers (V0-V7)
1244 Info.setAllowsRegister();
1245 return true;
1246 }
1247 return false;
1248 }
1249
validateConstraintModifier(StringRef Constraint,char Modifier,unsigned Size,std::string & SuggestedModifier) const1250 bool AArch64TargetInfo::validateConstraintModifier(
1251 StringRef Constraint, char Modifier, unsigned Size,
1252 std::string &SuggestedModifier) const {
1253 // Strip off constraint modifiers.
1254 while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&')
1255 Constraint = Constraint.substr(1);
1256
1257 switch (Constraint[0]) {
1258 default:
1259 return true;
1260 case 'z':
1261 case 'r': {
1262 switch (Modifier) {
1263 case 'x':
1264 case 'w':
1265 // For now assume that the person knows what they're
1266 // doing with the modifier.
1267 return true;
1268 default:
1269 // By default an 'r' constraint will be in the 'x'
1270 // registers.
1271 if (Size == 64)
1272 return true;
1273
1274 if (Size == 512)
1275 return HasLS64;
1276
1277 SuggestedModifier = "w";
1278 return false;
1279 }
1280 }
1281 }
1282 }
1283
getClobbers() const1284 const char *AArch64TargetInfo::getClobbers() const { return ""; }
1285
getEHDataRegisterNumber(unsigned RegNo) const1286 int AArch64TargetInfo::getEHDataRegisterNumber(unsigned RegNo) const {
1287 if (RegNo == 0)
1288 return 0;
1289 if (RegNo == 1)
1290 return 1;
1291 return -1;
1292 }
1293
hasInt128Type() const1294 bool AArch64TargetInfo::hasInt128Type() const { return true; }
1295
AArch64leTargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)1296 AArch64leTargetInfo::AArch64leTargetInfo(const llvm::Triple &Triple,
1297 const TargetOptions &Opts)
1298 : AArch64TargetInfo(Triple, Opts) {}
1299
setDataLayout()1300 void AArch64leTargetInfo::setDataLayout() {
1301 if (getTriple().isOSBinFormatMachO()) {
1302 if(getTriple().isArch32Bit())
1303 resetDataLayout("e-m:o-p:32:32-i64:64-i128:128-n32:64-S128", "_");
1304 else
1305 resetDataLayout("e-m:o-i64:64-i128:128-n32:64-S128", "_");
1306 } else
1307 resetDataLayout("e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
1308 }
1309
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder) const1310 void AArch64leTargetInfo::getTargetDefines(const LangOptions &Opts,
1311 MacroBuilder &Builder) const {
1312 Builder.defineMacro("__AARCH64EL__");
1313 AArch64TargetInfo::getTargetDefines(Opts, Builder);
1314 }
1315
AArch64beTargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)1316 AArch64beTargetInfo::AArch64beTargetInfo(const llvm::Triple &Triple,
1317 const TargetOptions &Opts)
1318 : AArch64TargetInfo(Triple, Opts) {}
1319
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder) const1320 void AArch64beTargetInfo::getTargetDefines(const LangOptions &Opts,
1321 MacroBuilder &Builder) const {
1322 Builder.defineMacro("__AARCH64EB__");
1323 Builder.defineMacro("__AARCH_BIG_ENDIAN");
1324 Builder.defineMacro("__ARM_BIG_ENDIAN");
1325 AArch64TargetInfo::getTargetDefines(Opts, Builder);
1326 }
1327
setDataLayout()1328 void AArch64beTargetInfo::setDataLayout() {
1329 assert(!getTriple().isOSBinFormatMachO());
1330 resetDataLayout("E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
1331 }
1332
WindowsARM64TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)1333 WindowsARM64TargetInfo::WindowsARM64TargetInfo(const llvm::Triple &Triple,
1334 const TargetOptions &Opts)
1335 : WindowsTargetInfo<AArch64leTargetInfo>(Triple, Opts), Triple(Triple) {
1336
1337 // This is an LLP64 platform.
1338 // int:4, long:4, long long:8, long double:8.
1339 IntWidth = IntAlign = 32;
1340 LongWidth = LongAlign = 32;
1341 DoubleAlign = LongLongAlign = 64;
1342 LongDoubleWidth = LongDoubleAlign = 64;
1343 LongDoubleFormat = &llvm::APFloat::IEEEdouble();
1344 IntMaxType = SignedLongLong;
1345 Int64Type = SignedLongLong;
1346 SizeType = UnsignedLongLong;
1347 PtrDiffType = SignedLongLong;
1348 IntPtrType = SignedLongLong;
1349 }
1350
setDataLayout()1351 void WindowsARM64TargetInfo::setDataLayout() {
1352 resetDataLayout(Triple.isOSBinFormatMachO()
1353 ? "e-m:o-i64:64-i128:128-n32:64-S128"
1354 : "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128",
1355 Triple.isOSBinFormatMachO() ? "_" : "");
1356 }
1357
1358 TargetInfo::BuiltinVaListKind
getBuiltinVaListKind() const1359 WindowsARM64TargetInfo::getBuiltinVaListKind() const {
1360 return TargetInfo::CharPtrBuiltinVaList;
1361 }
1362
1363 TargetInfo::CallingConvCheckResult
checkCallingConvention(CallingConv CC) const1364 WindowsARM64TargetInfo::checkCallingConvention(CallingConv CC) const {
1365 switch (CC) {
1366 case CC_X86StdCall:
1367 case CC_X86ThisCall:
1368 case CC_X86FastCall:
1369 case CC_X86VectorCall:
1370 return CCCR_Ignore;
1371 case CC_C:
1372 case CC_OpenCLKernel:
1373 case CC_PreserveMost:
1374 case CC_PreserveAll:
1375 case CC_Swift:
1376 case CC_SwiftAsync:
1377 case CC_Win64:
1378 return CCCR_OK;
1379 default:
1380 return CCCR_Warning;
1381 }
1382 }
1383
MicrosoftARM64TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)1384 MicrosoftARM64TargetInfo::MicrosoftARM64TargetInfo(const llvm::Triple &Triple,
1385 const TargetOptions &Opts)
1386 : WindowsARM64TargetInfo(Triple, Opts) {
1387 TheCXXABI.set(TargetCXXABI::Microsoft);
1388 }
1389
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder) const1390 void MicrosoftARM64TargetInfo::getTargetDefines(const LangOptions &Opts,
1391 MacroBuilder &Builder) const {
1392 WindowsARM64TargetInfo::getTargetDefines(Opts, Builder);
1393 Builder.defineMacro("_M_ARM64", "1");
1394 }
1395
1396 TargetInfo::CallingConvKind
getCallingConvKind(bool ClangABICompat4) const1397 MicrosoftARM64TargetInfo::getCallingConvKind(bool ClangABICompat4) const {
1398 return CCK_MicrosoftWin64;
1399 }
1400
getMinGlobalAlign(uint64_t TypeSize) const1401 unsigned MicrosoftARM64TargetInfo::getMinGlobalAlign(uint64_t TypeSize) const {
1402 unsigned Align = WindowsARM64TargetInfo::getMinGlobalAlign(TypeSize);
1403
1404 // MSVC does size based alignment for arm64 based on alignment section in
1405 // below document, replicate that to keep alignment consistent with object
1406 // files compiled by MSVC.
1407 // https://docs.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions
1408 if (TypeSize >= 512) { // TypeSize >= 64 bytes
1409 Align = std::max(Align, 128u); // align type at least 16 bytes
1410 } else if (TypeSize >= 64) { // TypeSize >= 8 bytes
1411 Align = std::max(Align, 64u); // align type at least 8 butes
1412 } else if (TypeSize >= 16) { // TypeSize >= 2 bytes
1413 Align = std::max(Align, 32u); // align type at least 4 bytes
1414 }
1415 return Align;
1416 }
1417
MinGWARM64TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)1418 MinGWARM64TargetInfo::MinGWARM64TargetInfo(const llvm::Triple &Triple,
1419 const TargetOptions &Opts)
1420 : WindowsARM64TargetInfo(Triple, Opts) {
1421 TheCXXABI.set(TargetCXXABI::GenericAArch64);
1422 }
1423
DarwinAArch64TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)1424 DarwinAArch64TargetInfo::DarwinAArch64TargetInfo(const llvm::Triple &Triple,
1425 const TargetOptions &Opts)
1426 : DarwinTargetInfo<AArch64leTargetInfo>(Triple, Opts) {
1427 Int64Type = SignedLongLong;
1428 if (getTriple().isArch32Bit())
1429 IntMaxType = SignedLongLong;
1430
1431 WCharType = SignedInt;
1432 UseSignedCharForObjCBool = false;
1433
1434 LongDoubleWidth = LongDoubleAlign = SuitableAlign = 64;
1435 LongDoubleFormat = &llvm::APFloat::IEEEdouble();
1436
1437 UseZeroLengthBitfieldAlignment = false;
1438
1439 if (getTriple().isArch32Bit()) {
1440 UseBitFieldTypeAlignment = false;
1441 ZeroLengthBitfieldBoundary = 32;
1442 UseZeroLengthBitfieldAlignment = true;
1443 TheCXXABI.set(TargetCXXABI::WatchOS);
1444 } else
1445 TheCXXABI.set(TargetCXXABI::AppleARM64);
1446 }
1447
getOSDefines(const LangOptions & Opts,const llvm::Triple & Triple,MacroBuilder & Builder) const1448 void DarwinAArch64TargetInfo::getOSDefines(const LangOptions &Opts,
1449 const llvm::Triple &Triple,
1450 MacroBuilder &Builder) const {
1451 Builder.defineMacro("__AARCH64_SIMD__");
1452 if (Triple.isArch32Bit())
1453 Builder.defineMacro("__ARM64_ARCH_8_32__");
1454 else
1455 Builder.defineMacro("__ARM64_ARCH_8__");
1456 Builder.defineMacro("__ARM_NEON__");
1457 Builder.defineMacro("__LITTLE_ENDIAN__");
1458 Builder.defineMacro("__REGISTER_PREFIX__", "");
1459 Builder.defineMacro("__arm64", "1");
1460 Builder.defineMacro("__arm64__", "1");
1461
1462 if (Triple.isArm64e())
1463 Builder.defineMacro("__arm64e__", "1");
1464
1465 getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion);
1466 }
1467
1468 TargetInfo::BuiltinVaListKind
getBuiltinVaListKind() const1469 DarwinAArch64TargetInfo::getBuiltinVaListKind() const {
1470 return TargetInfo::CharPtrBuiltinVaList;
1471 }
1472
1473 // 64-bit RenderScript is aarch64
RenderScript64TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)1474 RenderScript64TargetInfo::RenderScript64TargetInfo(const llvm::Triple &Triple,
1475 const TargetOptions &Opts)
1476 : AArch64leTargetInfo(llvm::Triple("aarch64", Triple.getVendorName(),
1477 Triple.getOSName(),
1478 Triple.getEnvironmentName()),
1479 Opts) {
1480 IsRenderScriptTarget = true;
1481 }
1482
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder) const1483 void RenderScript64TargetInfo::getTargetDefines(const LangOptions &Opts,
1484 MacroBuilder &Builder) const {
1485 Builder.defineMacro("__RENDERSCRIPT__");
1486 AArch64leTargetInfo::getTargetDefines(Opts, Builder);
1487 }
1488