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