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 // 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 291 ArrayRef<Builtin::Info> AArch64TargetInfo::getTargetBuiltins() const { 292 return llvm::makeArrayRef(BuiltinInfo, clang::AArch64::LastTSBuiltin - 293 Builtin::FirstTSBuiltin); 294 } 295 296 bool 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 302 bool 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 353 TargetInfo::CallingConvCheckResult 354 AArch64TargetInfo::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 369 bool AArch64TargetInfo::isCLZForZeroUndef() const { return false; } 370 371 TargetInfo::BuiltinVaListKind AArch64TargetInfo::getBuiltinVaListKind() const { 372 return TargetInfo::AArch64ABIBuiltinVaList; 373 } 374 375 const 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 411 ArrayRef<const char *> AArch64TargetInfo::getGCCRegNames() const { 412 return llvm::makeArrayRef(GCCRegNames); 413 } 414 415 const 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 454 ArrayRef<TargetInfo::GCCRegAlias> AArch64TargetInfo::getGCCRegAliases() const { 455 return llvm::makeArrayRef(GCCRegAliases); 456 } 457 458 bool 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 497 bool 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 528 const char *AArch64TargetInfo::getClobbers() const { return ""; } 529 530 int AArch64TargetInfo::getEHDataRegisterNumber(unsigned RegNo) const { 531 if (RegNo == 0) 532 return 0; 533 if (RegNo == 1) 534 return 1; 535 return -1; 536 } 537 538 bool AArch64TargetInfo::hasInt128Type() const { return true; } 539 540 AArch64leTargetInfo::AArch64leTargetInfo(const llvm::Triple &Triple, 541 const TargetOptions &Opts) 542 : AArch64TargetInfo(Triple, Opts) {} 543 544 void 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 554 void AArch64leTargetInfo::getTargetDefines(const LangOptions &Opts, 555 MacroBuilder &Builder) const { 556 Builder.defineMacro("__AARCH64EL__"); 557 AArch64TargetInfo::getTargetDefines(Opts, Builder); 558 } 559 560 AArch64beTargetInfo::AArch64beTargetInfo(const llvm::Triple &Triple, 561 const TargetOptions &Opts) 562 : AArch64TargetInfo(Triple, Opts) {} 563 564 void 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 572 void 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 577 WindowsARM64TargetInfo::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 595 void WindowsARM64TargetInfo::setDataLayout() { 596 resetDataLayout("e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128"); 597 } 598 599 TargetInfo::BuiltinVaListKind 600 WindowsARM64TargetInfo::getBuiltinVaListKind() const { 601 return TargetInfo::CharPtrBuiltinVaList; 602 } 603 604 TargetInfo::CallingConvCheckResult 605 WindowsARM64TargetInfo::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 624 MicrosoftARM64TargetInfo::MicrosoftARM64TargetInfo(const llvm::Triple &Triple, 625 const TargetOptions &Opts) 626 : WindowsARM64TargetInfo(Triple, Opts) { 627 TheCXXABI.set(TargetCXXABI::Microsoft); 628 } 629 630 void MicrosoftARM64TargetInfo::getTargetDefines(const LangOptions &Opts, 631 MacroBuilder &Builder) const { 632 WindowsARM64TargetInfo::getTargetDefines(Opts, Builder); 633 Builder.defineMacro("_M_ARM64", "1"); 634 } 635 636 TargetInfo::CallingConvKind 637 MicrosoftARM64TargetInfo::getCallingConvKind(bool ClangABICompat4) const { 638 return CCK_MicrosoftWin64; 639 } 640 641 unsigned 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 658 MinGWARM64TargetInfo::MinGWARM64TargetInfo(const llvm::Triple &Triple, 659 const TargetOptions &Opts) 660 : WindowsARM64TargetInfo(Triple, Opts) { 661 TheCXXABI.set(TargetCXXABI::GenericAArch64); 662 } 663 664 DarwinAArch64TargetInfo::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 688 void 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 705 TargetInfo::BuiltinVaListKind 706 DarwinAArch64TargetInfo::getBuiltinVaListKind() const { 707 return TargetInfo::CharPtrBuiltinVaList; 708 } 709 710 // 64-bit RenderScript is aarch64 711 RenderScript64TargetInfo::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 720 void RenderScript64TargetInfo::getTargetDefines(const LangOptions &Opts, 721 MacroBuilder &Builder) const { 722 Builder.defineMacro("__RENDERSCRIPT__"); 723 AArch64leTargetInfo::getTargetDefines(Opts, Builder); 724 } 725