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
22 using namespace clang;
23 using namespace clang::targets;
24
25 const Builtin::Info AArch64TargetInfo::BuiltinInfo[] = {
26 #define BUILTIN(ID, TYPE, ATTRS) \
27 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
28 #include "clang/Basic/BuiltinsNEON.def"
29
30 #define BUILTIN(ID, TYPE, ATTRS) \
31 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
32 #include "clang/Basic/BuiltinsSVE.def"
33
34 #define BUILTIN(ID, TYPE, ATTRS) \
35 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
36 #define LANGBUILTIN(ID, TYPE, ATTRS, LANG) \
37 {#ID, TYPE, ATTRS, nullptr, LANG, nullptr},
38 #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
39 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE},
40 #define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \
41 {#ID, TYPE, ATTRS, HEADER, LANGS, FEATURE},
42 #include "clang/Basic/BuiltinsAArch64.def"
43 };
44
AArch64TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)45 AArch64TargetInfo::AArch64TargetInfo(const llvm::Triple &Triple,
46 const TargetOptions &Opts)
47 : TargetInfo(Triple), ABI("aapcs") {
48 if (getTriple().isOSOpenBSD()) {
49 Int64Type = SignedLongLong;
50 IntMaxType = SignedLongLong;
51 } else {
52 if (!getTriple().isOSDarwin() && !getTriple().isOSNetBSD())
53 WCharType = UnsignedInt;
54
55 Int64Type = SignedLong;
56 IntMaxType = SignedLong;
57 }
58
59 // All AArch64 implementations support ARMv8 FP, which makes half a legal type.
60 HasLegalHalfType = true;
61 HasFloat16 = true;
62
63 if (Triple.isArch64Bit())
64 LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
65 else
66 LongWidth = LongAlign = PointerWidth = PointerAlign = 32;
67
68 MaxVectorAlign = 128;
69 MaxAtomicInlineWidth = 128;
70 MaxAtomicPromoteWidth = 128;
71
72 LongDoubleWidth = LongDoubleAlign = SuitableAlign = 128;
73 LongDoubleFormat = &llvm::APFloat::IEEEquad();
74
75 BFloat16Width = BFloat16Align = 16;
76 BFloat16Format = &llvm::APFloat::BFloat();
77
78 // Make __builtin_ms_va_list available.
79 HasBuiltinMSVaList = true;
80
81 // Make the SVE types available. Note that this deliberately doesn't
82 // depend on SveMode, since in principle it should be possible to turn
83 // SVE on and off within a translation unit. It should also be possible
84 // to compile the global declaration:
85 //
86 // __SVInt8_t *ptr;
87 //
88 // even without SVE.
89 HasAArch64SVETypes = true;
90
91 // {} in inline assembly are neon specifiers, not assembly variant
92 // specifiers.
93 NoAsmVariants = true;
94
95 // AAPCS gives rules for bitfields. 7.1.7 says: "The container type
96 // contributes to the alignment of the containing aggregate in the same way
97 // a plain (non bit-field) member of that type would, without exception for
98 // zero-sized or anonymous bit-fields."
99 assert(UseBitFieldTypeAlignment && "bitfields affect type alignment");
100 UseZeroLengthBitfieldAlignment = true;
101
102 // AArch64 targets default to using the ARM C++ ABI.
103 TheCXXABI.set(TargetCXXABI::GenericAArch64);
104
105 if (Triple.getOS() == llvm::Triple::Linux)
106 this->MCountName = "\01_mcount";
107 else if (Triple.getOS() == llvm::Triple::UnknownOS)
108 this->MCountName =
109 Opts.EABIVersion == llvm::EABI::GNU ? "\01_mcount" : "mcount";
110 }
111
getABI() const112 StringRef AArch64TargetInfo::getABI() const { return ABI; }
113
setABI(const std::string & Name)114 bool AArch64TargetInfo::setABI(const std::string &Name) {
115 if (Name != "aapcs" && Name != "darwinpcs")
116 return false;
117
118 ABI = Name;
119 return true;
120 }
121
validateBranchProtection(StringRef Spec,BranchProtectionInfo & BPI,StringRef & Err) const122 bool AArch64TargetInfo::validateBranchProtection(StringRef Spec,
123 BranchProtectionInfo &BPI,
124 StringRef &Err) const {
125 llvm::AArch64::ParsedBranchProtection PBP;
126 if (!llvm::AArch64::parseBranchProtection(Spec, PBP, Err))
127 return false;
128
129 BPI.SignReturnAddr =
130 llvm::StringSwitch<LangOptions::SignReturnAddressScopeKind>(PBP.Scope)
131 .Case("non-leaf", LangOptions::SignReturnAddressScopeKind::NonLeaf)
132 .Case("all", LangOptions::SignReturnAddressScopeKind::All)
133 .Default(LangOptions::SignReturnAddressScopeKind::None);
134
135 if (PBP.Key == "a_key")
136 BPI.SignKey = LangOptions::SignReturnAddressKeyKind::AKey;
137 else
138 BPI.SignKey = LangOptions::SignReturnAddressKeyKind::BKey;
139
140 BPI.BranchTargetEnforcement = PBP.BranchTargetEnforcement;
141 return true;
142 }
143
isValidCPUName(StringRef Name) const144 bool AArch64TargetInfo::isValidCPUName(StringRef Name) const {
145 return Name == "generic" ||
146 llvm::AArch64::parseCPUArch(Name) != llvm::AArch64::ArchKind::INVALID;
147 }
148
setCPU(const std::string & Name)149 bool AArch64TargetInfo::setCPU(const std::string &Name) {
150 return isValidCPUName(Name);
151 }
152
fillValidCPUList(SmallVectorImpl<StringRef> & Values) const153 void AArch64TargetInfo::fillValidCPUList(
154 SmallVectorImpl<StringRef> &Values) const {
155 llvm::AArch64::fillValidCPUArchList(Values);
156 }
157
getTargetDefinesARMV81A(const LangOptions & Opts,MacroBuilder & Builder) const158 void AArch64TargetInfo::getTargetDefinesARMV81A(const LangOptions &Opts,
159 MacroBuilder &Builder) const {
160 Builder.defineMacro("__ARM_FEATURE_QRDMX", "1");
161 Builder.defineMacro("__ARM_FEATURE_ATOMICS", "1");
162 Builder.defineMacro("__ARM_FEATURE_CRC32", "1");
163 }
164
getTargetDefinesARMV82A(const LangOptions & Opts,MacroBuilder & Builder) const165 void AArch64TargetInfo::getTargetDefinesARMV82A(const LangOptions &Opts,
166 MacroBuilder &Builder) const {
167 // Also include the ARMv8.1 defines
168 getTargetDefinesARMV81A(Opts, Builder);
169 }
170
getTargetDefinesARMV83A(const LangOptions & Opts,MacroBuilder & Builder) const171 void AArch64TargetInfo::getTargetDefinesARMV83A(const LangOptions &Opts,
172 MacroBuilder &Builder) const {
173 Builder.defineMacro("__ARM_FEATURE_COMPLEX", "1");
174 Builder.defineMacro("__ARM_FEATURE_JCVT", "1");
175 // Also include the Armv8.2 defines
176 getTargetDefinesARMV82A(Opts, Builder);
177 }
178
getTargetDefinesARMV84A(const LangOptions & Opts,MacroBuilder & Builder) const179 void AArch64TargetInfo::getTargetDefinesARMV84A(const LangOptions &Opts,
180 MacroBuilder &Builder) const {
181 // Also include the Armv8.3 defines
182 getTargetDefinesARMV83A(Opts, Builder);
183 }
184
getTargetDefinesARMV85A(const LangOptions & Opts,MacroBuilder & Builder) const185 void AArch64TargetInfo::getTargetDefinesARMV85A(const LangOptions &Opts,
186 MacroBuilder &Builder) const {
187 Builder.defineMacro("__ARM_FEATURE_FRINT", "1");
188 // Also include the Armv8.4 defines
189 getTargetDefinesARMV84A(Opts, Builder);
190 }
191
getTargetDefinesARMV86A(const LangOptions & Opts,MacroBuilder & Builder) const192 void AArch64TargetInfo::getTargetDefinesARMV86A(const LangOptions &Opts,
193 MacroBuilder &Builder) const {
194 // Also include the Armv8.5 defines
195 // FIXME: Armv8.6 makes the following extensions mandatory:
196 // - __ARM_FEATURE_BF16
197 // - __ARM_FEATURE_MATMUL_INT8
198 // Handle them here.
199 getTargetDefinesARMV85A(Opts, Builder);
200 }
201
getTargetDefinesARMV87A(const LangOptions & Opts,MacroBuilder & Builder) const202 void AArch64TargetInfo::getTargetDefinesARMV87A(const LangOptions &Opts,
203 MacroBuilder &Builder) const {
204 // Also include the Armv8.6 defines
205 getTargetDefinesARMV86A(Opts, Builder);
206 }
207
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder) const208 void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts,
209 MacroBuilder &Builder) const {
210 // Target identification.
211 Builder.defineMacro("__aarch64__");
212 // For bare-metal.
213 if (getTriple().getOS() == llvm::Triple::UnknownOS &&
214 getTriple().isOSBinFormatELF())
215 Builder.defineMacro("__ELF__");
216
217 // Target properties.
218 if (!getTriple().isOSWindows() && getTriple().isArch64Bit()) {
219 Builder.defineMacro("_LP64");
220 Builder.defineMacro("__LP64__");
221 }
222
223 std::string CodeModel = getTargetOpts().CodeModel;
224 if (CodeModel == "default")
225 CodeModel = "small";
226 for (char &c : CodeModel)
227 c = toupper(c);
228 Builder.defineMacro("__AARCH64_CMODEL_" + CodeModel + "__");
229
230 // ACLE predefines. Many can only have one possible value on v8 AArch64.
231 Builder.defineMacro("__ARM_ACLE", "200");
232 Builder.defineMacro("__ARM_ARCH", "8");
233 Builder.defineMacro("__ARM_ARCH_PROFILE", "'A'");
234
235 Builder.defineMacro("__ARM_64BIT_STATE", "1");
236 Builder.defineMacro("__ARM_PCS_AAPCS64", "1");
237 Builder.defineMacro("__ARM_ARCH_ISA_A64", "1");
238
239 Builder.defineMacro("__ARM_FEATURE_CLZ", "1");
240 Builder.defineMacro("__ARM_FEATURE_FMA", "1");
241 Builder.defineMacro("__ARM_FEATURE_LDREX", "0xF");
242 Builder.defineMacro("__ARM_FEATURE_IDIV", "1"); // As specified in ACLE
243 Builder.defineMacro("__ARM_FEATURE_DIV"); // For backwards compatibility
244 Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN", "1");
245 Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING", "1");
246
247 Builder.defineMacro("__ARM_ALIGN_MAX_STACK_PWR", "4");
248
249 // 0xe implies support for half, single and double precision operations.
250 Builder.defineMacro("__ARM_FP", "0xE");
251
252 // PCS specifies this for SysV variants, which is all we support. Other ABIs
253 // may choose __ARM_FP16_FORMAT_ALTERNATIVE.
254 Builder.defineMacro("__ARM_FP16_FORMAT_IEEE", "1");
255 Builder.defineMacro("__ARM_FP16_ARGS", "1");
256
257 if (Opts.UnsafeFPMath)
258 Builder.defineMacro("__ARM_FP_FAST", "1");
259
260 Builder.defineMacro("__ARM_SIZEOF_WCHAR_T",
261 Twine(Opts.WCharSize ? Opts.WCharSize : 4));
262
263 Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM", Opts.ShortEnums ? "1" : "4");
264
265 if (FPU & NeonMode) {
266 Builder.defineMacro("__ARM_NEON", "1");
267 // 64-bit NEON supports half, single and double precision operations.
268 Builder.defineMacro("__ARM_NEON_FP", "0xE");
269 }
270
271 if (FPU & SveMode)
272 Builder.defineMacro("__ARM_FEATURE_SVE", "1");
273
274 if (HasSVE2)
275 Builder.defineMacro("__ARM_FEATURE_SVE2", "1");
276
277 if (HasSVE2 && HasSVE2AES)
278 Builder.defineMacro("__ARM_FEATURE_SVE2_AES", "1");
279
280 if (HasSVE2 && HasSVE2BitPerm)
281 Builder.defineMacro("__ARM_FEATURE_SVE2_BITPERM", "1");
282
283 if (HasSVE2 && HasSVE2SHA3)
284 Builder.defineMacro("__ARM_FEATURE_SVE2_SHA3", "1");
285
286 if (HasSVE2 && HasSVE2SM4)
287 Builder.defineMacro("__ARM_FEATURE_SVE2_SM4", "1");
288
289 if (HasCRC)
290 Builder.defineMacro("__ARM_FEATURE_CRC32", "1");
291
292 // The __ARM_FEATURE_CRYPTO is deprecated in favor of finer grained feature
293 // macros for AES, SHA2, SHA3 and SM4
294 if (HasAES && HasSHA2)
295 Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1");
296
297 if (HasAES)
298 Builder.defineMacro("__ARM_FEATURE_AES", "1");
299
300 if (HasSHA2)
301 Builder.defineMacro("__ARM_FEATURE_SHA2", "1");
302
303 if (HasSHA3) {
304 Builder.defineMacro("__ARM_FEATURE_SHA3", "1");
305 Builder.defineMacro("__ARM_FEATURE_SHA512", "1");
306 }
307
308 if (HasSM4) {
309 Builder.defineMacro("__ARM_FEATURE_SM3", "1");
310 Builder.defineMacro("__ARM_FEATURE_SM4", "1");
311 }
312
313 if (HasUnaligned)
314 Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1");
315
316 if ((FPU & NeonMode) && HasFullFP16)
317 Builder.defineMacro("__ARM_FEATURE_FP16_VECTOR_ARITHMETIC", "1");
318 if (HasFullFP16)
319 Builder.defineMacro("__ARM_FEATURE_FP16_SCALAR_ARITHMETIC", "1");
320
321 if (HasDotProd)
322 Builder.defineMacro("__ARM_FEATURE_DOTPROD", "1");
323
324 if (HasMTE)
325 Builder.defineMacro("__ARM_FEATURE_MEMORY_TAGGING", "1");
326
327 if (HasTME)
328 Builder.defineMacro("__ARM_FEATURE_TME", "1");
329
330 if (HasMatMul)
331 Builder.defineMacro("__ARM_FEATURE_MATMUL_INT8", "1");
332
333 if (HasLSE)
334 Builder.defineMacro("__ARM_FEATURE_ATOMICS", "1");
335
336 if (HasBFloat16) {
337 Builder.defineMacro("__ARM_FEATURE_BF16", "1");
338 Builder.defineMacro("__ARM_FEATURE_BF16_VECTOR_ARITHMETIC", "1");
339 Builder.defineMacro("__ARM_BF16_FORMAT_ALTERNATIVE", "1");
340 Builder.defineMacro("__ARM_FEATURE_BF16_SCALAR_ARITHMETIC", "1");
341 }
342
343 if ((FPU & SveMode) && HasBFloat16) {
344 Builder.defineMacro("__ARM_FEATURE_SVE_BF16", "1");
345 }
346
347 if ((FPU & SveMode) && HasMatmulFP64)
348 Builder.defineMacro("__ARM_FEATURE_SVE_MATMUL_FP64", "1");
349
350 if ((FPU & SveMode) && HasMatmulFP32)
351 Builder.defineMacro("__ARM_FEATURE_SVE_MATMUL_FP32", "1");
352
353 if ((FPU & SveMode) && HasMatMul)
354 Builder.defineMacro("__ARM_FEATURE_SVE_MATMUL_INT8", "1");
355
356 if ((FPU & NeonMode) && HasFP16FML)
357 Builder.defineMacro("__ARM_FEATURE_FP16_FML", "1");
358
359 if (Opts.hasSignReturnAddress()) {
360 // Bitmask:
361 // 0: Protection using the A key
362 // 1: Protection using the B key
363 // 2: Protection including leaf functions
364 unsigned Value = 0;
365
366 if (Opts.isSignReturnAddressWithAKey())
367 Value |= (1 << 0);
368 else
369 Value |= (1 << 1);
370
371 if (Opts.isSignReturnAddressScopeAll())
372 Value |= (1 << 2);
373
374 Builder.defineMacro("__ARM_FEATURE_PAC_DEFAULT", std::to_string(Value));
375 }
376
377 if (Opts.BranchTargetEnforcement)
378 Builder.defineMacro("__ARM_FEATURE_BTI_DEFAULT", "1");
379
380 if (HasLS64)
381 Builder.defineMacro("__ARM_FEATURE_LS64", "1");
382
383 if (HasRandGen)
384 Builder.defineMacro("__ARM_FEATURE_RNG", "1");
385
386 switch (ArchKind) {
387 default:
388 break;
389 case llvm::AArch64::ArchKind::ARMV8_1A:
390 getTargetDefinesARMV81A(Opts, Builder);
391 break;
392 case llvm::AArch64::ArchKind::ARMV8_2A:
393 getTargetDefinesARMV82A(Opts, Builder);
394 break;
395 case llvm::AArch64::ArchKind::ARMV8_3A:
396 getTargetDefinesARMV83A(Opts, Builder);
397 break;
398 case llvm::AArch64::ArchKind::ARMV8_4A:
399 getTargetDefinesARMV84A(Opts, Builder);
400 break;
401 case llvm::AArch64::ArchKind::ARMV8_5A:
402 getTargetDefinesARMV85A(Opts, Builder);
403 break;
404 case llvm::AArch64::ArchKind::ARMV8_6A:
405 getTargetDefinesARMV86A(Opts, Builder);
406 break;
407 case llvm::AArch64::ArchKind::ARMV8_7A:
408 getTargetDefinesARMV87A(Opts, Builder);
409 break;
410 }
411
412 // All of the __sync_(bool|val)_compare_and_swap_(1|2|4|8) builtins work.
413 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
414 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
415 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
416 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
417
418 if (Opts.ArmSveVectorBits) {
419 Builder.defineMacro("__ARM_FEATURE_SVE_BITS", Twine(Opts.ArmSveVectorBits));
420 Builder.defineMacro("__ARM_FEATURE_SVE_VECTOR_OPERATORS");
421 }
422 }
423
getTargetBuiltins() const424 ArrayRef<Builtin::Info> AArch64TargetInfo::getTargetBuiltins() const {
425 return llvm::makeArrayRef(BuiltinInfo, clang::AArch64::LastTSBuiltin -
426 Builtin::FirstTSBuiltin);
427 }
428
hasFeature(StringRef Feature) const429 bool AArch64TargetInfo::hasFeature(StringRef Feature) const {
430 return Feature == "aarch64" || Feature == "arm64" || Feature == "arm" ||
431 (Feature == "neon" && (FPU & NeonMode)) ||
432 ((Feature == "sve" || Feature == "sve2" || Feature == "sve2-bitperm" ||
433 Feature == "sve2-aes" || Feature == "sve2-sha3" ||
434 Feature == "sve2-sm4" || Feature == "f64mm" || Feature == "f32mm" ||
435 Feature == "i8mm" || Feature == "bf16") &&
436 (FPU & SveMode)) ||
437 (Feature == "ls64" && HasLS64);
438 }
439
handleTargetFeatures(std::vector<std::string> & Features,DiagnosticsEngine & Diags)440 bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
441 DiagnosticsEngine &Diags) {
442 FPU = FPUMode;
443 HasCRC = false;
444 HasCrypto = false;
445 HasAES = false;
446 HasSHA2 = false;
447 HasSHA3 = false;
448 HasSM4 = false;
449 HasUnaligned = true;
450 HasFullFP16 = false;
451 HasDotProd = false;
452 HasFP16FML = false;
453 HasMTE = false;
454 HasTME = false;
455 HasLS64 = false;
456 HasRandGen = false;
457 HasMatMul = false;
458 HasBFloat16 = false;
459 HasSVE2 = false;
460 HasSVE2AES = false;
461 HasSVE2SHA3 = false;
462 HasSVE2SM4 = false;
463 HasSVE2BitPerm = false;
464 HasMatmulFP64 = false;
465 HasMatmulFP32 = false;
466 HasLSE = false;
467
468 ArchKind = llvm::AArch64::ArchKind::ARMV8A;
469
470 for (const auto &Feature : Features) {
471 if (Feature == "+neon")
472 FPU |= NeonMode;
473 if (Feature == "+sve") {
474 FPU |= SveMode;
475 HasFullFP16 = 1;
476 }
477 if (Feature == "+sve2") {
478 FPU |= SveMode;
479 HasFullFP16 = 1;
480 HasSVE2 = 1;
481 }
482 if (Feature == "+sve2-aes") {
483 FPU |= SveMode;
484 HasFullFP16 = 1;
485 HasSVE2 = 1;
486 HasSVE2AES = 1;
487 }
488 if (Feature == "+sve2-sha3") {
489 FPU |= SveMode;
490 HasFullFP16 = 1;
491 HasSVE2 = 1;
492 HasSVE2SHA3 = 1;
493 }
494 if (Feature == "+sve2-sm4") {
495 FPU |= SveMode;
496 HasFullFP16 = 1;
497 HasSVE2 = 1;
498 HasSVE2SM4 = 1;
499 }
500 if (Feature == "+sve2-bitperm") {
501 FPU |= SveMode;
502 HasFullFP16 = 1;
503 HasSVE2 = 1;
504 HasSVE2BitPerm = 1;
505 }
506 if (Feature == "+f32mm") {
507 FPU |= SveMode;
508 HasMatmulFP32 = true;
509 }
510 if (Feature == "+f64mm") {
511 FPU |= SveMode;
512 HasMatmulFP64 = true;
513 }
514 if (Feature == "+crc")
515 HasCRC = true;
516 if (Feature == "+crypto")
517 HasCrypto = true;
518 if (Feature == "+aes")
519 HasAES = true;
520 if (Feature == "+sha2")
521 HasSHA2 = true;
522 if (Feature == "+sha3") {
523 HasSHA2 = true;
524 HasSHA3 = true;
525 }
526 if (Feature == "+sm4")
527 HasSM4 = true;
528 if (Feature == "+strict-align")
529 HasUnaligned = false;
530 if (Feature == "+v8.1a")
531 ArchKind = llvm::AArch64::ArchKind::ARMV8_1A;
532 if (Feature == "+v8.2a")
533 ArchKind = llvm::AArch64::ArchKind::ARMV8_2A;
534 if (Feature == "+v8.3a")
535 ArchKind = llvm::AArch64::ArchKind::ARMV8_3A;
536 if (Feature == "+v8.4a")
537 ArchKind = llvm::AArch64::ArchKind::ARMV8_4A;
538 if (Feature == "+v8.5a")
539 ArchKind = llvm::AArch64::ArchKind::ARMV8_5A;
540 if (Feature == "+v8.6a")
541 ArchKind = llvm::AArch64::ArchKind::ARMV8_6A;
542 if (Feature == "+v8.7a")
543 ArchKind = llvm::AArch64::ArchKind::ARMV8_7A;
544 if (Feature == "+v8r")
545 ArchKind = llvm::AArch64::ArchKind::ARMV8R;
546 if (Feature == "+fullfp16")
547 HasFullFP16 = true;
548 if (Feature == "+dotprod")
549 HasDotProd = true;
550 if (Feature == "+fp16fml")
551 HasFP16FML = true;
552 if (Feature == "+mte")
553 HasMTE = true;
554 if (Feature == "+tme")
555 HasTME = true;
556 if (Feature == "+pauth")
557 HasPAuth = true;
558 if (Feature == "+i8mm")
559 HasMatMul = true;
560 if (Feature == "+bf16")
561 HasBFloat16 = true;
562 if (Feature == "+lse")
563 HasLSE = true;
564 if (Feature == "+ls64")
565 HasLS64 = true;
566 if (Feature == "+rand")
567 HasRandGen = true;
568 if (Feature == "+flagm")
569 HasFlagM = true;
570 }
571
572 setDataLayout();
573
574 return true;
575 }
576
577 TargetInfo::CallingConvCheckResult
checkCallingConvention(CallingConv CC) const578 AArch64TargetInfo::checkCallingConvention(CallingConv CC) const {
579 switch (CC) {
580 case CC_C:
581 case CC_Swift:
582 case CC_SwiftAsync:
583 case CC_PreserveMost:
584 case CC_PreserveAll:
585 case CC_OpenCLKernel:
586 case CC_AArch64VectorCall:
587 case CC_Win64:
588 return CCCR_OK;
589 default:
590 return CCCR_Warning;
591 }
592 }
593
isCLZForZeroUndef() const594 bool AArch64TargetInfo::isCLZForZeroUndef() const { return false; }
595
getBuiltinVaListKind() const596 TargetInfo::BuiltinVaListKind AArch64TargetInfo::getBuiltinVaListKind() const {
597 return TargetInfo::AArch64ABIBuiltinVaList;
598 }
599
600 const char *const AArch64TargetInfo::GCCRegNames[] = {
601 // 32-bit Integer registers
602 "w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7", "w8", "w9", "w10", "w11",
603 "w12", "w13", "w14", "w15", "w16", "w17", "w18", "w19", "w20", "w21", "w22",
604 "w23", "w24", "w25", "w26", "w27", "w28", "w29", "w30", "wsp",
605
606 // 64-bit Integer registers
607 "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11",
608 "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22",
609 "x23", "x24", "x25", "x26", "x27", "x28", "fp", "lr", "sp",
610
611 // 32-bit floating point regsisters
612 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11",
613 "s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22",
614 "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
615
616 // 64-bit floating point regsisters
617 "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11",
618 "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19", "d20", "d21", "d22",
619 "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",
620
621 // Neon vector registers
622 "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11",
623 "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", "v20", "v21", "v22",
624 "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31",
625
626 // SVE vector registers
627 "z0", "z1", "z2", "z3", "z4", "z5", "z6", "z7", "z8", "z9", "z10",
628 "z11", "z12", "z13", "z14", "z15", "z16", "z17", "z18", "z19", "z20", "z21",
629 "z22", "z23", "z24", "z25", "z26", "z27", "z28", "z29", "z30", "z31",
630
631 // SVE predicate registers
632 "p0", "p1", "p2", "p3", "p4", "p5", "p6", "p7", "p8", "p9", "p10",
633 "p11", "p12", "p13", "p14", "p15"
634 };
635
getGCCRegNames() const636 ArrayRef<const char *> AArch64TargetInfo::getGCCRegNames() const {
637 return llvm::makeArrayRef(GCCRegNames);
638 }
639
640 const TargetInfo::GCCRegAlias AArch64TargetInfo::GCCRegAliases[] = {
641 {{"w31"}, "wsp"},
642 {{"x31"}, "sp"},
643 // GCC rN registers are aliases of xN registers.
644 {{"r0"}, "x0"},
645 {{"r1"}, "x1"},
646 {{"r2"}, "x2"},
647 {{"r3"}, "x3"},
648 {{"r4"}, "x4"},
649 {{"r5"}, "x5"},
650 {{"r6"}, "x6"},
651 {{"r7"}, "x7"},
652 {{"r8"}, "x8"},
653 {{"r9"}, "x9"},
654 {{"r10"}, "x10"},
655 {{"r11"}, "x11"},
656 {{"r12"}, "x12"},
657 {{"r13"}, "x13"},
658 {{"r14"}, "x14"},
659 {{"r15"}, "x15"},
660 {{"r16"}, "x16"},
661 {{"r17"}, "x17"},
662 {{"r18"}, "x18"},
663 {{"r19"}, "x19"},
664 {{"r20"}, "x20"},
665 {{"r21"}, "x21"},
666 {{"r22"}, "x22"},
667 {{"r23"}, "x23"},
668 {{"r24"}, "x24"},
669 {{"r25"}, "x25"},
670 {{"r26"}, "x26"},
671 {{"r27"}, "x27"},
672 {{"r28"}, "x28"},
673 {{"r29", "x29"}, "fp"},
674 {{"r30", "x30"}, "lr"},
675 // The S/D/Q and W/X registers overlap, but aren't really aliases; we
676 // don't want to substitute one of these for a different-sized one.
677 };
678
getGCCRegAliases() const679 ArrayRef<TargetInfo::GCCRegAlias> AArch64TargetInfo::getGCCRegAliases() const {
680 return llvm::makeArrayRef(GCCRegAliases);
681 }
682
validateAsmConstraint(const char * & Name,TargetInfo::ConstraintInfo & Info) const683 bool AArch64TargetInfo::validateAsmConstraint(
684 const char *&Name, TargetInfo::ConstraintInfo &Info) const {
685 switch (*Name) {
686 default:
687 return false;
688 case 'w': // Floating point and SIMD registers (V0-V31)
689 Info.setAllowsRegister();
690 return true;
691 case 'I': // Constant that can be used with an ADD instruction
692 case 'J': // Constant that can be used with a SUB instruction
693 case 'K': // Constant that can be used with a 32-bit logical instruction
694 case 'L': // Constant that can be used with a 64-bit logical instruction
695 case 'M': // Constant that can be used as a 32-bit MOV immediate
696 case 'N': // Constant that can be used as a 64-bit MOV immediate
697 case 'Y': // Floating point constant zero
698 case 'Z': // Integer constant zero
699 return true;
700 case 'Q': // A memory reference with base register and no offset
701 Info.setAllowsMemory();
702 return true;
703 case 'S': // A symbolic address
704 Info.setAllowsRegister();
705 return true;
706 case 'U':
707 if (Name[1] == 'p' && (Name[2] == 'l' || Name[2] == 'a')) {
708 // SVE predicate registers ("Upa"=P0-15, "Upl"=P0-P7)
709 Info.setAllowsRegister();
710 Name += 2;
711 return true;
712 }
713 // Ump: A memory address suitable for ldp/stp in SI, DI, SF and DF modes.
714 // Utf: A memory address suitable for ldp/stp in TF mode.
715 // Usa: An absolute symbolic address.
716 // Ush: The high part (bits 32:12) of a pc-relative symbolic address.
717
718 // Better to return an error saying that it's an unrecognised constraint
719 // even if this is a valid constraint in gcc.
720 return false;
721 case 'z': // Zero register, wzr or xzr
722 Info.setAllowsRegister();
723 return true;
724 case 'x': // Floating point and SIMD registers (V0-V15)
725 Info.setAllowsRegister();
726 return true;
727 case 'y': // SVE registers (V0-V7)
728 Info.setAllowsRegister();
729 return true;
730 }
731 return false;
732 }
733
validateConstraintModifier(StringRef Constraint,char Modifier,unsigned Size,std::string & SuggestedModifier) const734 bool AArch64TargetInfo::validateConstraintModifier(
735 StringRef Constraint, char Modifier, unsigned Size,
736 std::string &SuggestedModifier) const {
737 // Strip off constraint modifiers.
738 while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&')
739 Constraint = Constraint.substr(1);
740
741 switch (Constraint[0]) {
742 default:
743 return true;
744 case 'z':
745 case 'r': {
746 switch (Modifier) {
747 case 'x':
748 case 'w':
749 // For now assume that the person knows what they're
750 // doing with the modifier.
751 return true;
752 default:
753 // By default an 'r' constraint will be in the 'x'
754 // registers.
755 if (Size == 64)
756 return true;
757
758 if (Size == 512)
759 return HasLS64;
760
761 SuggestedModifier = "w";
762 return false;
763 }
764 }
765 }
766 }
767
getClobbers() const768 const char *AArch64TargetInfo::getClobbers() const { return ""; }
769
getEHDataRegisterNumber(unsigned RegNo) const770 int AArch64TargetInfo::getEHDataRegisterNumber(unsigned RegNo) const {
771 if (RegNo == 0)
772 return 0;
773 if (RegNo == 1)
774 return 1;
775 return -1;
776 }
777
hasInt128Type() const778 bool AArch64TargetInfo::hasInt128Type() const { return true; }
779
AArch64leTargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)780 AArch64leTargetInfo::AArch64leTargetInfo(const llvm::Triple &Triple,
781 const TargetOptions &Opts)
782 : AArch64TargetInfo(Triple, Opts) {}
783
setDataLayout()784 void AArch64leTargetInfo::setDataLayout() {
785 if (getTriple().isOSBinFormatMachO()) {
786 if(getTriple().isArch32Bit())
787 resetDataLayout("e-m:o-p:32:32-i64:64-i128:128-n32:64-S128", "_");
788 else
789 resetDataLayout("e-m:o-i64:64-i128:128-n32:64-S128", "_");
790 } else
791 resetDataLayout("e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
792 }
793
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder) const794 void AArch64leTargetInfo::getTargetDefines(const LangOptions &Opts,
795 MacroBuilder &Builder) const {
796 Builder.defineMacro("__AARCH64EL__");
797 AArch64TargetInfo::getTargetDefines(Opts, Builder);
798 }
799
AArch64beTargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)800 AArch64beTargetInfo::AArch64beTargetInfo(const llvm::Triple &Triple,
801 const TargetOptions &Opts)
802 : AArch64TargetInfo(Triple, Opts) {}
803
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder) const804 void AArch64beTargetInfo::getTargetDefines(const LangOptions &Opts,
805 MacroBuilder &Builder) const {
806 Builder.defineMacro("__AARCH64EB__");
807 Builder.defineMacro("__AARCH_BIG_ENDIAN");
808 Builder.defineMacro("__ARM_BIG_ENDIAN");
809 AArch64TargetInfo::getTargetDefines(Opts, Builder);
810 }
811
setDataLayout()812 void AArch64beTargetInfo::setDataLayout() {
813 assert(!getTriple().isOSBinFormatMachO());
814 resetDataLayout("E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
815 }
816
WindowsARM64TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)817 WindowsARM64TargetInfo::WindowsARM64TargetInfo(const llvm::Triple &Triple,
818 const TargetOptions &Opts)
819 : WindowsTargetInfo<AArch64leTargetInfo>(Triple, Opts), Triple(Triple) {
820
821 // This is an LLP64 platform.
822 // int:4, long:4, long long:8, long double:8.
823 IntWidth = IntAlign = 32;
824 LongWidth = LongAlign = 32;
825 DoubleAlign = LongLongAlign = 64;
826 LongDoubleWidth = LongDoubleAlign = 64;
827 LongDoubleFormat = &llvm::APFloat::IEEEdouble();
828 IntMaxType = SignedLongLong;
829 Int64Type = SignedLongLong;
830 SizeType = UnsignedLongLong;
831 PtrDiffType = SignedLongLong;
832 IntPtrType = SignedLongLong;
833 }
834
setDataLayout()835 void WindowsARM64TargetInfo::setDataLayout() {
836 resetDataLayout(Triple.isOSBinFormatMachO()
837 ? "e-m:o-i64:64-i128:128-n32:64-S128"
838 : "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128",
839 Triple.isOSBinFormatMachO() ? "_" : "");
840 }
841
842 TargetInfo::BuiltinVaListKind
getBuiltinVaListKind() const843 WindowsARM64TargetInfo::getBuiltinVaListKind() const {
844 return TargetInfo::CharPtrBuiltinVaList;
845 }
846
847 TargetInfo::CallingConvCheckResult
checkCallingConvention(CallingConv CC) const848 WindowsARM64TargetInfo::checkCallingConvention(CallingConv CC) const {
849 switch (CC) {
850 case CC_X86StdCall:
851 case CC_X86ThisCall:
852 case CC_X86FastCall:
853 case CC_X86VectorCall:
854 return CCCR_Ignore;
855 case CC_C:
856 case CC_OpenCLKernel:
857 case CC_PreserveMost:
858 case CC_PreserveAll:
859 case CC_Swift:
860 case CC_SwiftAsync:
861 case CC_Win64:
862 return CCCR_OK;
863 default:
864 return CCCR_Warning;
865 }
866 }
867
MicrosoftARM64TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)868 MicrosoftARM64TargetInfo::MicrosoftARM64TargetInfo(const llvm::Triple &Triple,
869 const TargetOptions &Opts)
870 : WindowsARM64TargetInfo(Triple, Opts) {
871 TheCXXABI.set(TargetCXXABI::Microsoft);
872 }
873
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder) const874 void MicrosoftARM64TargetInfo::getTargetDefines(const LangOptions &Opts,
875 MacroBuilder &Builder) const {
876 WindowsARM64TargetInfo::getTargetDefines(Opts, Builder);
877 Builder.defineMacro("_M_ARM64", "1");
878 }
879
880 TargetInfo::CallingConvKind
getCallingConvKind(bool ClangABICompat4) const881 MicrosoftARM64TargetInfo::getCallingConvKind(bool ClangABICompat4) const {
882 return CCK_MicrosoftWin64;
883 }
884
getMinGlobalAlign(uint64_t TypeSize) const885 unsigned MicrosoftARM64TargetInfo::getMinGlobalAlign(uint64_t TypeSize) const {
886 unsigned Align = WindowsARM64TargetInfo::getMinGlobalAlign(TypeSize);
887
888 // MSVC does size based alignment for arm64 based on alignment section in
889 // below document, replicate that to keep alignment consistent with object
890 // files compiled by MSVC.
891 // https://docs.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions
892 if (TypeSize >= 512) { // TypeSize >= 64 bytes
893 Align = std::max(Align, 128u); // align type at least 16 bytes
894 } else if (TypeSize >= 64) { // TypeSize >= 8 bytes
895 Align = std::max(Align, 64u); // align type at least 8 butes
896 } else if (TypeSize >= 16) { // TypeSize >= 2 bytes
897 Align = std::max(Align, 32u); // align type at least 4 bytes
898 }
899 return Align;
900 }
901
MinGWARM64TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)902 MinGWARM64TargetInfo::MinGWARM64TargetInfo(const llvm::Triple &Triple,
903 const TargetOptions &Opts)
904 : WindowsARM64TargetInfo(Triple, Opts) {
905 TheCXXABI.set(TargetCXXABI::GenericAArch64);
906 }
907
DarwinAArch64TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)908 DarwinAArch64TargetInfo::DarwinAArch64TargetInfo(const llvm::Triple &Triple,
909 const TargetOptions &Opts)
910 : DarwinTargetInfo<AArch64leTargetInfo>(Triple, Opts) {
911 Int64Type = SignedLongLong;
912 if (getTriple().isArch32Bit())
913 IntMaxType = SignedLongLong;
914
915 WCharType = SignedInt;
916 UseSignedCharForObjCBool = false;
917
918 LongDoubleWidth = LongDoubleAlign = SuitableAlign = 64;
919 LongDoubleFormat = &llvm::APFloat::IEEEdouble();
920
921 UseZeroLengthBitfieldAlignment = false;
922
923 if (getTriple().isArch32Bit()) {
924 UseBitFieldTypeAlignment = false;
925 ZeroLengthBitfieldBoundary = 32;
926 UseZeroLengthBitfieldAlignment = true;
927 TheCXXABI.set(TargetCXXABI::WatchOS);
928 } else
929 TheCXXABI.set(TargetCXXABI::AppleARM64);
930 }
931
getOSDefines(const LangOptions & Opts,const llvm::Triple & Triple,MacroBuilder & Builder) const932 void DarwinAArch64TargetInfo::getOSDefines(const LangOptions &Opts,
933 const llvm::Triple &Triple,
934 MacroBuilder &Builder) const {
935 Builder.defineMacro("__AARCH64_SIMD__");
936 if (Triple.isArch32Bit())
937 Builder.defineMacro("__ARM64_ARCH_8_32__");
938 else
939 Builder.defineMacro("__ARM64_ARCH_8__");
940 Builder.defineMacro("__ARM_NEON__");
941 Builder.defineMacro("__LITTLE_ENDIAN__");
942 Builder.defineMacro("__REGISTER_PREFIX__", "");
943 Builder.defineMacro("__arm64", "1");
944 Builder.defineMacro("__arm64__", "1");
945
946 if (Triple.isArm64e())
947 Builder.defineMacro("__arm64e__", "1");
948
949 getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion);
950 }
951
952 TargetInfo::BuiltinVaListKind
getBuiltinVaListKind() const953 DarwinAArch64TargetInfo::getBuiltinVaListKind() const {
954 return TargetInfo::CharPtrBuiltinVaList;
955 }
956
957 // 64-bit RenderScript is aarch64
RenderScript64TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)958 RenderScript64TargetInfo::RenderScript64TargetInfo(const llvm::Triple &Triple,
959 const TargetOptions &Opts)
960 : AArch64leTargetInfo(llvm::Triple("aarch64", Triple.getVendorName(),
961 Triple.getOSName(),
962 Triple.getEnvironmentName()),
963 Opts) {
964 IsRenderScriptTarget = true;
965 }
966
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder) const967 void RenderScript64TargetInfo::getTargetDefines(const LangOptions &Opts,
968 MacroBuilder &Builder) const {
969 Builder.defineMacro("__RENDERSCRIPT__");
970 AArch64leTargetInfo::getTargetDefines(Opts, Builder);
971 }
972