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   Builder.defineMacro("__ARM_FEATURE_QRDMX", "1");
159   Builder.defineMacro("__ARM_FEATURE_ATOMICS", "1");
160   Builder.defineMacro("__ARM_FEATURE_CRC32", "1");
161 }
162 
getTargetDefinesARMV82A(const LangOptions & Opts,MacroBuilder & Builder) const163 void AArch64TargetInfo::getTargetDefinesARMV82A(const LangOptions &Opts,
164                                                 MacroBuilder &Builder) const {
165   // Also include the ARMv8.1 defines
166   getTargetDefinesARMV81A(Opts, Builder);
167 }
168 
getTargetDefinesARMV83A(const LangOptions & Opts,MacroBuilder & Builder) const169 void AArch64TargetInfo::getTargetDefinesARMV83A(const LangOptions &Opts,
170                                                 MacroBuilder &Builder) const {
171   Builder.defineMacro("__ARM_FEATURE_COMPLEX", "1");
172   Builder.defineMacro("__ARM_FEATURE_JCVT", "1");
173   // Also include the Armv8.2 defines
174   getTargetDefinesARMV82A(Opts, Builder);
175 }
176 
getTargetDefinesARMV84A(const LangOptions & Opts,MacroBuilder & Builder) const177 void AArch64TargetInfo::getTargetDefinesARMV84A(const LangOptions &Opts,
178                                                 MacroBuilder &Builder) const {
179   // Also include the Armv8.3 defines
180   getTargetDefinesARMV83A(Opts, Builder);
181 }
182 
getTargetDefinesARMV85A(const LangOptions & Opts,MacroBuilder & Builder) const183 void AArch64TargetInfo::getTargetDefinesARMV85A(const LangOptions &Opts,
184                                                 MacroBuilder &Builder) const {
185   // Also include the Armv8.4 defines
186   getTargetDefinesARMV84A(Opts, Builder);
187 }
188 
getTargetDefinesARMV86A(const LangOptions & Opts,MacroBuilder & Builder) const189 void AArch64TargetInfo::getTargetDefinesARMV86A(const LangOptions &Opts,
190                                                 MacroBuilder &Builder) const {
191   // Also include the Armv8.5 defines
192   // FIXME: Armv8.6 makes the following extensions mandatory:
193   // - __ARM_FEATURE_BF16
194   // - __ARM_FEATURE_MATMUL_INT8
195   // Handle them here.
196   getTargetDefinesARMV85A(Opts, Builder);
197 }
198 
getTargetDefinesARMV87A(const LangOptions & Opts,MacroBuilder & Builder) const199 void AArch64TargetInfo::getTargetDefinesARMV87A(const LangOptions &Opts,
200                                                 MacroBuilder &Builder) const {
201   // Also include the Armv8.6 defines
202   getTargetDefinesARMV86A(Opts, Builder);
203 }
204 
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder) const205 void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts,
206                                          MacroBuilder &Builder) const {
207   // Target identification.
208   Builder.defineMacro("__aarch64__");
209   // For bare-metal.
210   if (getTriple().getOS() == llvm::Triple::UnknownOS &&
211       getTriple().isOSBinFormatELF())
212     Builder.defineMacro("__ELF__");
213 
214   // Target properties.
215   if (!getTriple().isOSWindows() && getTriple().isArch64Bit()) {
216     Builder.defineMacro("_LP64");
217     Builder.defineMacro("__LP64__");
218   }
219 
220   std::string CodeModel = getTargetOpts().CodeModel;
221   if (CodeModel == "default")
222     CodeModel = "small";
223   for (char &c : CodeModel)
224     c = toupper(c);
225   Builder.defineMacro("__AARCH64_CMODEL_" + CodeModel + "__");
226 
227   // ACLE predefines. Many can only have one possible value on v8 AArch64.
228   Builder.defineMacro("__ARM_ACLE", "200");
229   Builder.defineMacro("__ARM_ARCH", "8");
230   Builder.defineMacro("__ARM_ARCH_PROFILE", "'A'");
231 
232   Builder.defineMacro("__ARM_64BIT_STATE", "1");
233   Builder.defineMacro("__ARM_PCS_AAPCS64", "1");
234   Builder.defineMacro("__ARM_ARCH_ISA_A64", "1");
235 
236   Builder.defineMacro("__ARM_FEATURE_CLZ", "1");
237   Builder.defineMacro("__ARM_FEATURE_FMA", "1");
238   Builder.defineMacro("__ARM_FEATURE_LDREX", "0xF");
239   Builder.defineMacro("__ARM_FEATURE_IDIV", "1"); // As specified in ACLE
240   Builder.defineMacro("__ARM_FEATURE_DIV");       // For backwards compatibility
241   Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN", "1");
242   Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING", "1");
243 
244   Builder.defineMacro("__ARM_ALIGN_MAX_STACK_PWR", "4");
245 
246   // 0xe implies support for half, single and double precision operations.
247   Builder.defineMacro("__ARM_FP", "0xE");
248 
249   // PCS specifies this for SysV variants, which is all we support. Other ABIs
250   // may choose __ARM_FP16_FORMAT_ALTERNATIVE.
251   Builder.defineMacro("__ARM_FP16_FORMAT_IEEE", "1");
252   Builder.defineMacro("__ARM_FP16_ARGS", "1");
253 
254   if (Opts.UnsafeFPMath)
255     Builder.defineMacro("__ARM_FP_FAST", "1");
256 
257   Builder.defineMacro("__ARM_SIZEOF_WCHAR_T",
258                       Twine(Opts.WCharSize ? Opts.WCharSize : 4));
259 
260   Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM", Opts.ShortEnums ? "1" : "4");
261 
262   if (FPU & NeonMode) {
263     Builder.defineMacro("__ARM_NEON", "1");
264     // 64-bit NEON supports half, single and double precision operations.
265     Builder.defineMacro("__ARM_NEON_FP", "0xE");
266   }
267 
268   if (FPU & SveMode)
269     Builder.defineMacro("__ARM_FEATURE_SVE", "1");
270 
271   if (HasSVE2)
272     Builder.defineMacro("__ARM_FEATURE_SVE2", "1");
273 
274   if (HasSVE2 && HasSVE2AES)
275     Builder.defineMacro("__ARM_FEATURE_SVE2_AES", "1");
276 
277   if (HasSVE2 && HasSVE2BitPerm)
278     Builder.defineMacro("__ARM_FEATURE_SVE2_BITPERM", "1");
279 
280   if (HasSVE2 && HasSVE2SHA3)
281     Builder.defineMacro("__ARM_FEATURE_SVE2_SHA3", "1");
282 
283   if (HasSVE2 && HasSVE2SM4)
284     Builder.defineMacro("__ARM_FEATURE_SVE2_SM4", "1");
285 
286   if (HasCRC)
287     Builder.defineMacro("__ARM_FEATURE_CRC32", "1");
288 
289   if (HasCrypto)
290     Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1");
291 
292   if (HasUnaligned)
293     Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1");
294 
295   if ((FPU & NeonMode) && HasFullFP16)
296     Builder.defineMacro("__ARM_FEATURE_FP16_VECTOR_ARITHMETIC", "1");
297   if (HasFullFP16)
298    Builder.defineMacro("__ARM_FEATURE_FP16_SCALAR_ARITHMETIC", "1");
299 
300   if (HasDotProd)
301     Builder.defineMacro("__ARM_FEATURE_DOTPROD", "1");
302 
303   if (HasMTE)
304     Builder.defineMacro("__ARM_FEATURE_MEMORY_TAGGING", "1");
305 
306   if (HasTME)
307     Builder.defineMacro("__ARM_FEATURE_TME", "1");
308 
309   if (HasMatMul)
310     Builder.defineMacro("__ARM_FEATURE_MATMUL_INT8", "1");
311 
312   if (HasLSE)
313     Builder.defineMacro("__ARM_FEATURE_ATOMICS", "1");
314 
315   if (HasBFloat16) {
316     Builder.defineMacro("__ARM_FEATURE_BF16", "1");
317     Builder.defineMacro("__ARM_FEATURE_BF16_VECTOR_ARITHMETIC", "1");
318     Builder.defineMacro("__ARM_BF16_FORMAT_ALTERNATIVE", "1");
319     Builder.defineMacro("__ARM_FEATURE_BF16_SCALAR_ARITHMETIC", "1");
320   }
321 
322   if ((FPU & SveMode) && HasBFloat16) {
323     Builder.defineMacro("__ARM_FEATURE_SVE_BF16", "1");
324   }
325 
326   if ((FPU & SveMode) && HasMatmulFP64)
327     Builder.defineMacro("__ARM_FEATURE_SVE_MATMUL_FP64", "1");
328 
329   if ((FPU & SveMode) && HasMatmulFP32)
330     Builder.defineMacro("__ARM_FEATURE_SVE_MATMUL_FP32", "1");
331 
332   if ((FPU & SveMode) && HasMatMul)
333     Builder.defineMacro("__ARM_FEATURE_SVE_MATMUL_INT8", "1");
334 
335   if ((FPU & NeonMode) && HasFP16FML)
336     Builder.defineMacro("__ARM_FEATURE_FP16FML", "1");
337 
338   if (Opts.hasSignReturnAddress()) {
339     // Bitmask:
340     // 0: Protection using the A key
341     // 1: Protection using the B key
342     // 2: Protection including leaf functions
343     unsigned Value = 0;
344 
345     if (Opts.isSignReturnAddressWithAKey())
346       Value |= (1 << 0);
347     else
348       Value |= (1 << 1);
349 
350     if (Opts.isSignReturnAddressScopeAll())
351       Value |= (1 << 2);
352 
353     Builder.defineMacro("__ARM_FEATURE_PAC_DEFAULT", std::to_string(Value));
354   }
355 
356   if (Opts.BranchTargetEnforcement)
357     Builder.defineMacro("__ARM_FEATURE_BTI_DEFAULT", "1");
358 
359   if (HasLS64)
360     Builder.defineMacro("__ARM_FEATURE_LS64", "1");
361 
362   switch (ArchKind) {
363   default:
364     break;
365   case llvm::AArch64::ArchKind::ARMV8_1A:
366     getTargetDefinesARMV81A(Opts, Builder);
367     break;
368   case llvm::AArch64::ArchKind::ARMV8_2A:
369     getTargetDefinesARMV82A(Opts, Builder);
370     break;
371   case llvm::AArch64::ArchKind::ARMV8_3A:
372     getTargetDefinesARMV83A(Opts, Builder);
373     break;
374   case llvm::AArch64::ArchKind::ARMV8_4A:
375     getTargetDefinesARMV84A(Opts, Builder);
376     break;
377   case llvm::AArch64::ArchKind::ARMV8_5A:
378     getTargetDefinesARMV85A(Opts, Builder);
379     break;
380   case llvm::AArch64::ArchKind::ARMV8_6A:
381     getTargetDefinesARMV86A(Opts, Builder);
382     break;
383   case llvm::AArch64::ArchKind::ARMV8_7A:
384     getTargetDefinesARMV87A(Opts, Builder);
385     break;
386   }
387 
388   // All of the __sync_(bool|val)_compare_and_swap_(1|2|4|8) builtins work.
389   Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
390   Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
391   Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
392   Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
393 
394   if (Opts.ArmSveVectorBits) {
395     Builder.defineMacro("__ARM_FEATURE_SVE_BITS", Twine(Opts.ArmSveVectorBits));
396     Builder.defineMacro("__ARM_FEATURE_SVE_VECTOR_OPERATORS");
397   }
398 }
399 
getTargetBuiltins() const400 ArrayRef<Builtin::Info> AArch64TargetInfo::getTargetBuiltins() const {
401   return llvm::makeArrayRef(BuiltinInfo, clang::AArch64::LastTSBuiltin -
402                                              Builtin::FirstTSBuiltin);
403 }
404 
hasFeature(StringRef Feature) const405 bool AArch64TargetInfo::hasFeature(StringRef Feature) const {
406   return Feature == "aarch64" || Feature == "arm64" || Feature == "arm" ||
407          (Feature == "neon" && (FPU & NeonMode)) ||
408          ((Feature == "sve" || Feature == "sve2" || Feature == "sve2-bitperm" ||
409            Feature == "sve2-aes" || Feature == "sve2-sha3" ||
410            Feature == "sve2-sm4" || Feature == "f64mm" || Feature == "f32mm" ||
411            Feature == "i8mm" || Feature == "bf16") &&
412           (FPU & SveMode));
413 }
414 
handleTargetFeatures(std::vector<std::string> & Features,DiagnosticsEngine & Diags)415 bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
416                                              DiagnosticsEngine &Diags) {
417   FPU = FPUMode;
418   HasCRC = false;
419   HasCrypto = false;
420   HasUnaligned = true;
421   HasFullFP16 = false;
422   HasDotProd = false;
423   HasFP16FML = false;
424   HasMTE = false;
425   HasTME = false;
426   HasLS64 = false;
427   HasMatMul = false;
428   HasBFloat16 = false;
429   HasSVE2 = false;
430   HasSVE2AES = false;
431   HasSVE2SHA3 = false;
432   HasSVE2SM4 = false;
433   HasSVE2BitPerm = false;
434   HasMatmulFP64 = false;
435   HasMatmulFP32 = false;
436   HasLSE = false;
437 
438   ArchKind = llvm::AArch64::ArchKind::ARMV8A;
439 
440   for (const auto &Feature : Features) {
441     if (Feature == "+neon")
442       FPU |= NeonMode;
443     if (Feature == "+sve") {
444       FPU |= SveMode;
445       HasFullFP16 = 1;
446     }
447     if (Feature == "+sve2") {
448       FPU |= SveMode;
449       HasFullFP16 = 1;
450       HasSVE2 = 1;
451     }
452     if (Feature == "+sve2-aes") {
453       FPU |= SveMode;
454       HasFullFP16 = 1;
455       HasSVE2 = 1;
456       HasSVE2AES = 1;
457     }
458     if (Feature == "+sve2-sha3") {
459       FPU |= SveMode;
460       HasFullFP16 = 1;
461       HasSVE2 = 1;
462       HasSVE2SHA3 = 1;
463     }
464     if (Feature == "+sve2-sm4") {
465       FPU |= SveMode;
466       HasFullFP16 = 1;
467       HasSVE2 = 1;
468       HasSVE2SM4 = 1;
469     }
470     if (Feature == "+sve2-bitperm") {
471       FPU |= SveMode;
472       HasFullFP16 = 1;
473       HasSVE2 = 1;
474       HasSVE2BitPerm = 1;
475     }
476     if (Feature == "+f32mm") {
477       FPU |= SveMode;
478       HasMatmulFP32 = true;
479     }
480     if (Feature == "+f64mm") {
481       FPU |= SveMode;
482       HasMatmulFP64 = true;
483     }
484     if (Feature == "+crc")
485       HasCRC = true;
486     if (Feature == "+crypto")
487       HasCrypto = true;
488     if (Feature == "+strict-align")
489       HasUnaligned = false;
490     if (Feature == "+v8.1a")
491       ArchKind = llvm::AArch64::ArchKind::ARMV8_1A;
492     if (Feature == "+v8.2a")
493       ArchKind = llvm::AArch64::ArchKind::ARMV8_2A;
494     if (Feature == "+v8.3a")
495       ArchKind = llvm::AArch64::ArchKind::ARMV8_3A;
496     if (Feature == "+v8.4a")
497       ArchKind = llvm::AArch64::ArchKind::ARMV8_4A;
498     if (Feature == "+v8.5a")
499       ArchKind = llvm::AArch64::ArchKind::ARMV8_5A;
500     if (Feature == "+v8.6a")
501       ArchKind = llvm::AArch64::ArchKind::ARMV8_6A;
502     if (Feature == "+v8.7a")
503       ArchKind = llvm::AArch64::ArchKind::ARMV8_7A;
504     if (Feature == "+v8r")
505       ArchKind = llvm::AArch64::ArchKind::ARMV8R;
506     if (Feature == "+fullfp16")
507       HasFullFP16 = true;
508     if (Feature == "+dotprod")
509       HasDotProd = true;
510     if (Feature == "+fp16fml")
511       HasFP16FML = true;
512     if (Feature == "+mte")
513       HasMTE = true;
514     if (Feature == "+tme")
515       HasTME = true;
516     if (Feature == "+pauth")
517       HasPAuth = true;
518     if (Feature == "+i8mm")
519       HasMatMul = true;
520     if (Feature == "+bf16")
521       HasBFloat16 = true;
522     if (Feature == "+lse")
523       HasLSE = true;
524     if (Feature == "+ls64")
525       HasLS64 = true;
526     if (Feature == "+flagm")
527       HasFlagM = true;
528   }
529 
530   setDataLayout();
531 
532   return true;
533 }
534 
535 TargetInfo::CallingConvCheckResult
checkCallingConvention(CallingConv CC) const536 AArch64TargetInfo::checkCallingConvention(CallingConv CC) const {
537   switch (CC) {
538   case CC_C:
539   case CC_Swift:
540   case CC_PreserveMost:
541   case CC_PreserveAll:
542   case CC_OpenCLKernel:
543   case CC_AArch64VectorCall:
544   case CC_Win64:
545     return CCCR_OK;
546   default:
547     return CCCR_Warning;
548   }
549 }
550 
isCLZForZeroUndef() const551 bool AArch64TargetInfo::isCLZForZeroUndef() const { return false; }
552 
getBuiltinVaListKind() const553 TargetInfo::BuiltinVaListKind AArch64TargetInfo::getBuiltinVaListKind() const {
554   return TargetInfo::AArch64ABIBuiltinVaList;
555 }
556 
557 const char *const AArch64TargetInfo::GCCRegNames[] = {
558     // 32-bit Integer registers
559     "w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7", "w8", "w9", "w10", "w11",
560     "w12", "w13", "w14", "w15", "w16", "w17", "w18", "w19", "w20", "w21", "w22",
561     "w23", "w24", "w25", "w26", "w27", "w28", "w29", "w30", "wsp",
562 
563     // 64-bit Integer registers
564     "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11",
565     "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22",
566     "x23", "x24", "x25", "x26", "x27", "x28", "fp", "lr", "sp",
567 
568     // 32-bit floating point regsisters
569     "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11",
570     "s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22",
571     "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
572 
573     // 64-bit floating point regsisters
574     "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11",
575     "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19", "d20", "d21", "d22",
576     "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",
577 
578     // Neon vector registers
579     "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11",
580     "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", "v20", "v21", "v22",
581     "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31",
582 
583     // SVE vector registers
584     "z0",  "z1",  "z2",  "z3",  "z4",  "z5",  "z6",  "z7",  "z8",  "z9",  "z10",
585     "z11", "z12", "z13", "z14", "z15", "z16", "z17", "z18", "z19", "z20", "z21",
586     "z22", "z23", "z24", "z25", "z26", "z27", "z28", "z29", "z30", "z31",
587 
588     // SVE predicate registers
589     "p0",  "p1",  "p2",  "p3",  "p4",  "p5",  "p6",  "p7",  "p8",  "p9",  "p10",
590     "p11", "p12", "p13", "p14", "p15"
591 };
592 
getGCCRegNames() const593 ArrayRef<const char *> AArch64TargetInfo::getGCCRegNames() const {
594   return llvm::makeArrayRef(GCCRegNames);
595 }
596 
597 const TargetInfo::GCCRegAlias AArch64TargetInfo::GCCRegAliases[] = {
598     {{"w31"}, "wsp"},
599     {{"x31"}, "sp"},
600     // GCC rN registers are aliases of xN registers.
601     {{"r0"}, "x0"},
602     {{"r1"}, "x1"},
603     {{"r2"}, "x2"},
604     {{"r3"}, "x3"},
605     {{"r4"}, "x4"},
606     {{"r5"}, "x5"},
607     {{"r6"}, "x6"},
608     {{"r7"}, "x7"},
609     {{"r8"}, "x8"},
610     {{"r9"}, "x9"},
611     {{"r10"}, "x10"},
612     {{"r11"}, "x11"},
613     {{"r12"}, "x12"},
614     {{"r13"}, "x13"},
615     {{"r14"}, "x14"},
616     {{"r15"}, "x15"},
617     {{"r16"}, "x16"},
618     {{"r17"}, "x17"},
619     {{"r18"}, "x18"},
620     {{"r19"}, "x19"},
621     {{"r20"}, "x20"},
622     {{"r21"}, "x21"},
623     {{"r22"}, "x22"},
624     {{"r23"}, "x23"},
625     {{"r24"}, "x24"},
626     {{"r25"}, "x25"},
627     {{"r26"}, "x26"},
628     {{"r27"}, "x27"},
629     {{"r28"}, "x28"},
630     {{"r29", "x29"}, "fp"},
631     {{"r30", "x30"}, "lr"},
632     // The S/D/Q and W/X registers overlap, but aren't really aliases; we
633     // don't want to substitute one of these for a different-sized one.
634 };
635 
getGCCRegAliases() const636 ArrayRef<TargetInfo::GCCRegAlias> AArch64TargetInfo::getGCCRegAliases() const {
637   return llvm::makeArrayRef(GCCRegAliases);
638 }
639 
validateAsmConstraint(const char * & Name,TargetInfo::ConstraintInfo & Info) const640 bool AArch64TargetInfo::validateAsmConstraint(
641     const char *&Name, TargetInfo::ConstraintInfo &Info) const {
642   switch (*Name) {
643   default:
644     return false;
645   case 'w': // Floating point and SIMD registers (V0-V31)
646     Info.setAllowsRegister();
647     return true;
648   case 'I': // Constant that can be used with an ADD instruction
649   case 'J': // Constant that can be used with a SUB instruction
650   case 'K': // Constant that can be used with a 32-bit logical instruction
651   case 'L': // Constant that can be used with a 64-bit logical instruction
652   case 'M': // Constant that can be used as a 32-bit MOV immediate
653   case 'N': // Constant that can be used as a 64-bit MOV immediate
654   case 'Y': // Floating point constant zero
655   case 'Z': // Integer constant zero
656     return true;
657   case 'Q': // A memory reference with base register and no offset
658     Info.setAllowsMemory();
659     return true;
660   case 'S': // A symbolic address
661     Info.setAllowsRegister();
662     return true;
663   case 'U':
664     if (Name[1] == 'p' && (Name[2] == 'l' || Name[2] == 'a')) {
665       // SVE predicate registers ("Upa"=P0-15, "Upl"=P0-P7)
666       Info.setAllowsRegister();
667       Name += 2;
668       return true;
669     }
670     // Ump: A memory address suitable for ldp/stp in SI, DI, SF and DF modes.
671     // Utf: A memory address suitable for ldp/stp in TF mode.
672     // Usa: An absolute symbolic address.
673     // Ush: The high part (bits 32:12) of a pc-relative symbolic address.
674 
675     // Better to return an error saying that it's an unrecognised constraint
676     // even if this is a valid constraint in gcc.
677     return false;
678   case 'z': // Zero register, wzr or xzr
679     Info.setAllowsRegister();
680     return true;
681   case 'x': // Floating point and SIMD registers (V0-V15)
682     Info.setAllowsRegister();
683     return true;
684   case 'y': // SVE registers (V0-V7)
685     Info.setAllowsRegister();
686     return true;
687   }
688   return false;
689 }
690 
validateConstraintModifier(StringRef Constraint,char Modifier,unsigned Size,std::string & SuggestedModifier) const691 bool AArch64TargetInfo::validateConstraintModifier(
692     StringRef Constraint, char Modifier, unsigned Size,
693     std::string &SuggestedModifier) const {
694   // Strip off constraint modifiers.
695   while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&')
696     Constraint = Constraint.substr(1);
697 
698   switch (Constraint[0]) {
699   default:
700     return true;
701   case 'z':
702   case 'r': {
703     switch (Modifier) {
704     case 'x':
705     case 'w':
706       // For now assume that the person knows what they're
707       // doing with the modifier.
708       return true;
709     default:
710       // By default an 'r' constraint will be in the 'x'
711       // registers.
712       if (Size == 64)
713         return true;
714 
715       SuggestedModifier = "w";
716       return false;
717     }
718   }
719   }
720 }
721 
getClobbers() const722 const char *AArch64TargetInfo::getClobbers() const { return ""; }
723 
getEHDataRegisterNumber(unsigned RegNo) const724 int AArch64TargetInfo::getEHDataRegisterNumber(unsigned RegNo) const {
725   if (RegNo == 0)
726     return 0;
727   if (RegNo == 1)
728     return 1;
729   return -1;
730 }
731 
hasInt128Type() const732 bool AArch64TargetInfo::hasInt128Type() const { return true; }
733 
AArch64leTargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)734 AArch64leTargetInfo::AArch64leTargetInfo(const llvm::Triple &Triple,
735                                          const TargetOptions &Opts)
736     : AArch64TargetInfo(Triple, Opts) {}
737 
setDataLayout()738 void AArch64leTargetInfo::setDataLayout() {
739   if (getTriple().isOSBinFormatMachO()) {
740     if(getTriple().isArch32Bit())
741       resetDataLayout("e-m:o-p:32:32-i64:64-i128:128-n32:64-S128");
742     else
743       resetDataLayout("e-m:o-i64:64-i128:128-n32:64-S128");
744   } else
745     resetDataLayout("e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
746 }
747 
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder) const748 void AArch64leTargetInfo::getTargetDefines(const LangOptions &Opts,
749                                            MacroBuilder &Builder) const {
750   Builder.defineMacro("__AARCH64EL__");
751   AArch64TargetInfo::getTargetDefines(Opts, Builder);
752 }
753 
AArch64beTargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)754 AArch64beTargetInfo::AArch64beTargetInfo(const llvm::Triple &Triple,
755                                          const TargetOptions &Opts)
756     : AArch64TargetInfo(Triple, Opts) {}
757 
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder) const758 void AArch64beTargetInfo::getTargetDefines(const LangOptions &Opts,
759                                            MacroBuilder &Builder) const {
760   Builder.defineMacro("__AARCH64EB__");
761   Builder.defineMacro("__AARCH_BIG_ENDIAN");
762   Builder.defineMacro("__ARM_BIG_ENDIAN");
763   AArch64TargetInfo::getTargetDefines(Opts, Builder);
764 }
765 
setDataLayout()766 void AArch64beTargetInfo::setDataLayout() {
767   assert(!getTriple().isOSBinFormatMachO());
768   resetDataLayout("E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
769 }
770 
WindowsARM64TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)771 WindowsARM64TargetInfo::WindowsARM64TargetInfo(const llvm::Triple &Triple,
772                                                const TargetOptions &Opts)
773     : WindowsTargetInfo<AArch64leTargetInfo>(Triple, Opts), Triple(Triple) {
774 
775   // This is an LLP64 platform.
776   // int:4, long:4, long long:8, long double:8.
777   IntWidth = IntAlign = 32;
778   LongWidth = LongAlign = 32;
779   DoubleAlign = LongLongAlign = 64;
780   LongDoubleWidth = LongDoubleAlign = 64;
781   LongDoubleFormat = &llvm::APFloat::IEEEdouble();
782   IntMaxType = SignedLongLong;
783   Int64Type = SignedLongLong;
784   SizeType = UnsignedLongLong;
785   PtrDiffType = SignedLongLong;
786   IntPtrType = SignedLongLong;
787 }
788 
setDataLayout()789 void WindowsARM64TargetInfo::setDataLayout() {
790   resetDataLayout(Triple.isOSBinFormatMachO()
791                       ? "e-m:o-i64:64-i128:128-n32:64-S128"
792                       : "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128");
793 }
794 
795 TargetInfo::BuiltinVaListKind
getBuiltinVaListKind() const796 WindowsARM64TargetInfo::getBuiltinVaListKind() const {
797   return TargetInfo::CharPtrBuiltinVaList;
798 }
799 
800 TargetInfo::CallingConvCheckResult
checkCallingConvention(CallingConv CC) const801 WindowsARM64TargetInfo::checkCallingConvention(CallingConv CC) const {
802   switch (CC) {
803   case CC_X86StdCall:
804   case CC_X86ThisCall:
805   case CC_X86FastCall:
806   case CC_X86VectorCall:
807     return CCCR_Ignore;
808   case CC_C:
809   case CC_OpenCLKernel:
810   case CC_PreserveMost:
811   case CC_PreserveAll:
812   case CC_Swift:
813   case CC_Win64:
814     return CCCR_OK;
815   default:
816     return CCCR_Warning;
817   }
818 }
819 
MicrosoftARM64TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)820 MicrosoftARM64TargetInfo::MicrosoftARM64TargetInfo(const llvm::Triple &Triple,
821                                                    const TargetOptions &Opts)
822     : WindowsARM64TargetInfo(Triple, Opts) {
823   TheCXXABI.set(TargetCXXABI::Microsoft);
824 }
825 
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder) const826 void MicrosoftARM64TargetInfo::getTargetDefines(const LangOptions &Opts,
827                                                 MacroBuilder &Builder) const {
828   WindowsARM64TargetInfo::getTargetDefines(Opts, Builder);
829   Builder.defineMacro("_M_ARM64", "1");
830 }
831 
832 TargetInfo::CallingConvKind
getCallingConvKind(bool ClangABICompat4) const833 MicrosoftARM64TargetInfo::getCallingConvKind(bool ClangABICompat4) const {
834   return CCK_MicrosoftWin64;
835 }
836 
getMinGlobalAlign(uint64_t TypeSize) const837 unsigned MicrosoftARM64TargetInfo::getMinGlobalAlign(uint64_t TypeSize) const {
838   unsigned Align = WindowsARM64TargetInfo::getMinGlobalAlign(TypeSize);
839 
840   // MSVC does size based alignment for arm64 based on alignment section in
841   // below document, replicate that to keep alignment consistent with object
842   // files compiled by MSVC.
843   // https://docs.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions
844   if (TypeSize >= 512) {              // TypeSize >= 64 bytes
845     Align = std::max(Align, 128u);    // align type at least 16 bytes
846   } else if (TypeSize >= 64) {        // TypeSize >= 8 bytes
847     Align = std::max(Align, 64u);     // align type at least 8 butes
848   } else if (TypeSize >= 16) {        // TypeSize >= 2 bytes
849     Align = std::max(Align, 32u);     // align type at least 4 bytes
850   }
851   return Align;
852 }
853 
MinGWARM64TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)854 MinGWARM64TargetInfo::MinGWARM64TargetInfo(const llvm::Triple &Triple,
855                                            const TargetOptions &Opts)
856     : WindowsARM64TargetInfo(Triple, Opts) {
857   TheCXXABI.set(TargetCXXABI::GenericAArch64);
858 }
859 
DarwinAArch64TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)860 DarwinAArch64TargetInfo::DarwinAArch64TargetInfo(const llvm::Triple &Triple,
861                                                  const TargetOptions &Opts)
862     : DarwinTargetInfo<AArch64leTargetInfo>(Triple, Opts) {
863   Int64Type = SignedLongLong;
864   if (getTriple().isArch32Bit())
865     IntMaxType = SignedLongLong;
866 
867   WCharType = SignedInt;
868   UseSignedCharForObjCBool = false;
869 
870   LongDoubleWidth = LongDoubleAlign = SuitableAlign = 64;
871   LongDoubleFormat = &llvm::APFloat::IEEEdouble();
872 
873   UseZeroLengthBitfieldAlignment = false;
874 
875   if (getTriple().isArch32Bit()) {
876     UseBitFieldTypeAlignment = false;
877     ZeroLengthBitfieldBoundary = 32;
878     UseZeroLengthBitfieldAlignment = true;
879     TheCXXABI.set(TargetCXXABI::WatchOS);
880   } else
881     TheCXXABI.set(TargetCXXABI::AppleARM64);
882 }
883 
getOSDefines(const LangOptions & Opts,const llvm::Triple & Triple,MacroBuilder & Builder) const884 void DarwinAArch64TargetInfo::getOSDefines(const LangOptions &Opts,
885                                            const llvm::Triple &Triple,
886                                            MacroBuilder &Builder) const {
887   Builder.defineMacro("__AARCH64_SIMD__");
888   if (Triple.isArch32Bit())
889     Builder.defineMacro("__ARM64_ARCH_8_32__");
890   else
891     Builder.defineMacro("__ARM64_ARCH_8__");
892   Builder.defineMacro("__ARM_NEON__");
893   Builder.defineMacro("__LITTLE_ENDIAN__");
894   Builder.defineMacro("__REGISTER_PREFIX__", "");
895   Builder.defineMacro("__arm64", "1");
896   Builder.defineMacro("__arm64__", "1");
897 
898   if (Triple.isArm64e())
899     Builder.defineMacro("__arm64e__", "1");
900 
901   getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion);
902 }
903 
904 TargetInfo::BuiltinVaListKind
getBuiltinVaListKind() const905 DarwinAArch64TargetInfo::getBuiltinVaListKind() const {
906   return TargetInfo::CharPtrBuiltinVaList;
907 }
908 
909 // 64-bit RenderScript is aarch64
RenderScript64TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)910 RenderScript64TargetInfo::RenderScript64TargetInfo(const llvm::Triple &Triple,
911                                                    const TargetOptions &Opts)
912     : AArch64leTargetInfo(llvm::Triple("aarch64", Triple.getVendorName(),
913                                        Triple.getOSName(),
914                                        Triple.getEnvironmentName()),
915                           Opts) {
916   IsRenderScriptTarget = true;
917 }
918 
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder) const919 void RenderScript64TargetInfo::getTargetDefines(const LangOptions &Opts,
920                                                 MacroBuilder &Builder) const {
921   Builder.defineMacro("__RENDERSCRIPT__");
922   AArch64leTargetInfo::getTargetDefines(Opts, Builder);
923 }
924