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