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::getTargetDefinesARMV83A(const LangOptions &Opts,
122                                                 MacroBuilder &Builder) const {
123   Builder.defineMacro("__ARM_FEATURE_JCVT", "1");
124   // Also include the Armv8.2 defines
125   getTargetDefinesARMV82A(Opts, Builder);
126 }
127 
128 void AArch64TargetInfo::getTargetDefinesARMV84A(const LangOptions &Opts,
129                                                 MacroBuilder &Builder) const {
130   // Also include the Armv8.3 defines
131   // FIXME: Armv8.4 makes some extensions mandatory. Handle them here.
132   getTargetDefinesARMV83A(Opts, Builder);
133 }
134 
135 void AArch64TargetInfo::getTargetDefinesARMV85A(const LangOptions &Opts,
136                                                 MacroBuilder &Builder) const {
137   // Also include the Armv8.4 defines
138   // FIXME: Armv8.5 makes some extensions mandatory. Handle them here.
139   getTargetDefinesARMV84A(Opts, Builder);
140 }
141 
142 
143 void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts,
144                                          MacroBuilder &Builder) const {
145   // Target identification.
146   Builder.defineMacro("__aarch64__");
147   // For bare-metal.
148   if (getTriple().getOS() == llvm::Triple::UnknownOS &&
149       getTriple().isOSBinFormatELF())
150     Builder.defineMacro("__ELF__");
151 
152   // Target properties.
153   if (!getTriple().isOSWindows()) {
154     Builder.defineMacro("_LP64");
155     Builder.defineMacro("__LP64__");
156   }
157 
158   // ACLE predefines. Many can only have one possible value on v8 AArch64.
159   Builder.defineMacro("__ARM_ACLE", "200");
160   Builder.defineMacro("__ARM_ARCH", "8");
161   Builder.defineMacro("__ARM_ARCH_PROFILE", "'A'");
162 
163   Builder.defineMacro("__ARM_64BIT_STATE", "1");
164   Builder.defineMacro("__ARM_PCS_AAPCS64", "1");
165   Builder.defineMacro("__ARM_ARCH_ISA_A64", "1");
166 
167   Builder.defineMacro("__ARM_FEATURE_CLZ", "1");
168   Builder.defineMacro("__ARM_FEATURE_FMA", "1");
169   Builder.defineMacro("__ARM_FEATURE_LDREX", "0xF");
170   Builder.defineMacro("__ARM_FEATURE_IDIV", "1"); // As specified in ACLE
171   Builder.defineMacro("__ARM_FEATURE_DIV");       // For backwards compatibility
172   Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN", "1");
173   Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING", "1");
174 
175   Builder.defineMacro("__ARM_ALIGN_MAX_STACK_PWR", "4");
176 
177   // 0xe implies support for half, single and double precision operations.
178   Builder.defineMacro("__ARM_FP", "0xE");
179 
180   // PCS specifies this for SysV variants, which is all we support. Other ABIs
181   // may choose __ARM_FP16_FORMAT_ALTERNATIVE.
182   Builder.defineMacro("__ARM_FP16_FORMAT_IEEE", "1");
183   Builder.defineMacro("__ARM_FP16_ARGS", "1");
184 
185   if (Opts.UnsafeFPMath)
186     Builder.defineMacro("__ARM_FP_FAST", "1");
187 
188   Builder.defineMacro("__ARM_SIZEOF_WCHAR_T",
189                       Twine(Opts.WCharSize ? Opts.WCharSize : 4));
190 
191   Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM", Opts.ShortEnums ? "1" : "4");
192 
193   if (FPU & NeonMode) {
194     Builder.defineMacro("__ARM_NEON", "1");
195     // 64-bit NEON supports half, single and double precision operations.
196     Builder.defineMacro("__ARM_NEON_FP", "0xE");
197   }
198 
199   if (FPU & SveMode)
200     Builder.defineMacro("__ARM_FEATURE_SVE", "1");
201 
202   if (HasCRC)
203     Builder.defineMacro("__ARM_FEATURE_CRC32", "1");
204 
205   if (HasCrypto)
206     Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1");
207 
208   if (HasUnaligned)
209     Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1");
210 
211   if ((FPU & NeonMode) && HasFullFP16)
212     Builder.defineMacro("__ARM_FEATURE_FP16_VECTOR_ARITHMETIC", "1");
213   if (HasFullFP16)
214    Builder.defineMacro("__ARM_FEATURE_FP16_SCALAR_ARITHMETIC", "1");
215 
216   if (HasDotProd)
217     Builder.defineMacro("__ARM_FEATURE_DOTPROD", "1");
218 
219   if (HasMTE)
220     Builder.defineMacro("__ARM_FEATURE_MEMORY_TAGGING", "1");
221 
222   if ((FPU & NeonMode) && HasFP16FML)
223     Builder.defineMacro("__ARM_FEATURE_FP16FML", "1");
224 
225   switch (ArchKind) {
226   default:
227     break;
228   case llvm::AArch64::ArchKind::ARMV8_1A:
229     getTargetDefinesARMV81A(Opts, Builder);
230     break;
231   case llvm::AArch64::ArchKind::ARMV8_2A:
232     getTargetDefinesARMV82A(Opts, Builder);
233     break;
234   case llvm::AArch64::ArchKind::ARMV8_3A:
235     getTargetDefinesARMV83A(Opts, Builder);
236     break;
237   case llvm::AArch64::ArchKind::ARMV8_4A:
238     getTargetDefinesARMV84A(Opts, Builder);
239     break;
240   case llvm::AArch64::ArchKind::ARMV8_5A:
241     getTargetDefinesARMV85A(Opts, Builder);
242     break;
243   }
244 
245   // All of the __sync_(bool|val)_compare_and_swap_(1|2|4|8) builtins work.
246   Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
247   Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
248   Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
249   Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
250 }
251 
252 ArrayRef<Builtin::Info> AArch64TargetInfo::getTargetBuiltins() const {
253   return llvm::makeArrayRef(BuiltinInfo, clang::AArch64::LastTSBuiltin -
254                                              Builtin::FirstTSBuiltin);
255 }
256 
257 bool AArch64TargetInfo::hasFeature(StringRef Feature) const {
258   return Feature == "aarch64" || Feature == "arm64" || Feature == "arm" ||
259          (Feature == "neon" && (FPU & NeonMode)) ||
260          (Feature == "sve" && (FPU & SveMode));
261 }
262 
263 bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
264                                              DiagnosticsEngine &Diags) {
265   FPU = FPUMode;
266   HasCRC = false;
267   HasCrypto = false;
268   HasUnaligned = true;
269   HasFullFP16 = false;
270   HasDotProd = false;
271   HasFP16FML = false;
272   HasMTE = false;
273   ArchKind = llvm::AArch64::ArchKind::ARMV8A;
274 
275   for (const auto &Feature : Features) {
276     if (Feature == "+neon")
277       FPU |= NeonMode;
278     if (Feature == "+sve")
279       FPU |= SveMode;
280     if (Feature == "+crc")
281       HasCRC = true;
282     if (Feature == "+crypto")
283       HasCrypto = true;
284     if (Feature == "+strict-align")
285       HasUnaligned = false;
286     if (Feature == "+v8.1a")
287       ArchKind = llvm::AArch64::ArchKind::ARMV8_1A;
288     if (Feature == "+v8.2a")
289       ArchKind = llvm::AArch64::ArchKind::ARMV8_2A;
290     if (Feature == "+v8.3a")
291       ArchKind = llvm::AArch64::ArchKind::ARMV8_3A;
292     if (Feature == "+v8.4a")
293       ArchKind = llvm::AArch64::ArchKind::ARMV8_4A;
294     if (Feature == "+v8.5a")
295       ArchKind = llvm::AArch64::ArchKind::ARMV8_5A;
296     if (Feature == "+fullfp16")
297       HasFullFP16 = true;
298     if (Feature == "+dotprod")
299       HasDotProd = true;
300     if (Feature == "+fp16fml")
301       HasFP16FML = true;
302     if (Feature == "+mte")
303       HasMTE = true;
304   }
305 
306   setDataLayout();
307 
308   return true;
309 }
310 
311 TargetInfo::CallingConvCheckResult
312 AArch64TargetInfo::checkCallingConvention(CallingConv CC) const {
313   switch (CC) {
314   case CC_C:
315   case CC_Swift:
316   case CC_PreserveMost:
317   case CC_PreserveAll:
318   case CC_OpenCLKernel:
319   case CC_AArch64VectorCall:
320   case CC_Win64:
321     return CCCR_OK;
322   default:
323     return CCCR_Warning;
324   }
325 }
326 
327 bool AArch64TargetInfo::isCLZForZeroUndef() const { return false; }
328 
329 TargetInfo::BuiltinVaListKind AArch64TargetInfo::getBuiltinVaListKind() const {
330   return TargetInfo::AArch64ABIBuiltinVaList;
331 }
332 
333 const char *const AArch64TargetInfo::GCCRegNames[] = {
334     // 32-bit Integer registers
335     "w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7", "w8", "w9", "w10", "w11",
336     "w12", "w13", "w14", "w15", "w16", "w17", "w18", "w19", "w20", "w21", "w22",
337     "w23", "w24", "w25", "w26", "w27", "w28", "w29", "w30", "wsp",
338 
339     // 64-bit Integer registers
340     "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11",
341     "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22",
342     "x23", "x24", "x25", "x26", "x27", "x28", "fp", "lr", "sp",
343 
344     // 32-bit floating point regsisters
345     "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11",
346     "s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22",
347     "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
348 
349     // 64-bit floating point regsisters
350     "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11",
351     "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19", "d20", "d21", "d22",
352     "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",
353 
354     // Neon vector registers
355     "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11",
356     "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", "v20", "v21", "v22",
357     "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31",
358 
359     // SVE vector registers
360     "z0",  "z1",  "z2",  "z3",  "z4",  "z5",  "z6",  "z7",  "z8",  "z9",  "z10",
361     "z11", "z12", "z13", "z14", "z15", "z16", "z17", "z18", "z19", "z20", "z21",
362     "z22", "z23", "z24", "z25", "z26", "z27", "z28", "z29", "z30", "z31",
363 
364     // SVE predicate registers
365     "p0",  "p1",  "p2",  "p3",  "p4",  "p5",  "p6",  "p7",  "p8",  "p9",  "p10",
366     "p11", "p12", "p13", "p14", "p15"
367 };
368 
369 ArrayRef<const char *> AArch64TargetInfo::getGCCRegNames() const {
370   return llvm::makeArrayRef(GCCRegNames);
371 }
372 
373 const TargetInfo::GCCRegAlias AArch64TargetInfo::GCCRegAliases[] = {
374     {{"w31"}, "wsp"},
375     {{"x31"}, "sp"},
376     // GCC rN registers are aliases of xN registers.
377     {{"r0"}, "x0"},
378     {{"r1"}, "x1"},
379     {{"r2"}, "x2"},
380     {{"r3"}, "x3"},
381     {{"r4"}, "x4"},
382     {{"r5"}, "x5"},
383     {{"r6"}, "x6"},
384     {{"r7"}, "x7"},
385     {{"r8"}, "x8"},
386     {{"r9"}, "x9"},
387     {{"r10"}, "x10"},
388     {{"r11"}, "x11"},
389     {{"r12"}, "x12"},
390     {{"r13"}, "x13"},
391     {{"r14"}, "x14"},
392     {{"r15"}, "x15"},
393     {{"r16"}, "x16"},
394     {{"r17"}, "x17"},
395     {{"r18"}, "x18"},
396     {{"r19"}, "x19"},
397     {{"r20"}, "x20"},
398     {{"r21"}, "x21"},
399     {{"r22"}, "x22"},
400     {{"r23"}, "x23"},
401     {{"r24"}, "x24"},
402     {{"r25"}, "x25"},
403     {{"r26"}, "x26"},
404     {{"r27"}, "x27"},
405     {{"r28"}, "x28"},
406     {{"r29", "x29"}, "fp"},
407     {{"r30", "x30"}, "lr"},
408     // The S/D/Q and W/X registers overlap, but aren't really aliases; we
409     // don't want to substitute one of these for a different-sized one.
410 };
411 
412 ArrayRef<TargetInfo::GCCRegAlias> AArch64TargetInfo::getGCCRegAliases() const {
413   return llvm::makeArrayRef(GCCRegAliases);
414 }
415 
416 bool AArch64TargetInfo::validateAsmConstraint(
417     const char *&Name, TargetInfo::ConstraintInfo &Info) const {
418   switch (*Name) {
419   default:
420     return false;
421   case 'w': // Floating point and SIMD registers (V0-V31)
422     Info.setAllowsRegister();
423     return true;
424   case 'I': // Constant that can be used with an ADD instruction
425   case 'J': // Constant that can be used with a SUB instruction
426   case 'K': // Constant that can be used with a 32-bit logical instruction
427   case 'L': // Constant that can be used with a 64-bit logical instruction
428   case 'M': // Constant that can be used as a 32-bit MOV immediate
429   case 'N': // Constant that can be used as a 64-bit MOV immediate
430   case 'Y': // Floating point constant zero
431   case 'Z': // Integer constant zero
432     return true;
433   case 'Q': // A memory reference with base register and no offset
434     Info.setAllowsMemory();
435     return true;
436   case 'S': // A symbolic address
437     Info.setAllowsRegister();
438     return true;
439   case 'U':
440     // Ump: A memory address suitable for ldp/stp in SI, DI, SF and DF modes.
441     // Utf: A memory address suitable for ldp/stp in TF mode.
442     // Usa: An absolute symbolic address.
443     // Ush: The high part (bits 32:12) of a pc-relative symbolic address.
444     llvm_unreachable("FIXME: Unimplemented support for U* constraints.");
445   case 'z': // Zero register, wzr or xzr
446     Info.setAllowsRegister();
447     return true;
448   case 'x': // Floating point and SIMD registers (V0-V15)
449     Info.setAllowsRegister();
450     return true;
451   }
452   return false;
453 }
454 
455 bool AArch64TargetInfo::validateConstraintModifier(
456     StringRef Constraint, char Modifier, unsigned Size,
457     std::string &SuggestedModifier) const {
458   // Strip off constraint modifiers.
459   while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&')
460     Constraint = Constraint.substr(1);
461 
462   switch (Constraint[0]) {
463   default:
464     return true;
465   case 'z':
466   case 'r': {
467     switch (Modifier) {
468     case 'x':
469     case 'w':
470       // For now assume that the person knows what they're
471       // doing with the modifier.
472       return true;
473     default:
474       // By default an 'r' constraint will be in the 'x'
475       // registers.
476       if (Size == 64)
477         return true;
478 
479       SuggestedModifier = "w";
480       return false;
481     }
482   }
483   }
484 }
485 
486 const char *AArch64TargetInfo::getClobbers() const { return ""; }
487 
488 int AArch64TargetInfo::getEHDataRegisterNumber(unsigned RegNo) const {
489   if (RegNo == 0)
490     return 0;
491   if (RegNo == 1)
492     return 1;
493   return -1;
494 }
495 
496 AArch64leTargetInfo::AArch64leTargetInfo(const llvm::Triple &Triple,
497                                          const TargetOptions &Opts)
498     : AArch64TargetInfo(Triple, Opts) {}
499 
500 void AArch64leTargetInfo::setDataLayout() {
501   if (getTriple().isOSBinFormatMachO())
502     resetDataLayout("e-m:o-i64:64-i128:128-n32:64-S128");
503   else
504     resetDataLayout("e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
505 }
506 
507 void AArch64leTargetInfo::getTargetDefines(const LangOptions &Opts,
508                                            MacroBuilder &Builder) const {
509   Builder.defineMacro("__AARCH64EL__");
510   AArch64TargetInfo::getTargetDefines(Opts, Builder);
511 }
512 
513 AArch64beTargetInfo::AArch64beTargetInfo(const llvm::Triple &Triple,
514                                          const TargetOptions &Opts)
515     : AArch64TargetInfo(Triple, Opts) {}
516 
517 void AArch64beTargetInfo::getTargetDefines(const LangOptions &Opts,
518                                            MacroBuilder &Builder) const {
519   Builder.defineMacro("__AARCH64EB__");
520   Builder.defineMacro("__AARCH_BIG_ENDIAN");
521   Builder.defineMacro("__ARM_BIG_ENDIAN");
522   AArch64TargetInfo::getTargetDefines(Opts, Builder);
523 }
524 
525 void AArch64beTargetInfo::setDataLayout() {
526   assert(!getTriple().isOSBinFormatMachO());
527   resetDataLayout("E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
528 }
529 
530 WindowsARM64TargetInfo::WindowsARM64TargetInfo(const llvm::Triple &Triple,
531                                                const TargetOptions &Opts)
532     : WindowsTargetInfo<AArch64leTargetInfo>(Triple, Opts), Triple(Triple) {
533 
534   // This is an LLP64 platform.
535   // int:4, long:4, long long:8, long double:8.
536   IntWidth = IntAlign = 32;
537   LongWidth = LongAlign = 32;
538   DoubleAlign = LongLongAlign = 64;
539   LongDoubleWidth = LongDoubleAlign = 64;
540   LongDoubleFormat = &llvm::APFloat::IEEEdouble();
541   IntMaxType = SignedLongLong;
542   Int64Type = SignedLongLong;
543   SizeType = UnsignedLongLong;
544   PtrDiffType = SignedLongLong;
545   IntPtrType = SignedLongLong;
546 }
547 
548 void WindowsARM64TargetInfo::setDataLayout() {
549   resetDataLayout("e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128");
550 }
551 
552 TargetInfo::BuiltinVaListKind
553 WindowsARM64TargetInfo::getBuiltinVaListKind() const {
554   return TargetInfo::CharPtrBuiltinVaList;
555 }
556 
557 TargetInfo::CallingConvCheckResult
558 WindowsARM64TargetInfo::checkCallingConvention(CallingConv CC) const {
559   switch (CC) {
560   case CC_X86StdCall:
561   case CC_X86ThisCall:
562   case CC_X86FastCall:
563   case CC_X86VectorCall:
564     return CCCR_Ignore;
565   case CC_C:
566   case CC_OpenCLKernel:
567   case CC_PreserveMost:
568   case CC_PreserveAll:
569   case CC_Swift:
570   case CC_Win64:
571     return CCCR_OK;
572   default:
573     return CCCR_Warning;
574   }
575 }
576 
577 MicrosoftARM64TargetInfo::MicrosoftARM64TargetInfo(const llvm::Triple &Triple,
578                                                    const TargetOptions &Opts)
579     : WindowsARM64TargetInfo(Triple, Opts) {
580   TheCXXABI.set(TargetCXXABI::Microsoft);
581 }
582 
583 void MicrosoftARM64TargetInfo::getTargetDefines(const LangOptions &Opts,
584                                                 MacroBuilder &Builder) const {
585   WindowsARM64TargetInfo::getTargetDefines(Opts, Builder);
586   Builder.defineMacro("_M_ARM64", "1");
587 }
588 
589 TargetInfo::CallingConvKind
590 MicrosoftARM64TargetInfo::getCallingConvKind(bool ClangABICompat4) const {
591   return CCK_MicrosoftWin64;
592 }
593 
594 unsigned MicrosoftARM64TargetInfo::getMinGlobalAlign(uint64_t TypeSize) const {
595   unsigned Align = WindowsARM64TargetInfo::getMinGlobalAlign(TypeSize);
596 
597   // MSVC does size based alignment for arm64 based on alignment section in
598   // below document, replicate that to keep alignment consistent with object
599   // files compiled by MSVC.
600   // https://docs.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions
601   if (TypeSize >= 512) {              // TypeSize >= 64 bytes
602     Align = std::max(Align, 128u);    // align type at least 16 bytes
603   } else if (TypeSize >= 64) {        // TypeSize >= 8 bytes
604     Align = std::max(Align, 64u);     // align type at least 8 butes
605   } else if (TypeSize >= 16) {        // TypeSize >= 2 bytes
606     Align = std::max(Align, 32u);     // align type at least 4 bytes
607   }
608   return Align;
609 }
610 
611 MinGWARM64TargetInfo::MinGWARM64TargetInfo(const llvm::Triple &Triple,
612                                            const TargetOptions &Opts)
613     : WindowsARM64TargetInfo(Triple, Opts) {
614   TheCXXABI.set(TargetCXXABI::GenericAArch64);
615 }
616 
617 DarwinAArch64TargetInfo::DarwinAArch64TargetInfo(const llvm::Triple &Triple,
618                                                  const TargetOptions &Opts)
619     : DarwinTargetInfo<AArch64leTargetInfo>(Triple, Opts) {
620   Int64Type = SignedLongLong;
621   UseSignedCharForObjCBool = false;
622 
623   LongDoubleWidth = LongDoubleAlign = SuitableAlign = 64;
624   LongDoubleFormat = &llvm::APFloat::IEEEdouble();
625 
626   TheCXXABI.set(TargetCXXABI::iOS64);
627 }
628 
629 void DarwinAArch64TargetInfo::getOSDefines(const LangOptions &Opts,
630                                            const llvm::Triple &Triple,
631                                            MacroBuilder &Builder) const {
632   Builder.defineMacro("__AARCH64_SIMD__");
633   Builder.defineMacro("__ARM64_ARCH_8__");
634   Builder.defineMacro("__ARM_NEON__");
635   Builder.defineMacro("__LITTLE_ENDIAN__");
636   Builder.defineMacro("__REGISTER_PREFIX__", "");
637   Builder.defineMacro("__arm64", "1");
638   Builder.defineMacro("__arm64__", "1");
639 
640   getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion);
641 }
642 
643 TargetInfo::BuiltinVaListKind
644 DarwinAArch64TargetInfo::getBuiltinVaListKind() const {
645   return TargetInfo::CharPtrBuiltinVaList;
646 }
647 
648 // 64-bit RenderScript is aarch64
649 RenderScript64TargetInfo::RenderScript64TargetInfo(const llvm::Triple &Triple,
650                                                    const TargetOptions &Opts)
651     : AArch64leTargetInfo(llvm::Triple("aarch64", Triple.getVendorName(),
652                                        Triple.getOSName(),
653                                        Triple.getEnvironmentName()),
654                           Opts) {
655   IsRenderScriptTarget = true;
656 }
657 
658 void RenderScript64TargetInfo::getTargetDefines(const LangOptions &Opts,
659                                                 MacroBuilder &Builder) const {
660   Builder.defineMacro("__RENDERSCRIPT__");
661   AArch64leTargetInfo::getTargetDefines(Opts, Builder);
662 }
663