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