1 //===--- AArch64.cpp - Implement AArch64 target feature support -----------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements AArch64 TargetInfo objects.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "AArch64.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 
20 using namespace clang;
21 using namespace clang::targets;
22 
23 const Builtin::Info AArch64TargetInfo::BuiltinInfo[] = {
24 #define BUILTIN(ID, TYPE, ATTRS)                                               \
25    {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
26 #include "clang/Basic/BuiltinsNEON.def"
27 
28 #define BUILTIN(ID, TYPE, ATTRS)                                               \
29    {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
30 #define LANGBUILTIN(ID, TYPE, ATTRS, LANG)                                     \
31   {#ID, TYPE, ATTRS, nullptr, LANG, nullptr},
32 #define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE)         \
33   {#ID, TYPE, ATTRS, HEADER, LANGS, FEATURE},
34 #include "clang/Basic/BuiltinsAArch64.def"
35 };
36 
37 AArch64TargetInfo::AArch64TargetInfo(const llvm::Triple &Triple,
38                                      const TargetOptions &Opts)
39     : TargetInfo(Triple), ABI("aapcs") {
40   if (getTriple().getOS() == llvm::Triple::OpenBSD) {
41     Int64Type = SignedLongLong;
42     IntMaxType = SignedLongLong;
43   } else {
44     if (!getTriple().isOSDarwin() && getTriple().getOS() != llvm::Triple::NetBSD)
45       WCharType = UnsignedInt;
46 
47     Int64Type = SignedLong;
48     IntMaxType = SignedLong;
49   }
50 
51   // All AArch64 implementations support ARMv8 FP, which makes half a legal type.
52   HasLegalHalfType = 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   switch (ArchKind) {
198   default:
199     break;
200   case llvm::AArch64::ArchKind::ARMV8_1A:
201     getTargetDefinesARMV81A(Opts, Builder);
202     break;
203   case llvm::AArch64::ArchKind::ARMV8_2A:
204     getTargetDefinesARMV82A(Opts, Builder);
205     break;
206   }
207 
208   // All of the __sync_(bool|val)_compare_and_swap_(1|2|4|8) builtins work.
209   Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
210   Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
211   Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
212   Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
213 }
214 
215 ArrayRef<Builtin::Info> AArch64TargetInfo::getTargetBuiltins() const {
216   return llvm::makeArrayRef(BuiltinInfo, clang::AArch64::LastTSBuiltin -
217                                              Builtin::FirstTSBuiltin);
218 }
219 
220 bool AArch64TargetInfo::hasFeature(StringRef Feature) const {
221   return Feature == "aarch64" || Feature == "arm64" || Feature == "arm" ||
222          (Feature == "neon" && (FPU & NeonMode)) ||
223          (Feature == "sve" && (FPU & SveMode));
224 }
225 
226 bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
227                                              DiagnosticsEngine &Diags) {
228   FPU = FPUMode;
229   CRC = 0;
230   Crypto = 0;
231   Unaligned = 1;
232   HasFullFP16 = 0;
233   HasDotProd = 0;
234   ArchKind = llvm::AArch64::ArchKind::ARMV8A;
235 
236   for (const auto &Feature : Features) {
237     if (Feature == "+neon")
238       FPU |= NeonMode;
239     if (Feature == "+sve")
240       FPU |= SveMode;
241     if (Feature == "+crc")
242       CRC = 1;
243     if (Feature == "+crypto")
244       Crypto = 1;
245     if (Feature == "+strict-align")
246       Unaligned = 0;
247     if (Feature == "+v8.1a")
248       ArchKind = llvm::AArch64::ArchKind::ARMV8_1A;
249     if (Feature == "+v8.2a")
250       ArchKind = llvm::AArch64::ArchKind::ARMV8_2A;
251     if (Feature == "+fullfp16")
252       HasFullFP16 = 1;
253     if (Feature == "+dotprod")
254       HasDotProd = 1;
255   }
256 
257   setDataLayout();
258 
259   return true;
260 }
261 
262 TargetInfo::CallingConvCheckResult
263 AArch64TargetInfo::checkCallingConvention(CallingConv CC) const {
264   switch (CC) {
265   case CC_C:
266   case CC_Swift:
267   case CC_PreserveMost:
268   case CC_PreserveAll:
269   case CC_OpenCLKernel:
270   case CC_Win64:
271     return CCCR_OK;
272   default:
273     return CCCR_Warning;
274   }
275 }
276 
277 bool AArch64TargetInfo::isCLZForZeroUndef() const { return false; }
278 
279 TargetInfo::BuiltinVaListKind AArch64TargetInfo::getBuiltinVaListKind() const {
280   return TargetInfo::AArch64ABIBuiltinVaList;
281 }
282 
283 const char *const AArch64TargetInfo::GCCRegNames[] = {
284     // 32-bit Integer registers
285     "w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7", "w8", "w9", "w10", "w11",
286     "w12", "w13", "w14", "w15", "w16", "w17", "w18", "w19", "w20", "w21", "w22",
287     "w23", "w24", "w25", "w26", "w27", "w28", "w29", "w30", "wsp",
288 
289     // 64-bit Integer registers
290     "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11",
291     "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22",
292     "x23", "x24", "x25", "x26", "x27", "x28", "fp", "lr", "sp",
293 
294     // 32-bit floating point regsisters
295     "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11",
296     "s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22",
297     "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
298 
299     // 64-bit floating point regsisters
300     "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11",
301     "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19", "d20", "d21", "d22",
302     "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",
303 
304     // Vector registers
305     "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11",
306     "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", "v20", "v21", "v22",
307     "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"
308 };
309 
310 ArrayRef<const char *> AArch64TargetInfo::getGCCRegNames() const {
311   return llvm::makeArrayRef(GCCRegNames);
312 }
313 
314 const TargetInfo::GCCRegAlias AArch64TargetInfo::GCCRegAliases[] = {
315     {{"w31"}, "wsp"},
316     {{"x31"}, "sp"},
317     // GCC rN registers are aliases of xN registers.
318     {{"r0"}, "x0"},
319     {{"r1"}, "x1"},
320     {{"r2"}, "x2"},
321     {{"r3"}, "x3"},
322     {{"r4"}, "x4"},
323     {{"r5"}, "x5"},
324     {{"r6"}, "x6"},
325     {{"r7"}, "x7"},
326     {{"r8"}, "x8"},
327     {{"r9"}, "x9"},
328     {{"r10"}, "x10"},
329     {{"r11"}, "x11"},
330     {{"r12"}, "x12"},
331     {{"r13"}, "x13"},
332     {{"r14"}, "x14"},
333     {{"r15"}, "x15"},
334     {{"r16"}, "x16"},
335     {{"r17"}, "x17"},
336     {{"r18"}, "x18"},
337     {{"r19"}, "x19"},
338     {{"r20"}, "x20"},
339     {{"r21"}, "x21"},
340     {{"r22"}, "x22"},
341     {{"r23"}, "x23"},
342     {{"r24"}, "x24"},
343     {{"r25"}, "x25"},
344     {{"r26"}, "x26"},
345     {{"r27"}, "x27"},
346     {{"r28"}, "x28"},
347     {{"r29", "x29"}, "fp"},
348     {{"r30", "x30"}, "lr"},
349     // The S/D/Q and W/X registers overlap, but aren't really aliases; we
350     // don't want to substitute one of these for a different-sized one.
351 };
352 
353 ArrayRef<TargetInfo::GCCRegAlias> AArch64TargetInfo::getGCCRegAliases() const {
354   return llvm::makeArrayRef(GCCRegAliases);
355 }
356 
357 bool AArch64TargetInfo::validateAsmConstraint(
358     const char *&Name, TargetInfo::ConstraintInfo &Info) const {
359   switch (*Name) {
360   default:
361     return false;
362   case 'w': // Floating point and SIMD registers (V0-V31)
363     Info.setAllowsRegister();
364     return true;
365   case 'I': // Constant that can be used with an ADD instruction
366   case 'J': // Constant that can be used with a SUB instruction
367   case 'K': // Constant that can be used with a 32-bit logical instruction
368   case 'L': // Constant that can be used with a 64-bit logical instruction
369   case 'M': // Constant that can be used as a 32-bit MOV immediate
370   case 'N': // Constant that can be used as a 64-bit MOV immediate
371   case 'Y': // Floating point constant zero
372   case 'Z': // Integer constant zero
373     return true;
374   case 'Q': // A memory reference with base register and no offset
375     Info.setAllowsMemory();
376     return true;
377   case 'S': // A symbolic address
378     Info.setAllowsRegister();
379     return true;
380   case 'U':
381     // Ump: A memory address suitable for ldp/stp in SI, DI, SF and DF modes.
382     // Utf: A memory address suitable for ldp/stp in TF mode.
383     // Usa: An absolute symbolic address.
384     // Ush: The high part (bits 32:12) of a pc-relative symbolic address.
385     llvm_unreachable("FIXME: Unimplemented support for U* constraints.");
386   case 'z': // Zero register, wzr or xzr
387     Info.setAllowsRegister();
388     return true;
389   case 'x': // Floating point and SIMD registers (V0-V15)
390     Info.setAllowsRegister();
391     return true;
392   }
393   return false;
394 }
395 
396 bool AArch64TargetInfo::validateConstraintModifier(
397     StringRef Constraint, char Modifier, unsigned Size,
398     std::string &SuggestedModifier) const {
399   // Strip off constraint modifiers.
400   while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&')
401     Constraint = Constraint.substr(1);
402 
403   switch (Constraint[0]) {
404   default:
405     return true;
406   case 'z':
407   case 'r': {
408     switch (Modifier) {
409     case 'x':
410     case 'w':
411       // For now assume that the person knows what they're
412       // doing with the modifier.
413       return true;
414     default:
415       // By default an 'r' constraint will be in the 'x'
416       // registers.
417       if (Size == 64)
418         return true;
419 
420       SuggestedModifier = "w";
421       return false;
422     }
423   }
424   }
425 }
426 
427 const char *AArch64TargetInfo::getClobbers() const { return ""; }
428 
429 int AArch64TargetInfo::getEHDataRegisterNumber(unsigned RegNo) const {
430   if (RegNo == 0)
431     return 0;
432   if (RegNo == 1)
433     return 1;
434   return -1;
435 }
436 
437 AArch64leTargetInfo::AArch64leTargetInfo(const llvm::Triple &Triple,
438                                          const TargetOptions &Opts)
439     : AArch64TargetInfo(Triple, Opts) {}
440 
441 void AArch64leTargetInfo::setDataLayout() {
442   if (getTriple().isOSBinFormatMachO())
443     resetDataLayout("e-m:o-i64:64-i128:128-n32:64-S128");
444   else
445     resetDataLayout("e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
446 }
447 
448 void AArch64leTargetInfo::getTargetDefines(const LangOptions &Opts,
449                                            MacroBuilder &Builder) const {
450   Builder.defineMacro("__AARCH64EL__");
451   AArch64TargetInfo::getTargetDefines(Opts, Builder);
452 }
453 
454 AArch64beTargetInfo::AArch64beTargetInfo(const llvm::Triple &Triple,
455                                          const TargetOptions &Opts)
456     : AArch64TargetInfo(Triple, Opts) {}
457 
458 void AArch64beTargetInfo::getTargetDefines(const LangOptions &Opts,
459                                            MacroBuilder &Builder) const {
460   Builder.defineMacro("__AARCH64EB__");
461   Builder.defineMacro("__AARCH_BIG_ENDIAN");
462   Builder.defineMacro("__ARM_BIG_ENDIAN");
463   AArch64TargetInfo::getTargetDefines(Opts, Builder);
464 }
465 
466 void AArch64beTargetInfo::setDataLayout() {
467   assert(!getTriple().isOSBinFormatMachO());
468   resetDataLayout("E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
469 }
470 
471 WindowsARM64TargetInfo::WindowsARM64TargetInfo(const llvm::Triple &Triple,
472                                                const TargetOptions &Opts)
473     : WindowsTargetInfo<AArch64leTargetInfo>(Triple, Opts), Triple(Triple) {
474 
475   // This is an LLP64 platform.
476   // int:4, long:4, long long:8, long double:8.
477   IntWidth = IntAlign = 32;
478   LongWidth = LongAlign = 32;
479   DoubleAlign = LongLongAlign = 64;
480   LongDoubleWidth = LongDoubleAlign = 64;
481   LongDoubleFormat = &llvm::APFloat::IEEEdouble();
482   IntMaxType = SignedLongLong;
483   Int64Type = SignedLongLong;
484   SizeType = UnsignedLongLong;
485   PtrDiffType = SignedLongLong;
486   IntPtrType = SignedLongLong;
487 }
488 
489 void WindowsARM64TargetInfo::setDataLayout() {
490   resetDataLayout("e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128");
491 }
492 
493 TargetInfo::BuiltinVaListKind
494 WindowsARM64TargetInfo::getBuiltinVaListKind() const {
495   return TargetInfo::CharPtrBuiltinVaList;
496 }
497 
498 TargetInfo::CallingConvCheckResult
499 WindowsARM64TargetInfo::checkCallingConvention(CallingConv CC) const {
500   switch (CC) {
501   case CC_X86StdCall:
502   case CC_X86ThisCall:
503   case CC_X86FastCall:
504   case CC_X86VectorCall:
505     return CCCR_Ignore;
506   case CC_C:
507   case CC_OpenCLKernel:
508   case CC_PreserveMost:
509   case CC_PreserveAll:
510   case CC_Win64:
511     return CCCR_OK;
512   default:
513     return CCCR_Warning;
514   }
515 }
516 
517 MicrosoftARM64TargetInfo::MicrosoftARM64TargetInfo(const llvm::Triple &Triple,
518                                                    const TargetOptions &Opts)
519     : WindowsARM64TargetInfo(Triple, Opts) {
520   TheCXXABI.set(TargetCXXABI::Microsoft);
521 }
522 
523 void MicrosoftARM64TargetInfo::getVisualStudioDefines(
524     const LangOptions &Opts, MacroBuilder &Builder) const {
525   WindowsTargetInfo<AArch64leTargetInfo>::getVisualStudioDefines(Opts, Builder);
526   Builder.defineMacro("_M_ARM64", "1");
527 }
528 
529 void MicrosoftARM64TargetInfo::getTargetDefines(const LangOptions &Opts,
530                                                 MacroBuilder &Builder) const {
531   WindowsTargetInfo::getTargetDefines(Opts, Builder);
532   getVisualStudioDefines(Opts, Builder);
533 }
534 
535 TargetInfo::CallingConvKind
536 MicrosoftARM64TargetInfo::getCallingConvKind(bool ClangABICompat4) const {
537   return CCK_MicrosoftWin64;
538 }
539 
540 MinGWARM64TargetInfo::MinGWARM64TargetInfo(const llvm::Triple &Triple,
541                                            const TargetOptions &Opts)
542     : WindowsARM64TargetInfo(Triple, Opts) {
543   TheCXXABI.set(TargetCXXABI::GenericAArch64);
544 }
545 
546 DarwinAArch64TargetInfo::DarwinAArch64TargetInfo(const llvm::Triple &Triple,
547                                                  const TargetOptions &Opts)
548     : DarwinTargetInfo<AArch64leTargetInfo>(Triple, Opts) {
549   Int64Type = SignedLongLong;
550   UseSignedCharForObjCBool = false;
551 
552   LongDoubleWidth = LongDoubleAlign = SuitableAlign = 64;
553   LongDoubleFormat = &llvm::APFloat::IEEEdouble();
554 
555   TheCXXABI.set(TargetCXXABI::iOS64);
556 }
557 
558 void DarwinAArch64TargetInfo::getOSDefines(const LangOptions &Opts,
559                                            const llvm::Triple &Triple,
560                                            MacroBuilder &Builder) const {
561   Builder.defineMacro("__AARCH64_SIMD__");
562   Builder.defineMacro("__ARM64_ARCH_8__");
563   Builder.defineMacro("__ARM_NEON__");
564   Builder.defineMacro("__LITTLE_ENDIAN__");
565   Builder.defineMacro("__REGISTER_PREFIX__", "");
566   Builder.defineMacro("__arm64", "1");
567   Builder.defineMacro("__arm64__", "1");
568 
569   getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion);
570 }
571 
572 TargetInfo::BuiltinVaListKind
573 DarwinAArch64TargetInfo::getBuiltinVaListKind() const {
574   return TargetInfo::CharPtrBuiltinVaList;
575 }
576 
577 // 64-bit RenderScript is aarch64
578 RenderScript64TargetInfo::RenderScript64TargetInfo(const llvm::Triple &Triple,
579                                                    const TargetOptions &Opts)
580     : AArch64leTargetInfo(llvm::Triple("aarch64", Triple.getVendorName(),
581                                        Triple.getOSName(),
582                                        Triple.getEnvironmentName()),
583                           Opts) {
584   IsRenderScriptTarget = true;
585 }
586 
587 void RenderScript64TargetInfo::getTargetDefines(const LangOptions &Opts,
588                                                 MacroBuilder &Builder) const {
589   Builder.defineMacro("__RENDERSCRIPT__");
590   AArch64leTargetInfo::getTargetDefines(Opts, Builder);
591 }
592