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