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