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 if (Name[1] == 'p' && (Name[2] == 'l' || Name[2] == 'a')) { 490 // SVE predicate registers ("Upa"=P0-15, "Upl"=P0-P7) 491 Info.setAllowsRegister(); 492 Name += 2; 493 return true; 494 } 495 // Ump: A memory address suitable for ldp/stp in SI, DI, SF and DF modes. 496 // Utf: A memory address suitable for ldp/stp in TF mode. 497 // Usa: An absolute symbolic address. 498 // Ush: The high part (bits 32:12) of a pc-relative symbolic address. 499 500 // Better to return an error saying that it's an unrecognised constraint 501 // even if this is a valid constraint in gcc. 502 return false; 503 case 'z': // Zero register, wzr or xzr 504 Info.setAllowsRegister(); 505 return true; 506 case 'x': // Floating point and SIMD registers (V0-V15) 507 Info.setAllowsRegister(); 508 return true; 509 case 'y': // SVE registers (V0-V7) 510 Info.setAllowsRegister(); 511 return true; 512 } 513 return false; 514 } 515 516 bool AArch64TargetInfo::validateConstraintModifier( 517 StringRef Constraint, char Modifier, unsigned Size, 518 std::string &SuggestedModifier) const { 519 // Strip off constraint modifiers. 520 while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&') 521 Constraint = Constraint.substr(1); 522 523 switch (Constraint[0]) { 524 default: 525 return true; 526 case 'z': 527 case 'r': { 528 switch (Modifier) { 529 case 'x': 530 case 'w': 531 // For now assume that the person knows what they're 532 // doing with the modifier. 533 return true; 534 default: 535 // By default an 'r' constraint will be in the 'x' 536 // registers. 537 if (Size == 64) 538 return true; 539 540 SuggestedModifier = "w"; 541 return false; 542 } 543 } 544 } 545 } 546 547 const char *AArch64TargetInfo::getClobbers() const { return ""; } 548 549 int AArch64TargetInfo::getEHDataRegisterNumber(unsigned RegNo) const { 550 if (RegNo == 0) 551 return 0; 552 if (RegNo == 1) 553 return 1; 554 return -1; 555 } 556 557 bool AArch64TargetInfo::hasInt128Type() const { return true; } 558 559 AArch64leTargetInfo::AArch64leTargetInfo(const llvm::Triple &Triple, 560 const TargetOptions &Opts) 561 : AArch64TargetInfo(Triple, Opts) {} 562 563 void AArch64leTargetInfo::setDataLayout() { 564 if (getTriple().isOSBinFormatMachO()) { 565 if(getTriple().isArch32Bit()) 566 resetDataLayout("e-m:o-p:32:32-i64:64-i128:128-n32:64-S128"); 567 else 568 resetDataLayout("e-m:o-i64:64-i128:128-n32:64-S128"); 569 } else 570 resetDataLayout("e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"); 571 } 572 573 void AArch64leTargetInfo::getTargetDefines(const LangOptions &Opts, 574 MacroBuilder &Builder) const { 575 Builder.defineMacro("__AARCH64EL__"); 576 AArch64TargetInfo::getTargetDefines(Opts, Builder); 577 } 578 579 AArch64beTargetInfo::AArch64beTargetInfo(const llvm::Triple &Triple, 580 const TargetOptions &Opts) 581 : AArch64TargetInfo(Triple, Opts) {} 582 583 void AArch64beTargetInfo::getTargetDefines(const LangOptions &Opts, 584 MacroBuilder &Builder) const { 585 Builder.defineMacro("__AARCH64EB__"); 586 Builder.defineMacro("__AARCH_BIG_ENDIAN"); 587 Builder.defineMacro("__ARM_BIG_ENDIAN"); 588 AArch64TargetInfo::getTargetDefines(Opts, Builder); 589 } 590 591 void AArch64beTargetInfo::setDataLayout() { 592 assert(!getTriple().isOSBinFormatMachO()); 593 resetDataLayout("E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"); 594 } 595 596 WindowsARM64TargetInfo::WindowsARM64TargetInfo(const llvm::Triple &Triple, 597 const TargetOptions &Opts) 598 : WindowsTargetInfo<AArch64leTargetInfo>(Triple, Opts), Triple(Triple) { 599 600 // This is an LLP64 platform. 601 // int:4, long:4, long long:8, long double:8. 602 IntWidth = IntAlign = 32; 603 LongWidth = LongAlign = 32; 604 DoubleAlign = LongLongAlign = 64; 605 LongDoubleWidth = LongDoubleAlign = 64; 606 LongDoubleFormat = &llvm::APFloat::IEEEdouble(); 607 IntMaxType = SignedLongLong; 608 Int64Type = SignedLongLong; 609 SizeType = UnsignedLongLong; 610 PtrDiffType = SignedLongLong; 611 IntPtrType = SignedLongLong; 612 } 613 614 void WindowsARM64TargetInfo::setDataLayout() { 615 resetDataLayout("e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128"); 616 } 617 618 TargetInfo::BuiltinVaListKind 619 WindowsARM64TargetInfo::getBuiltinVaListKind() const { 620 return TargetInfo::CharPtrBuiltinVaList; 621 } 622 623 TargetInfo::CallingConvCheckResult 624 WindowsARM64TargetInfo::checkCallingConvention(CallingConv CC) const { 625 switch (CC) { 626 case CC_X86StdCall: 627 case CC_X86ThisCall: 628 case CC_X86FastCall: 629 case CC_X86VectorCall: 630 return CCCR_Ignore; 631 case CC_C: 632 case CC_OpenCLKernel: 633 case CC_PreserveMost: 634 case CC_PreserveAll: 635 case CC_Swift: 636 case CC_Win64: 637 return CCCR_OK; 638 default: 639 return CCCR_Warning; 640 } 641 } 642 643 MicrosoftARM64TargetInfo::MicrosoftARM64TargetInfo(const llvm::Triple &Triple, 644 const TargetOptions &Opts) 645 : WindowsARM64TargetInfo(Triple, Opts) { 646 TheCXXABI.set(TargetCXXABI::Microsoft); 647 } 648 649 void MicrosoftARM64TargetInfo::getTargetDefines(const LangOptions &Opts, 650 MacroBuilder &Builder) const { 651 WindowsARM64TargetInfo::getTargetDefines(Opts, Builder); 652 Builder.defineMacro("_M_ARM64", "1"); 653 } 654 655 TargetInfo::CallingConvKind 656 MicrosoftARM64TargetInfo::getCallingConvKind(bool ClangABICompat4) const { 657 return CCK_MicrosoftWin64; 658 } 659 660 unsigned MicrosoftARM64TargetInfo::getMinGlobalAlign(uint64_t TypeSize) const { 661 unsigned Align = WindowsARM64TargetInfo::getMinGlobalAlign(TypeSize); 662 663 // MSVC does size based alignment for arm64 based on alignment section in 664 // below document, replicate that to keep alignment consistent with object 665 // files compiled by MSVC. 666 // https://docs.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions 667 if (TypeSize >= 512) { // TypeSize >= 64 bytes 668 Align = std::max(Align, 128u); // align type at least 16 bytes 669 } else if (TypeSize >= 64) { // TypeSize >= 8 bytes 670 Align = std::max(Align, 64u); // align type at least 8 butes 671 } else if (TypeSize >= 16) { // TypeSize >= 2 bytes 672 Align = std::max(Align, 32u); // align type at least 4 bytes 673 } 674 return Align; 675 } 676 677 MinGWARM64TargetInfo::MinGWARM64TargetInfo(const llvm::Triple &Triple, 678 const TargetOptions &Opts) 679 : WindowsARM64TargetInfo(Triple, Opts) { 680 TheCXXABI.set(TargetCXXABI::GenericAArch64); 681 } 682 683 DarwinAArch64TargetInfo::DarwinAArch64TargetInfo(const llvm::Triple &Triple, 684 const TargetOptions &Opts) 685 : DarwinTargetInfo<AArch64leTargetInfo>(Triple, Opts) { 686 Int64Type = SignedLongLong; 687 if (getTriple().isArch32Bit()) 688 IntMaxType = SignedLongLong; 689 690 WCharType = SignedInt; 691 UseSignedCharForObjCBool = false; 692 693 LongDoubleWidth = LongDoubleAlign = SuitableAlign = 64; 694 LongDoubleFormat = &llvm::APFloat::IEEEdouble(); 695 696 UseZeroLengthBitfieldAlignment = false; 697 698 if (getTriple().isArch32Bit()) { 699 UseBitFieldTypeAlignment = false; 700 ZeroLengthBitfieldBoundary = 32; 701 UseZeroLengthBitfieldAlignment = true; 702 TheCXXABI.set(TargetCXXABI::WatchOS); 703 } else 704 TheCXXABI.set(TargetCXXABI::iOS64); 705 } 706 707 void DarwinAArch64TargetInfo::getOSDefines(const LangOptions &Opts, 708 const llvm::Triple &Triple, 709 MacroBuilder &Builder) const { 710 Builder.defineMacro("__AARCH64_SIMD__"); 711 if (Triple.isArch32Bit()) 712 Builder.defineMacro("__ARM64_ARCH_8_32__"); 713 else 714 Builder.defineMacro("__ARM64_ARCH_8__"); 715 Builder.defineMacro("__ARM_NEON__"); 716 Builder.defineMacro("__LITTLE_ENDIAN__"); 717 Builder.defineMacro("__REGISTER_PREFIX__", ""); 718 Builder.defineMacro("__arm64", "1"); 719 Builder.defineMacro("__arm64__", "1"); 720 721 getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion); 722 } 723 724 TargetInfo::BuiltinVaListKind 725 DarwinAArch64TargetInfo::getBuiltinVaListKind() const { 726 return TargetInfo::CharPtrBuiltinVaList; 727 } 728 729 // 64-bit RenderScript is aarch64 730 RenderScript64TargetInfo::RenderScript64TargetInfo(const llvm::Triple &Triple, 731 const TargetOptions &Opts) 732 : AArch64leTargetInfo(llvm::Triple("aarch64", Triple.getVendorName(), 733 Triple.getOSName(), 734 Triple.getEnvironmentName()), 735 Opts) { 736 IsRenderScriptTarget = true; 737 } 738 739 void RenderScript64TargetInfo::getTargetDefines(const LangOptions &Opts, 740 MacroBuilder &Builder) const { 741 Builder.defineMacro("__RENDERSCRIPT__"); 742 AArch64leTargetInfo::getTargetDefines(Opts, Builder); 743 } 744