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