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