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