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/TargetBuiltins.h"
15 #include "clang/Basic/TargetInfo.h"
16 #include "llvm/ADT/ArrayRef.h"
17 #include "llvm/ADT/StringExtras.h"
18 
19 using namespace clang;
20 using namespace clang::targets;
21 
22 const Builtin::Info AArch64TargetInfo::BuiltinInfo[] = {
23 #define BUILTIN(ID, TYPE, ATTRS)                                               \
24    {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
25 #include "clang/Basic/BuiltinsNEON.def"
26 
27 #define BUILTIN(ID, TYPE, ATTRS)                                               \
28    {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
29 #define LANGBUILTIN(ID, TYPE, ATTRS, LANG)                                     \
30   {#ID, TYPE, ATTRS, nullptr, LANG, nullptr},
31 #define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE)         \
32   {#ID, TYPE, ATTRS, HEADER, LANGS, FEATURE},
33 #include "clang/Basic/BuiltinsAArch64.def"
34 };
35 
36 AArch64TargetInfo::AArch64TargetInfo(const llvm::Triple &Triple,
37                                      const TargetOptions &Opts)
38     : TargetInfo(Triple), ABI("aapcs") {
39   if (getTriple().isOSOpenBSD()) {
40     Int64Type = SignedLongLong;
41     IntMaxType = SignedLongLong;
42   } else {
43     if (!getTriple().isOSDarwin() && !getTriple().isOSNetBSD())
44       WCharType = UnsignedInt;
45 
46     Int64Type = SignedLong;
47     IntMaxType = SignedLong;
48   }
49 
50   // All AArch64 implementations support ARMv8 FP, which makes half a legal type.
51   HasLegalHalfType = true;
52   HasFloat16 = true;
53 
54   LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
55   MaxVectorAlign = 128;
56   MaxAtomicInlineWidth = 128;
57   MaxAtomicPromoteWidth = 128;
58 
59   LongDoubleWidth = LongDoubleAlign = SuitableAlign = 128;
60   LongDoubleFormat = &llvm::APFloat::IEEEquad();
61 
62   // Make __builtin_ms_va_list available.
63   HasBuiltinMSVaList = true;
64 
65   // {} in inline assembly are neon specifiers, not assembly variant
66   // specifiers.
67   NoAsmVariants = true;
68 
69   // AAPCS gives rules for bitfields. 7.1.7 says: "The container type
70   // contributes to the alignment of the containing aggregate in the same way
71   // a plain (non bit-field) member of that type would, without exception for
72   // zero-sized or anonymous bit-fields."
73   assert(UseBitFieldTypeAlignment && "bitfields affect type alignment");
74   UseZeroLengthBitfieldAlignment = true;
75 
76   // AArch64 targets default to using the ARM C++ ABI.
77   TheCXXABI.set(TargetCXXABI::GenericAArch64);
78 
79   if (Triple.getOS() == llvm::Triple::Linux)
80     this->MCountName = "\01_mcount";
81   else if (Triple.getOS() == llvm::Triple::UnknownOS)
82     this->MCountName =
83         Opts.EABIVersion == llvm::EABI::GNU ? "\01_mcount" : "mcount";
84 }
85 
86 StringRef AArch64TargetInfo::getABI() const { return ABI; }
87 
88 bool AArch64TargetInfo::setABI(const std::string &Name) {
89   if (Name != "aapcs" && Name != "darwinpcs")
90     return false;
91 
92   ABI = Name;
93   return true;
94 }
95 
96 bool AArch64TargetInfo::isValidCPUName(StringRef Name) const {
97   return Name == "generic" ||
98          llvm::AArch64::parseCPUArch(Name) != llvm::AArch64::ArchKind::INVALID;
99 }
100 
101 bool AArch64TargetInfo::setCPU(const std::string &Name) {
102   return isValidCPUName(Name);
103 }
104 
105 void AArch64TargetInfo::fillValidCPUList(
106     SmallVectorImpl<StringRef> &Values) const {
107   llvm::AArch64::fillValidCPUArchList(Values);
108 }
109 
110 void AArch64TargetInfo::getTargetDefinesARMV81A(const LangOptions &Opts,
111                                                 MacroBuilder &Builder) const {
112   Builder.defineMacro("__ARM_FEATURE_QRDMX", "1");
113 }
114 
115 void AArch64TargetInfo::getTargetDefinesARMV82A(const LangOptions &Opts,
116                                                 MacroBuilder &Builder) const {
117   // Also include the ARMv8.1 defines
118   getTargetDefinesARMV81A(Opts, Builder);
119 }
120 
121 void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts,
122                                          MacroBuilder &Builder) const {
123   // Target identification.
124   Builder.defineMacro("__aarch64__");
125   // For bare-metal.
126   if (getTriple().getOS() == llvm::Triple::UnknownOS &&
127       getTriple().isOSBinFormatELF())
128     Builder.defineMacro("__ELF__");
129 
130   // Target properties.
131   if (!getTriple().isOSWindows()) {
132     Builder.defineMacro("_LP64");
133     Builder.defineMacro("__LP64__");
134   }
135 
136   // ACLE predefines. Many can only have one possible value on v8 AArch64.
137   Builder.defineMacro("__ARM_ACLE", "200");
138   Builder.defineMacro("__ARM_ARCH", "8");
139   Builder.defineMacro("__ARM_ARCH_PROFILE", "'A'");
140 
141   Builder.defineMacro("__ARM_64BIT_STATE", "1");
142   Builder.defineMacro("__ARM_PCS_AAPCS64", "1");
143   Builder.defineMacro("__ARM_ARCH_ISA_A64", "1");
144 
145   Builder.defineMacro("__ARM_FEATURE_CLZ", "1");
146   Builder.defineMacro("__ARM_FEATURE_FMA", "1");
147   Builder.defineMacro("__ARM_FEATURE_LDREX", "0xF");
148   Builder.defineMacro("__ARM_FEATURE_IDIV", "1"); // As specified in ACLE
149   Builder.defineMacro("__ARM_FEATURE_DIV");       // For backwards compatibility
150   Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN", "1");
151   Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING", "1");
152 
153   Builder.defineMacro("__ARM_ALIGN_MAX_STACK_PWR", "4");
154 
155   // 0xe implies support for half, single and double precision operations.
156   Builder.defineMacro("__ARM_FP", "0xE");
157 
158   // PCS specifies this for SysV variants, which is all we support. Other ABIs
159   // may choose __ARM_FP16_FORMAT_ALTERNATIVE.
160   Builder.defineMacro("__ARM_FP16_FORMAT_IEEE", "1");
161   Builder.defineMacro("__ARM_FP16_ARGS", "1");
162 
163   if (Opts.UnsafeFPMath)
164     Builder.defineMacro("__ARM_FP_FAST", "1");
165 
166   Builder.defineMacro("__ARM_SIZEOF_WCHAR_T",
167                       Twine(Opts.WCharSize ? Opts.WCharSize : 4));
168 
169   Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM", Opts.ShortEnums ? "1" : "4");
170 
171   if (FPU & NeonMode) {
172     Builder.defineMacro("__ARM_NEON", "1");
173     // 64-bit NEON supports half, single and double precision operations.
174     Builder.defineMacro("__ARM_NEON_FP", "0xE");
175   }
176 
177   if (FPU & SveMode)
178     Builder.defineMacro("__ARM_FEATURE_SVE", "1");
179 
180   if (CRC)
181     Builder.defineMacro("__ARM_FEATURE_CRC32", "1");
182 
183   if (Crypto)
184     Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1");
185 
186   if (Unaligned)
187     Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1");
188 
189   if ((FPU & NeonMode) && HasFullFP16)
190     Builder.defineMacro("__ARM_FEATURE_FP16_VECTOR_ARITHMETIC", "1");
191   if (HasFullFP16)
192    Builder.defineMacro("__ARM_FEATURE_FP16_SCALAR_ARITHMETIC", "1");
193 
194   if (HasDotProd)
195     Builder.defineMacro("__ARM_FEATURE_DOTPROD", "1");
196 
197   if (HasMTE)
198     Builder.defineMacro("__ARM_FEATURE_MEMORY_TAGGING", "1");
199 
200   if ((FPU & NeonMode) && HasFP16FML)
201     Builder.defineMacro("__ARM_FEATURE_FP16FML", "1");
202 
203   switch (ArchKind) {
204   default:
205     break;
206   case llvm::AArch64::ArchKind::ARMV8_1A:
207     getTargetDefinesARMV81A(Opts, Builder);
208     break;
209   case llvm::AArch64::ArchKind::ARMV8_2A:
210     getTargetDefinesARMV82A(Opts, Builder);
211     break;
212   }
213 
214   // All of the __sync_(bool|val)_compare_and_swap_(1|2|4|8) builtins work.
215   Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
216   Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
217   Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
218   Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
219 }
220 
221 ArrayRef<Builtin::Info> AArch64TargetInfo::getTargetBuiltins() const {
222   return llvm::makeArrayRef(BuiltinInfo, clang::AArch64::LastTSBuiltin -
223                                              Builtin::FirstTSBuiltin);
224 }
225 
226 bool AArch64TargetInfo::hasFeature(StringRef Feature) const {
227   return Feature == "aarch64" || Feature == "arm64" || Feature == "arm" ||
228          (Feature == "neon" && (FPU & NeonMode)) ||
229          (Feature == "sve" && (FPU & SveMode));
230 }
231 
232 bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
233                                              DiagnosticsEngine &Diags) {
234   FPU = FPUMode;
235   CRC = 0;
236   Crypto = 0;
237   Unaligned = 1;
238   HasFullFP16 = 0;
239   HasDotProd = 0;
240   HasFP16FML = 0;
241   HasMTE = 0;
242   ArchKind = llvm::AArch64::ArchKind::ARMV8A;
243 
244   for (const auto &Feature : Features) {
245     if (Feature == "+neon")
246       FPU |= NeonMode;
247     if (Feature == "+sve")
248       FPU |= SveMode;
249     if (Feature == "+crc")
250       CRC = 1;
251     if (Feature == "+crypto")
252       Crypto = 1;
253     if (Feature == "+strict-align")
254       Unaligned = 0;
255     if (Feature == "+v8.1a")
256       ArchKind = llvm::AArch64::ArchKind::ARMV8_1A;
257     if (Feature == "+v8.2a")
258       ArchKind = llvm::AArch64::ArchKind::ARMV8_2A;
259     if (Feature == "+fullfp16")
260       HasFullFP16 = 1;
261     if (Feature == "+dotprod")
262       HasDotProd = 1;
263     if (Feature == "+fp16fml")
264       HasFP16FML = 1;
265     if (Feature == "+mte")
266       HasMTE = 1;
267   }
268 
269   setDataLayout();
270 
271   return true;
272 }
273 
274 TargetInfo::CallingConvCheckResult
275 AArch64TargetInfo::checkCallingConvention(CallingConv CC) const {
276   switch (CC) {
277   case CC_C:
278   case CC_Swift:
279   case CC_PreserveMost:
280   case CC_PreserveAll:
281   case CC_OpenCLKernel:
282   case CC_AArch64VectorCall:
283   case CC_Win64:
284     return CCCR_OK;
285   default:
286     return CCCR_Warning;
287   }
288 }
289 
290 bool AArch64TargetInfo::isCLZForZeroUndef() const { return false; }
291 
292 TargetInfo::BuiltinVaListKind AArch64TargetInfo::getBuiltinVaListKind() const {
293   return TargetInfo::AArch64ABIBuiltinVaList;
294 }
295 
296 const char *const AArch64TargetInfo::GCCRegNames[] = {
297     // 32-bit Integer registers
298     "w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7", "w8", "w9", "w10", "w11",
299     "w12", "w13", "w14", "w15", "w16", "w17", "w18", "w19", "w20", "w21", "w22",
300     "w23", "w24", "w25", "w26", "w27", "w28", "w29", "w30", "wsp",
301 
302     // 64-bit Integer registers
303     "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11",
304     "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22",
305     "x23", "x24", "x25", "x26", "x27", "x28", "fp", "lr", "sp",
306 
307     // 32-bit floating point regsisters
308     "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11",
309     "s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22",
310     "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
311 
312     // 64-bit floating point regsisters
313     "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11",
314     "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19", "d20", "d21", "d22",
315     "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",
316 
317     // Vector registers
318     "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11",
319     "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", "v20", "v21", "v22",
320     "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"
321 };
322 
323 ArrayRef<const char *> AArch64TargetInfo::getGCCRegNames() const {
324   return llvm::makeArrayRef(GCCRegNames);
325 }
326 
327 const TargetInfo::GCCRegAlias AArch64TargetInfo::GCCRegAliases[] = {
328     {{"w31"}, "wsp"},
329     {{"x31"}, "sp"},
330     // GCC rN registers are aliases of xN registers.
331     {{"r0"}, "x0"},
332     {{"r1"}, "x1"},
333     {{"r2"}, "x2"},
334     {{"r3"}, "x3"},
335     {{"r4"}, "x4"},
336     {{"r5"}, "x5"},
337     {{"r6"}, "x6"},
338     {{"r7"}, "x7"},
339     {{"r8"}, "x8"},
340     {{"r9"}, "x9"},
341     {{"r10"}, "x10"},
342     {{"r11"}, "x11"},
343     {{"r12"}, "x12"},
344     {{"r13"}, "x13"},
345     {{"r14"}, "x14"},
346     {{"r15"}, "x15"},
347     {{"r16"}, "x16"},
348     {{"r17"}, "x17"},
349     {{"r18"}, "x18"},
350     {{"r19"}, "x19"},
351     {{"r20"}, "x20"},
352     {{"r21"}, "x21"},
353     {{"r22"}, "x22"},
354     {{"r23"}, "x23"},
355     {{"r24"}, "x24"},
356     {{"r25"}, "x25"},
357     {{"r26"}, "x26"},
358     {{"r27"}, "x27"},
359     {{"r28"}, "x28"},
360     {{"r29", "x29"}, "fp"},
361     {{"r30", "x30"}, "lr"},
362     // The S/D/Q and W/X registers overlap, but aren't really aliases; we
363     // don't want to substitute one of these for a different-sized one.
364 };
365 
366 ArrayRef<TargetInfo::GCCRegAlias> AArch64TargetInfo::getGCCRegAliases() const {
367   return llvm::makeArrayRef(GCCRegAliases);
368 }
369 
370 bool AArch64TargetInfo::validateAsmConstraint(
371     const char *&Name, TargetInfo::ConstraintInfo &Info) const {
372   switch (*Name) {
373   default:
374     return false;
375   case 'w': // Floating point and SIMD registers (V0-V31)
376     Info.setAllowsRegister();
377     return true;
378   case 'I': // Constant that can be used with an ADD instruction
379   case 'J': // Constant that can be used with a SUB instruction
380   case 'K': // Constant that can be used with a 32-bit logical instruction
381   case 'L': // Constant that can be used with a 64-bit logical instruction
382   case 'M': // Constant that can be used as a 32-bit MOV immediate
383   case 'N': // Constant that can be used as a 64-bit MOV immediate
384   case 'Y': // Floating point constant zero
385   case 'Z': // Integer constant zero
386     return true;
387   case 'Q': // A memory reference with base register and no offset
388     Info.setAllowsMemory();
389     return true;
390   case 'S': // A symbolic address
391     Info.setAllowsRegister();
392     return true;
393   case 'U':
394     // Ump: A memory address suitable for ldp/stp in SI, DI, SF and DF modes.
395     // Utf: A memory address suitable for ldp/stp in TF mode.
396     // Usa: An absolute symbolic address.
397     // Ush: The high part (bits 32:12) of a pc-relative symbolic address.
398     llvm_unreachable("FIXME: Unimplemented support for U* constraints.");
399   case 'z': // Zero register, wzr or xzr
400     Info.setAllowsRegister();
401     return true;
402   case 'x': // Floating point and SIMD registers (V0-V15)
403     Info.setAllowsRegister();
404     return true;
405   }
406   return false;
407 }
408 
409 bool AArch64TargetInfo::validateConstraintModifier(
410     StringRef Constraint, char Modifier, unsigned Size,
411     std::string &SuggestedModifier) const {
412   // Strip off constraint modifiers.
413   while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&')
414     Constraint = Constraint.substr(1);
415 
416   switch (Constraint[0]) {
417   default:
418     return true;
419   case 'z':
420   case 'r': {
421     switch (Modifier) {
422     case 'x':
423     case 'w':
424       // For now assume that the person knows what they're
425       // doing with the modifier.
426       return true;
427     default:
428       // By default an 'r' constraint will be in the 'x'
429       // registers.
430       if (Size == 64)
431         return true;
432 
433       SuggestedModifier = "w";
434       return false;
435     }
436   }
437   }
438 }
439 
440 const char *AArch64TargetInfo::getClobbers() const { return ""; }
441 
442 int AArch64TargetInfo::getEHDataRegisterNumber(unsigned RegNo) const {
443   if (RegNo == 0)
444     return 0;
445   if (RegNo == 1)
446     return 1;
447   return -1;
448 }
449 
450 AArch64leTargetInfo::AArch64leTargetInfo(const llvm::Triple &Triple,
451                                          const TargetOptions &Opts)
452     : AArch64TargetInfo(Triple, Opts) {}
453 
454 void AArch64leTargetInfo::setDataLayout() {
455   if (getTriple().isOSBinFormatMachO())
456     resetDataLayout("e-m:o-i64:64-i128:128-n32:64-S128");
457   else
458     resetDataLayout("e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
459 }
460 
461 void AArch64leTargetInfo::getTargetDefines(const LangOptions &Opts,
462                                            MacroBuilder &Builder) const {
463   Builder.defineMacro("__AARCH64EL__");
464   AArch64TargetInfo::getTargetDefines(Opts, Builder);
465 }
466 
467 AArch64beTargetInfo::AArch64beTargetInfo(const llvm::Triple &Triple,
468                                          const TargetOptions &Opts)
469     : AArch64TargetInfo(Triple, Opts) {}
470 
471 void AArch64beTargetInfo::getTargetDefines(const LangOptions &Opts,
472                                            MacroBuilder &Builder) const {
473   Builder.defineMacro("__AARCH64EB__");
474   Builder.defineMacro("__AARCH_BIG_ENDIAN");
475   Builder.defineMacro("__ARM_BIG_ENDIAN");
476   AArch64TargetInfo::getTargetDefines(Opts, Builder);
477 }
478 
479 void AArch64beTargetInfo::setDataLayout() {
480   assert(!getTriple().isOSBinFormatMachO());
481   resetDataLayout("E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
482 }
483 
484 WindowsARM64TargetInfo::WindowsARM64TargetInfo(const llvm::Triple &Triple,
485                                                const TargetOptions &Opts)
486     : WindowsTargetInfo<AArch64leTargetInfo>(Triple, Opts), Triple(Triple) {
487 
488   // This is an LLP64 platform.
489   // int:4, long:4, long long:8, long double:8.
490   IntWidth = IntAlign = 32;
491   LongWidth = LongAlign = 32;
492   DoubleAlign = LongLongAlign = 64;
493   LongDoubleWidth = LongDoubleAlign = 64;
494   LongDoubleFormat = &llvm::APFloat::IEEEdouble();
495   IntMaxType = SignedLongLong;
496   Int64Type = SignedLongLong;
497   SizeType = UnsignedLongLong;
498   PtrDiffType = SignedLongLong;
499   IntPtrType = SignedLongLong;
500 }
501 
502 void WindowsARM64TargetInfo::setDataLayout() {
503   resetDataLayout("e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128");
504 }
505 
506 TargetInfo::BuiltinVaListKind
507 WindowsARM64TargetInfo::getBuiltinVaListKind() const {
508   return TargetInfo::CharPtrBuiltinVaList;
509 }
510 
511 TargetInfo::CallingConvCheckResult
512 WindowsARM64TargetInfo::checkCallingConvention(CallingConv CC) const {
513   switch (CC) {
514   case CC_X86StdCall:
515   case CC_X86ThisCall:
516   case CC_X86FastCall:
517   case CC_X86VectorCall:
518     return CCCR_Ignore;
519   case CC_C:
520   case CC_OpenCLKernel:
521   case CC_PreserveMost:
522   case CC_PreserveAll:
523   case CC_Swift:
524   case CC_Win64:
525     return CCCR_OK;
526   default:
527     return CCCR_Warning;
528   }
529 }
530 
531 MicrosoftARM64TargetInfo::MicrosoftARM64TargetInfo(const llvm::Triple &Triple,
532                                                    const TargetOptions &Opts)
533     : WindowsARM64TargetInfo(Triple, Opts) {
534   TheCXXABI.set(TargetCXXABI::Microsoft);
535 }
536 
537 void MicrosoftARM64TargetInfo::getVisualStudioDefines(
538     const LangOptions &Opts, MacroBuilder &Builder) const {
539   WindowsTargetInfo<AArch64leTargetInfo>::getVisualStudioDefines(Opts, Builder);
540   Builder.defineMacro("_M_ARM64", "1");
541 }
542 
543 void MicrosoftARM64TargetInfo::getTargetDefines(const LangOptions &Opts,
544                                                 MacroBuilder &Builder) const {
545   WindowsTargetInfo::getTargetDefines(Opts, Builder);
546   getVisualStudioDefines(Opts, Builder);
547 }
548 
549 TargetInfo::CallingConvKind
550 MicrosoftARM64TargetInfo::getCallingConvKind(bool ClangABICompat4) const {
551   return CCK_MicrosoftWin64;
552 }
553 
554 unsigned MicrosoftARM64TargetInfo::getMinGlobalAlign(uint64_t TypeSize) const {
555   unsigned Align = WindowsARM64TargetInfo::getMinGlobalAlign(TypeSize);
556 
557   // MSVC does size based alignment for arm64 based on alignment section in
558   // below document, replicate that to keep alignment consistent with object
559   // files compiled by MSVC.
560   // https://docs.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions
561   if (TypeSize >= 512) {              // TypeSize >= 64 bytes
562     Align = std::max(Align, 128u);    // align type at least 16 bytes
563   } else if (TypeSize >= 64) {        // TypeSize >= 8 bytes
564     Align = std::max(Align, 64u);     // align type at least 8 butes
565   } else if (TypeSize >= 16) {        // TypeSize >= 2 bytes
566     Align = std::max(Align, 32u);     // align type at least 4 bytes
567   }
568   return Align;
569 }
570 
571 MinGWARM64TargetInfo::MinGWARM64TargetInfo(const llvm::Triple &Triple,
572                                            const TargetOptions &Opts)
573     : WindowsARM64TargetInfo(Triple, Opts) {
574   TheCXXABI.set(TargetCXXABI::GenericAArch64);
575 }
576 
577 DarwinAArch64TargetInfo::DarwinAArch64TargetInfo(const llvm::Triple &Triple,
578                                                  const TargetOptions &Opts)
579     : DarwinTargetInfo<AArch64leTargetInfo>(Triple, Opts) {
580   Int64Type = SignedLongLong;
581   UseSignedCharForObjCBool = false;
582 
583   LongDoubleWidth = LongDoubleAlign = SuitableAlign = 64;
584   LongDoubleFormat = &llvm::APFloat::IEEEdouble();
585 
586   TheCXXABI.set(TargetCXXABI::iOS64);
587 }
588 
589 void DarwinAArch64TargetInfo::getOSDefines(const LangOptions &Opts,
590                                            const llvm::Triple &Triple,
591                                            MacroBuilder &Builder) const {
592   Builder.defineMacro("__AARCH64_SIMD__");
593   Builder.defineMacro("__ARM64_ARCH_8__");
594   Builder.defineMacro("__ARM_NEON__");
595   Builder.defineMacro("__LITTLE_ENDIAN__");
596   Builder.defineMacro("__REGISTER_PREFIX__", "");
597   Builder.defineMacro("__arm64", "1");
598   Builder.defineMacro("__arm64__", "1");
599 
600   getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion);
601 }
602 
603 TargetInfo::BuiltinVaListKind
604 DarwinAArch64TargetInfo::getBuiltinVaListKind() const {
605   return TargetInfo::CharPtrBuiltinVaList;
606 }
607 
608 // 64-bit RenderScript is aarch64
609 RenderScript64TargetInfo::RenderScript64TargetInfo(const llvm::Triple &Triple,
610                                                    const TargetOptions &Opts)
611     : AArch64leTargetInfo(llvm::Triple("aarch64", Triple.getVendorName(),
612                                        Triple.getOSName(),
613                                        Triple.getEnvironmentName()),
614                           Opts) {
615   IsRenderScriptTarget = true;
616 }
617 
618 void RenderScript64TargetInfo::getTargetDefines(const LangOptions &Opts,
619                                                 MacroBuilder &Builder) const {
620   Builder.defineMacro("__RENDERSCRIPT__");
621   AArch64leTargetInfo::getTargetDefines(Opts, Builder);
622 }
623