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