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 #include "llvm/ADT/StringSwitch.h"
19 #include "llvm/Support/AArch64TargetParser.h"
20 
21 using namespace clang;
22 using namespace clang::targets;
23 
24 const Builtin::Info AArch64TargetInfo::BuiltinInfo[] = {
25 #define BUILTIN(ID, TYPE, ATTRS)                                               \
26    {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
27 #include "clang/Basic/BuiltinsNEON.def"
28 
29 #define BUILTIN(ID, TYPE, ATTRS)                                               \
30    {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
31 #define LANGBUILTIN(ID, TYPE, ATTRS, LANG)                                     \
32   {#ID, TYPE, ATTRS, nullptr, LANG, nullptr},
33 #define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE)         \
34   {#ID, TYPE, ATTRS, HEADER, LANGS, FEATURE},
35 #include "clang/Basic/BuiltinsAArch64.def"
36 };
37 
38 AArch64TargetInfo::AArch64TargetInfo(const llvm::Triple &Triple,
39                                      const TargetOptions &Opts)
40     : TargetInfo(Triple), ABI("aapcs") {
41   if (getTriple().isOSOpenBSD()) {
42     Int64Type = SignedLongLong;
43     IntMaxType = SignedLongLong;
44   } else {
45     if (!getTriple().isOSDarwin() && !getTriple().isOSNetBSD())
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   HasFloat16 = true;
55 
56   if (Triple.isArch64Bit())
57     LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
58   else
59     LongWidth = LongAlign = PointerWidth = PointerAlign = 32;
60 
61   MaxVectorAlign = 128;
62   MaxAtomicInlineWidth = 128;
63   MaxAtomicPromoteWidth = 128;
64 
65   LongDoubleWidth = LongDoubleAlign = SuitableAlign = 128;
66   LongDoubleFormat = &llvm::APFloat::IEEEquad();
67 
68   // Make __builtin_ms_va_list available.
69   HasBuiltinMSVaList = true;
70 
71   // Make the SVE types available.  Note that this deliberately doesn't
72   // depend on SveMode, since in principle it should be possible to turn
73   // SVE on and off within a translation unit.  It should also be possible
74   // to compile the global declaration:
75   //
76   // __SVInt8_t *ptr;
77   //
78   // even without SVE.
79   HasAArch64SVETypes = true;
80 
81   // {} in inline assembly are neon specifiers, not assembly variant
82   // specifiers.
83   NoAsmVariants = true;
84 
85   // AAPCS gives rules for bitfields. 7.1.7 says: "The container type
86   // contributes to the alignment of the containing aggregate in the same way
87   // a plain (non bit-field) member of that type would, without exception for
88   // zero-sized or anonymous bit-fields."
89   assert(UseBitFieldTypeAlignment && "bitfields affect type alignment");
90   UseZeroLengthBitfieldAlignment = true;
91 
92   // AArch64 targets default to using the ARM C++ ABI.
93   TheCXXABI.set(TargetCXXABI::GenericAArch64);
94 
95   if (Triple.getOS() == llvm::Triple::Linux)
96     this->MCountName = "\01_mcount";
97   else if (Triple.getOS() == llvm::Triple::UnknownOS)
98     this->MCountName =
99         Opts.EABIVersion == llvm::EABI::GNU ? "\01_mcount" : "mcount";
100 }
101 
102 StringRef AArch64TargetInfo::getABI() const { return ABI; }
103 
104 bool AArch64TargetInfo::setABI(const std::string &Name) {
105   if (Name != "aapcs" && Name != "darwinpcs")
106     return false;
107 
108   ABI = Name;
109   return true;
110 }
111 
112 bool AArch64TargetInfo::validateBranchProtection(StringRef Spec,
113                                                  BranchProtectionInfo &BPI,
114                                                  StringRef &Err) const {
115   llvm::AArch64::ParsedBranchProtection PBP;
116   if (!llvm::AArch64::parseBranchProtection(Spec, PBP, Err))
117     return false;
118 
119   BPI.SignReturnAddr =
120       llvm::StringSwitch<CodeGenOptions::SignReturnAddressScope>(PBP.Scope)
121           .Case("non-leaf", CodeGenOptions::SignReturnAddressScope::NonLeaf)
122           .Case("all", CodeGenOptions::SignReturnAddressScope::All)
123           .Default(CodeGenOptions::SignReturnAddressScope::None);
124 
125   if (PBP.Key == "a_key")
126     BPI.SignKey = CodeGenOptions::SignReturnAddressKeyValue::AKey;
127   else
128     BPI.SignKey = CodeGenOptions::SignReturnAddressKeyValue::BKey;
129 
130   BPI.BranchTargetEnforcement = PBP.BranchTargetEnforcement;
131   return true;
132 }
133 
134 bool AArch64TargetInfo::isValidCPUName(StringRef Name) const {
135   return Name == "generic" ||
136          llvm::AArch64::parseCPUArch(Name) != llvm::AArch64::ArchKind::INVALID;
137 }
138 
139 bool AArch64TargetInfo::setCPU(const std::string &Name) {
140   return isValidCPUName(Name);
141 }
142 
143 void AArch64TargetInfo::fillValidCPUList(
144     SmallVectorImpl<StringRef> &Values) const {
145   llvm::AArch64::fillValidCPUArchList(Values);
146 }
147 
148 void AArch64TargetInfo::getTargetDefinesARMV81A(const LangOptions &Opts,
149                                                 MacroBuilder &Builder) const {
150   Builder.defineMacro("__ARM_FEATURE_QRDMX", "1");
151 }
152 
153 void AArch64TargetInfo::getTargetDefinesARMV82A(const LangOptions &Opts,
154                                                 MacroBuilder &Builder) const {
155   // Also include the ARMv8.1 defines
156   getTargetDefinesARMV81A(Opts, Builder);
157 }
158 
159 void AArch64TargetInfo::getTargetDefinesARMV83A(const LangOptions &Opts,
160                                                 MacroBuilder &Builder) const {
161   Builder.defineMacro("__ARM_FEATURE_COMPLEX", "1");
162   Builder.defineMacro("__ARM_FEATURE_JCVT", "1");
163   // Also include the Armv8.2 defines
164   getTargetDefinesARMV82A(Opts, Builder);
165 }
166 
167 void AArch64TargetInfo::getTargetDefinesARMV84A(const LangOptions &Opts,
168                                                 MacroBuilder &Builder) const {
169   // Also include the Armv8.3 defines
170   // FIXME: Armv8.4 makes some extensions mandatory. Handle them here.
171   getTargetDefinesARMV83A(Opts, Builder);
172 }
173 
174 void AArch64TargetInfo::getTargetDefinesARMV85A(const LangOptions &Opts,
175                                                 MacroBuilder &Builder) const {
176   // Also include the Armv8.4 defines
177   // FIXME: Armv8.5 makes some extensions mandatory. Handle them here.
178   getTargetDefinesARMV84A(Opts, Builder);
179 }
180 
181 
182 void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts,
183                                          MacroBuilder &Builder) const {
184   // Target identification.
185   Builder.defineMacro("__aarch64__");
186   // For bare-metal.
187   if (getTriple().getOS() == llvm::Triple::UnknownOS &&
188       getTriple().isOSBinFormatELF())
189     Builder.defineMacro("__ELF__");
190 
191   // Target properties.
192   if (!getTriple().isOSWindows() && getTriple().isArch64Bit()) {
193     Builder.defineMacro("_LP64");
194     Builder.defineMacro("__LP64__");
195   }
196 
197   std::string CodeModel = getTargetOpts().CodeModel;
198   if (CodeModel == "default")
199     CodeModel = "small";
200   for (char &c : CodeModel)
201     c = toupper(c);
202   Builder.defineMacro("__AARCH64_CMODEL_" + CodeModel + "__");
203 
204   // ACLE predefines. Many can only have one possible value on v8 AArch64.
205   Builder.defineMacro("__ARM_ACLE", "200");
206   Builder.defineMacro("__ARM_ARCH", "8");
207   Builder.defineMacro("__ARM_ARCH_PROFILE", "'A'");
208 
209   Builder.defineMacro("__ARM_64BIT_STATE", "1");
210   Builder.defineMacro("__ARM_PCS_AAPCS64", "1");
211   Builder.defineMacro("__ARM_ARCH_ISA_A64", "1");
212 
213   Builder.defineMacro("__ARM_FEATURE_CLZ", "1");
214   Builder.defineMacro("__ARM_FEATURE_FMA", "1");
215   Builder.defineMacro("__ARM_FEATURE_LDREX", "0xF");
216   Builder.defineMacro("__ARM_FEATURE_IDIV", "1"); // As specified in ACLE
217   Builder.defineMacro("__ARM_FEATURE_DIV");       // For backwards compatibility
218   Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN", "1");
219   Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING", "1");
220 
221   Builder.defineMacro("__ARM_ALIGN_MAX_STACK_PWR", "4");
222 
223   // 0xe implies support for half, single and double precision operations.
224   Builder.defineMacro("__ARM_FP", "0xE");
225 
226   // PCS specifies this for SysV variants, which is all we support. Other ABIs
227   // may choose __ARM_FP16_FORMAT_ALTERNATIVE.
228   Builder.defineMacro("__ARM_FP16_FORMAT_IEEE", "1");
229   Builder.defineMacro("__ARM_FP16_ARGS", "1");
230 
231   if (Opts.UnsafeFPMath)
232     Builder.defineMacro("__ARM_FP_FAST", "1");
233 
234   Builder.defineMacro("__ARM_SIZEOF_WCHAR_T",
235                       Twine(Opts.WCharSize ? Opts.WCharSize : 4));
236 
237   Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM", Opts.ShortEnums ? "1" : "4");
238 
239   if (FPU & NeonMode) {
240     Builder.defineMacro("__ARM_NEON", "1");
241     // 64-bit NEON supports half, single and double precision operations.
242     Builder.defineMacro("__ARM_NEON_FP", "0xE");
243   }
244 
245   if (HasCRC)
246     Builder.defineMacro("__ARM_FEATURE_CRC32", "1");
247 
248   if (HasCrypto)
249     Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1");
250 
251   if (HasUnaligned)
252     Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1");
253 
254   if ((FPU & NeonMode) && HasFullFP16)
255     Builder.defineMacro("__ARM_FEATURE_FP16_VECTOR_ARITHMETIC", "1");
256   if (HasFullFP16)
257    Builder.defineMacro("__ARM_FEATURE_FP16_SCALAR_ARITHMETIC", "1");
258 
259   if (HasDotProd)
260     Builder.defineMacro("__ARM_FEATURE_DOTPROD", "1");
261 
262   if (HasMTE)
263     Builder.defineMacro("__ARM_FEATURE_MEMORY_TAGGING", "1");
264 
265   if (HasTME)
266     Builder.defineMacro("__ARM_FEATURE_TME", "1");
267 
268   if ((FPU & NeonMode) && HasFP16FML)
269     Builder.defineMacro("__ARM_FEATURE_FP16FML", "1");
270 
271   switch (ArchKind) {
272   default:
273     break;
274   case llvm::AArch64::ArchKind::ARMV8_1A:
275     getTargetDefinesARMV81A(Opts, Builder);
276     break;
277   case llvm::AArch64::ArchKind::ARMV8_2A:
278     getTargetDefinesARMV82A(Opts, Builder);
279     break;
280   case llvm::AArch64::ArchKind::ARMV8_3A:
281     getTargetDefinesARMV83A(Opts, Builder);
282     break;
283   case llvm::AArch64::ArchKind::ARMV8_4A:
284     getTargetDefinesARMV84A(Opts, Builder);
285     break;
286   case llvm::AArch64::ArchKind::ARMV8_5A:
287     getTargetDefinesARMV85A(Opts, Builder);
288     break;
289   }
290 
291   // All of the __sync_(bool|val)_compare_and_swap_(1|2|4|8) builtins work.
292   Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
293   Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
294   Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
295   Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
296 }
297 
298 ArrayRef<Builtin::Info> AArch64TargetInfo::getTargetBuiltins() const {
299   return llvm::makeArrayRef(BuiltinInfo, clang::AArch64::LastTSBuiltin -
300                                              Builtin::FirstTSBuiltin);
301 }
302 
303 bool AArch64TargetInfo::hasFeature(StringRef Feature) const {
304   return Feature == "aarch64" || Feature == "arm64" || Feature == "arm" ||
305          (Feature == "neon" && (FPU & NeonMode)) ||
306          (Feature == "sve" && (FPU & SveMode));
307 }
308 
309 bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
310                                              DiagnosticsEngine &Diags) {
311   FPU = FPUMode;
312   HasCRC = false;
313   HasCrypto = false;
314   HasUnaligned = true;
315   HasFullFP16 = false;
316   HasDotProd = false;
317   HasFP16FML = false;
318   HasMTE = false;
319   HasTME = false;
320   ArchKind = llvm::AArch64::ArchKind::ARMV8A;
321 
322   for (const auto &Feature : Features) {
323     if (Feature == "+neon")
324       FPU |= NeonMode;
325     if (Feature == "+sve")
326       FPU |= SveMode;
327     if (Feature == "+crc")
328       HasCRC = true;
329     if (Feature == "+crypto")
330       HasCrypto = true;
331     if (Feature == "+strict-align")
332       HasUnaligned = false;
333     if (Feature == "+v8.1a")
334       ArchKind = llvm::AArch64::ArchKind::ARMV8_1A;
335     if (Feature == "+v8.2a")
336       ArchKind = llvm::AArch64::ArchKind::ARMV8_2A;
337     if (Feature == "+v8.3a")
338       ArchKind = llvm::AArch64::ArchKind::ARMV8_3A;
339     if (Feature == "+v8.4a")
340       ArchKind = llvm::AArch64::ArchKind::ARMV8_4A;
341     if (Feature == "+v8.5a")
342       ArchKind = llvm::AArch64::ArchKind::ARMV8_5A;
343     if (Feature == "+fullfp16")
344       HasFullFP16 = true;
345     if (Feature == "+dotprod")
346       HasDotProd = true;
347     if (Feature == "+fp16fml")
348       HasFP16FML = true;
349     if (Feature == "+mte")
350       HasMTE = true;
351     if (Feature == "+tme")
352       HasTME = true;
353   }
354 
355   setDataLayout();
356 
357   return true;
358 }
359 
360 TargetInfo::CallingConvCheckResult
361 AArch64TargetInfo::checkCallingConvention(CallingConv CC) const {
362   switch (CC) {
363   case CC_C:
364   case CC_Swift:
365   case CC_PreserveMost:
366   case CC_PreserveAll:
367   case CC_OpenCLKernel:
368   case CC_AArch64VectorCall:
369   case CC_Win64:
370     return CCCR_OK;
371   default:
372     return CCCR_Warning;
373   }
374 }
375 
376 bool AArch64TargetInfo::isCLZForZeroUndef() const { return false; }
377 
378 TargetInfo::BuiltinVaListKind AArch64TargetInfo::getBuiltinVaListKind() const {
379   return TargetInfo::AArch64ABIBuiltinVaList;
380 }
381 
382 const char *const AArch64TargetInfo::GCCRegNames[] = {
383     // 32-bit Integer registers
384     "w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7", "w8", "w9", "w10", "w11",
385     "w12", "w13", "w14", "w15", "w16", "w17", "w18", "w19", "w20", "w21", "w22",
386     "w23", "w24", "w25", "w26", "w27", "w28", "w29", "w30", "wsp",
387 
388     // 64-bit Integer registers
389     "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11",
390     "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22",
391     "x23", "x24", "x25", "x26", "x27", "x28", "fp", "lr", "sp",
392 
393     // 32-bit floating point regsisters
394     "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11",
395     "s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22",
396     "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
397 
398     // 64-bit floating point regsisters
399     "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11",
400     "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19", "d20", "d21", "d22",
401     "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",
402 
403     // Neon vector registers
404     "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11",
405     "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", "v20", "v21", "v22",
406     "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31",
407 
408     // SVE vector registers
409     "z0",  "z1",  "z2",  "z3",  "z4",  "z5",  "z6",  "z7",  "z8",  "z9",  "z10",
410     "z11", "z12", "z13", "z14", "z15", "z16", "z17", "z18", "z19", "z20", "z21",
411     "z22", "z23", "z24", "z25", "z26", "z27", "z28", "z29", "z30", "z31",
412 
413     // SVE predicate registers
414     "p0",  "p1",  "p2",  "p3",  "p4",  "p5",  "p6",  "p7",  "p8",  "p9",  "p10",
415     "p11", "p12", "p13", "p14", "p15"
416 };
417 
418 ArrayRef<const char *> AArch64TargetInfo::getGCCRegNames() const {
419   return llvm::makeArrayRef(GCCRegNames);
420 }
421 
422 const TargetInfo::GCCRegAlias AArch64TargetInfo::GCCRegAliases[] = {
423     {{"w31"}, "wsp"},
424     {{"x31"}, "sp"},
425     // GCC rN registers are aliases of xN registers.
426     {{"r0"}, "x0"},
427     {{"r1"}, "x1"},
428     {{"r2"}, "x2"},
429     {{"r3"}, "x3"},
430     {{"r4"}, "x4"},
431     {{"r5"}, "x5"},
432     {{"r6"}, "x6"},
433     {{"r7"}, "x7"},
434     {{"r8"}, "x8"},
435     {{"r9"}, "x9"},
436     {{"r10"}, "x10"},
437     {{"r11"}, "x11"},
438     {{"r12"}, "x12"},
439     {{"r13"}, "x13"},
440     {{"r14"}, "x14"},
441     {{"r15"}, "x15"},
442     {{"r16"}, "x16"},
443     {{"r17"}, "x17"},
444     {{"r18"}, "x18"},
445     {{"r19"}, "x19"},
446     {{"r20"}, "x20"},
447     {{"r21"}, "x21"},
448     {{"r22"}, "x22"},
449     {{"r23"}, "x23"},
450     {{"r24"}, "x24"},
451     {{"r25"}, "x25"},
452     {{"r26"}, "x26"},
453     {{"r27"}, "x27"},
454     {{"r28"}, "x28"},
455     {{"r29", "x29"}, "fp"},
456     {{"r30", "x30"}, "lr"},
457     // The S/D/Q and W/X registers overlap, but aren't really aliases; we
458     // don't want to substitute one of these for a different-sized one.
459 };
460 
461 ArrayRef<TargetInfo::GCCRegAlias> AArch64TargetInfo::getGCCRegAliases() const {
462   return llvm::makeArrayRef(GCCRegAliases);
463 }
464 
465 bool AArch64TargetInfo::validateAsmConstraint(
466     const char *&Name, TargetInfo::ConstraintInfo &Info) const {
467   switch (*Name) {
468   default:
469     return false;
470   case 'w': // Floating point and SIMD registers (V0-V31)
471     Info.setAllowsRegister();
472     return true;
473   case 'I': // Constant that can be used with an ADD instruction
474   case 'J': // Constant that can be used with a SUB instruction
475   case 'K': // Constant that can be used with a 32-bit logical instruction
476   case 'L': // Constant that can be used with a 64-bit logical instruction
477   case 'M': // Constant that can be used as a 32-bit MOV immediate
478   case 'N': // Constant that can be used as a 64-bit MOV immediate
479   case 'Y': // Floating point constant zero
480   case 'Z': // Integer constant zero
481     return true;
482   case 'Q': // A memory reference with base register and no offset
483     Info.setAllowsMemory();
484     return true;
485   case 'S': // A symbolic address
486     Info.setAllowsRegister();
487     return true;
488   case 'U':
489     if (Name[1] == 'p' && (Name[2] == 'l' || Name[2] == 'a')) {
490       // SVE predicate registers ("Upa"=P0-15, "Upl"=P0-P7)
491       Info.setAllowsRegister();
492       Name += 2;
493       return true;
494     }
495     // Ump: A memory address suitable for ldp/stp in SI, DI, SF and DF modes.
496     // Utf: A memory address suitable for ldp/stp in TF mode.
497     // Usa: An absolute symbolic address.
498     // Ush: The high part (bits 32:12) of a pc-relative symbolic address.
499 
500     // Better to return an error saying that it's an unrecognised constraint
501     // even if this is a valid constraint in gcc.
502     return false;
503   case 'z': // Zero register, wzr or xzr
504     Info.setAllowsRegister();
505     return true;
506   case 'x': // Floating point and SIMD registers (V0-V15)
507     Info.setAllowsRegister();
508     return true;
509   case 'y': // SVE registers (V0-V7)
510     Info.setAllowsRegister();
511     return true;
512   }
513   return false;
514 }
515 
516 bool AArch64TargetInfo::validateConstraintModifier(
517     StringRef Constraint, char Modifier, unsigned Size,
518     std::string &SuggestedModifier) const {
519   // Strip off constraint modifiers.
520   while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&')
521     Constraint = Constraint.substr(1);
522 
523   switch (Constraint[0]) {
524   default:
525     return true;
526   case 'z':
527   case 'r': {
528     switch (Modifier) {
529     case 'x':
530     case 'w':
531       // For now assume that the person knows what they're
532       // doing with the modifier.
533       return true;
534     default:
535       // By default an 'r' constraint will be in the 'x'
536       // registers.
537       if (Size == 64)
538         return true;
539 
540       SuggestedModifier = "w";
541       return false;
542     }
543   }
544   }
545 }
546 
547 const char *AArch64TargetInfo::getClobbers() const { return ""; }
548 
549 int AArch64TargetInfo::getEHDataRegisterNumber(unsigned RegNo) const {
550   if (RegNo == 0)
551     return 0;
552   if (RegNo == 1)
553     return 1;
554   return -1;
555 }
556 
557 bool AArch64TargetInfo::hasInt128Type() const { return true; }
558 
559 AArch64leTargetInfo::AArch64leTargetInfo(const llvm::Triple &Triple,
560                                          const TargetOptions &Opts)
561     : AArch64TargetInfo(Triple, Opts) {}
562 
563 void AArch64leTargetInfo::setDataLayout() {
564   if (getTriple().isOSBinFormatMachO()) {
565     if(getTriple().isArch32Bit())
566       resetDataLayout("e-m:o-p:32:32-i64:64-i128:128-n32:64-S128");
567     else
568       resetDataLayout("e-m:o-i64:64-i128:128-n32:64-S128");
569   } else
570     resetDataLayout("e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
571 }
572 
573 void AArch64leTargetInfo::getTargetDefines(const LangOptions &Opts,
574                                            MacroBuilder &Builder) const {
575   Builder.defineMacro("__AARCH64EL__");
576   AArch64TargetInfo::getTargetDefines(Opts, Builder);
577 }
578 
579 AArch64beTargetInfo::AArch64beTargetInfo(const llvm::Triple &Triple,
580                                          const TargetOptions &Opts)
581     : AArch64TargetInfo(Triple, Opts) {}
582 
583 void AArch64beTargetInfo::getTargetDefines(const LangOptions &Opts,
584                                            MacroBuilder &Builder) const {
585   Builder.defineMacro("__AARCH64EB__");
586   Builder.defineMacro("__AARCH_BIG_ENDIAN");
587   Builder.defineMacro("__ARM_BIG_ENDIAN");
588   AArch64TargetInfo::getTargetDefines(Opts, Builder);
589 }
590 
591 void AArch64beTargetInfo::setDataLayout() {
592   assert(!getTriple().isOSBinFormatMachO());
593   resetDataLayout("E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
594 }
595 
596 WindowsARM64TargetInfo::WindowsARM64TargetInfo(const llvm::Triple &Triple,
597                                                const TargetOptions &Opts)
598     : WindowsTargetInfo<AArch64leTargetInfo>(Triple, Opts), Triple(Triple) {
599 
600   // This is an LLP64 platform.
601   // int:4, long:4, long long:8, long double:8.
602   IntWidth = IntAlign = 32;
603   LongWidth = LongAlign = 32;
604   DoubleAlign = LongLongAlign = 64;
605   LongDoubleWidth = LongDoubleAlign = 64;
606   LongDoubleFormat = &llvm::APFloat::IEEEdouble();
607   IntMaxType = SignedLongLong;
608   Int64Type = SignedLongLong;
609   SizeType = UnsignedLongLong;
610   PtrDiffType = SignedLongLong;
611   IntPtrType = SignedLongLong;
612 }
613 
614 void WindowsARM64TargetInfo::setDataLayout() {
615   resetDataLayout("e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128");
616 }
617 
618 TargetInfo::BuiltinVaListKind
619 WindowsARM64TargetInfo::getBuiltinVaListKind() const {
620   return TargetInfo::CharPtrBuiltinVaList;
621 }
622 
623 TargetInfo::CallingConvCheckResult
624 WindowsARM64TargetInfo::checkCallingConvention(CallingConv CC) const {
625   switch (CC) {
626   case CC_X86StdCall:
627   case CC_X86ThisCall:
628   case CC_X86FastCall:
629   case CC_X86VectorCall:
630     return CCCR_Ignore;
631   case CC_C:
632   case CC_OpenCLKernel:
633   case CC_PreserveMost:
634   case CC_PreserveAll:
635   case CC_Swift:
636   case CC_Win64:
637     return CCCR_OK;
638   default:
639     return CCCR_Warning;
640   }
641 }
642 
643 MicrosoftARM64TargetInfo::MicrosoftARM64TargetInfo(const llvm::Triple &Triple,
644                                                    const TargetOptions &Opts)
645     : WindowsARM64TargetInfo(Triple, Opts) {
646   TheCXXABI.set(TargetCXXABI::Microsoft);
647 }
648 
649 void MicrosoftARM64TargetInfo::getTargetDefines(const LangOptions &Opts,
650                                                 MacroBuilder &Builder) const {
651   WindowsARM64TargetInfo::getTargetDefines(Opts, Builder);
652   Builder.defineMacro("_M_ARM64", "1");
653 }
654 
655 TargetInfo::CallingConvKind
656 MicrosoftARM64TargetInfo::getCallingConvKind(bool ClangABICompat4) const {
657   return CCK_MicrosoftWin64;
658 }
659 
660 unsigned MicrosoftARM64TargetInfo::getMinGlobalAlign(uint64_t TypeSize) const {
661   unsigned Align = WindowsARM64TargetInfo::getMinGlobalAlign(TypeSize);
662 
663   // MSVC does size based alignment for arm64 based on alignment section in
664   // below document, replicate that to keep alignment consistent with object
665   // files compiled by MSVC.
666   // https://docs.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions
667   if (TypeSize >= 512) {              // TypeSize >= 64 bytes
668     Align = std::max(Align, 128u);    // align type at least 16 bytes
669   } else if (TypeSize >= 64) {        // TypeSize >= 8 bytes
670     Align = std::max(Align, 64u);     // align type at least 8 butes
671   } else if (TypeSize >= 16) {        // TypeSize >= 2 bytes
672     Align = std::max(Align, 32u);     // align type at least 4 bytes
673   }
674   return Align;
675 }
676 
677 MinGWARM64TargetInfo::MinGWARM64TargetInfo(const llvm::Triple &Triple,
678                                            const TargetOptions &Opts)
679     : WindowsARM64TargetInfo(Triple, Opts) {
680   TheCXXABI.set(TargetCXXABI::GenericAArch64);
681 }
682 
683 DarwinAArch64TargetInfo::DarwinAArch64TargetInfo(const llvm::Triple &Triple,
684                                                  const TargetOptions &Opts)
685     : DarwinTargetInfo<AArch64leTargetInfo>(Triple, Opts) {
686   Int64Type = SignedLongLong;
687   if (getTriple().isArch32Bit())
688     IntMaxType = SignedLongLong;
689 
690   WCharType = SignedInt;
691   UseSignedCharForObjCBool = false;
692 
693   LongDoubleWidth = LongDoubleAlign = SuitableAlign = 64;
694   LongDoubleFormat = &llvm::APFloat::IEEEdouble();
695 
696   UseZeroLengthBitfieldAlignment = false;
697 
698   if (getTriple().isArch32Bit()) {
699     UseBitFieldTypeAlignment = false;
700     ZeroLengthBitfieldBoundary = 32;
701     UseZeroLengthBitfieldAlignment = true;
702     TheCXXABI.set(TargetCXXABI::WatchOS);
703   } else
704     TheCXXABI.set(TargetCXXABI::iOS64);
705 }
706 
707 void DarwinAArch64TargetInfo::getOSDefines(const LangOptions &Opts,
708                                            const llvm::Triple &Triple,
709                                            MacroBuilder &Builder) const {
710   Builder.defineMacro("__AARCH64_SIMD__");
711   if (Triple.isArch32Bit())
712     Builder.defineMacro("__ARM64_ARCH_8_32__");
713   else
714     Builder.defineMacro("__ARM64_ARCH_8__");
715   Builder.defineMacro("__ARM_NEON__");
716   Builder.defineMacro("__LITTLE_ENDIAN__");
717   Builder.defineMacro("__REGISTER_PREFIX__", "");
718   Builder.defineMacro("__arm64", "1");
719   Builder.defineMacro("__arm64__", "1");
720 
721   getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion);
722 }
723 
724 TargetInfo::BuiltinVaListKind
725 DarwinAArch64TargetInfo::getBuiltinVaListKind() const {
726   return TargetInfo::CharPtrBuiltinVaList;
727 }
728 
729 // 64-bit RenderScript is aarch64
730 RenderScript64TargetInfo::RenderScript64TargetInfo(const llvm::Triple &Triple,
731                                                    const TargetOptions &Opts)
732     : AArch64leTargetInfo(llvm::Triple("aarch64", Triple.getVendorName(),
733                                        Triple.getOSName(),
734                                        Triple.getEnvironmentName()),
735                           Opts) {
736   IsRenderScriptTarget = true;
737 }
738 
739 void RenderScript64TargetInfo::getTargetDefines(const LangOptions &Opts,
740                                                 MacroBuilder &Builder) const {
741   Builder.defineMacro("__RENDERSCRIPT__");
742   AArch64leTargetInfo::getTargetDefines(Opts, Builder);
743 }
744