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