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