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 Builder.defineMacro("__ARM_FEATURE_QRDMX", "1"); 159 Builder.defineMacro("__ARM_FEATURE_ATOMICS", "1"); 160 Builder.defineMacro("__ARM_FEATURE_CRC32", "1"); 161 } 162 163 void AArch64TargetInfo::getTargetDefinesARMV82A(const LangOptions &Opts, 164 MacroBuilder &Builder) const { 165 // Also include the ARMv8.1 defines 166 getTargetDefinesARMV81A(Opts, Builder); 167 } 168 169 void AArch64TargetInfo::getTargetDefinesARMV83A(const LangOptions &Opts, 170 MacroBuilder &Builder) const { 171 Builder.defineMacro("__ARM_FEATURE_COMPLEX", "1"); 172 Builder.defineMacro("__ARM_FEATURE_JCVT", "1"); 173 // Also include the Armv8.2 defines 174 getTargetDefinesARMV82A(Opts, Builder); 175 } 176 177 void AArch64TargetInfo::getTargetDefinesARMV84A(const LangOptions &Opts, 178 MacroBuilder &Builder) const { 179 // Also include the Armv8.3 defines 180 getTargetDefinesARMV83A(Opts, Builder); 181 } 182 183 void AArch64TargetInfo::getTargetDefinesARMV85A(const LangOptions &Opts, 184 MacroBuilder &Builder) const { 185 Builder.defineMacro("__ARM_FEATURE_FRINT", "1"); 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::getTargetDefinesARMV87A(const LangOptions &Opts, 201 MacroBuilder &Builder) const { 202 // Also include the Armv8.6 defines 203 getTargetDefinesARMV86A(Opts, Builder); 204 } 205 206 void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts, 207 MacroBuilder &Builder) const { 208 // Target identification. 209 Builder.defineMacro("__aarch64__"); 210 // For bare-metal. 211 if (getTriple().getOS() == llvm::Triple::UnknownOS && 212 getTriple().isOSBinFormatELF()) 213 Builder.defineMacro("__ELF__"); 214 215 // Target properties. 216 if (!getTriple().isOSWindows() && getTriple().isArch64Bit()) { 217 Builder.defineMacro("_LP64"); 218 Builder.defineMacro("__LP64__"); 219 } 220 221 std::string CodeModel = getTargetOpts().CodeModel; 222 if (CodeModel == "default") 223 CodeModel = "small"; 224 for (char &c : CodeModel) 225 c = toupper(c); 226 Builder.defineMacro("__AARCH64_CMODEL_" + CodeModel + "__"); 227 228 // ACLE predefines. Many can only have one possible value on v8 AArch64. 229 Builder.defineMacro("__ARM_ACLE", "200"); 230 Builder.defineMacro("__ARM_ARCH", "8"); 231 Builder.defineMacro("__ARM_ARCH_PROFILE", "'A'"); 232 233 Builder.defineMacro("__ARM_64BIT_STATE", "1"); 234 Builder.defineMacro("__ARM_PCS_AAPCS64", "1"); 235 Builder.defineMacro("__ARM_ARCH_ISA_A64", "1"); 236 237 Builder.defineMacro("__ARM_FEATURE_CLZ", "1"); 238 Builder.defineMacro("__ARM_FEATURE_FMA", "1"); 239 Builder.defineMacro("__ARM_FEATURE_LDREX", "0xF"); 240 Builder.defineMacro("__ARM_FEATURE_IDIV", "1"); // As specified in ACLE 241 Builder.defineMacro("__ARM_FEATURE_DIV"); // For backwards compatibility 242 Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN", "1"); 243 Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING", "1"); 244 245 Builder.defineMacro("__ARM_ALIGN_MAX_STACK_PWR", "4"); 246 247 // 0xe implies support for half, single and double precision operations. 248 Builder.defineMacro("__ARM_FP", "0xE"); 249 250 // PCS specifies this for SysV variants, which is all we support. Other ABIs 251 // may choose __ARM_FP16_FORMAT_ALTERNATIVE. 252 Builder.defineMacro("__ARM_FP16_FORMAT_IEEE", "1"); 253 Builder.defineMacro("__ARM_FP16_ARGS", "1"); 254 255 if (Opts.UnsafeFPMath) 256 Builder.defineMacro("__ARM_FP_FAST", "1"); 257 258 Builder.defineMacro("__ARM_SIZEOF_WCHAR_T", 259 Twine(Opts.WCharSize ? Opts.WCharSize : 4)); 260 261 Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM", Opts.ShortEnums ? "1" : "4"); 262 263 if (FPU & NeonMode) { 264 Builder.defineMacro("__ARM_NEON", "1"); 265 // 64-bit NEON supports half, single and double precision operations. 266 Builder.defineMacro("__ARM_NEON_FP", "0xE"); 267 } 268 269 if (FPU & SveMode) 270 Builder.defineMacro("__ARM_FEATURE_SVE", "1"); 271 272 if (HasSVE2) 273 Builder.defineMacro("__ARM_FEATURE_SVE2", "1"); 274 275 if (HasSVE2 && HasSVE2AES) 276 Builder.defineMacro("__ARM_FEATURE_SVE2_AES", "1"); 277 278 if (HasSVE2 && HasSVE2BitPerm) 279 Builder.defineMacro("__ARM_FEATURE_SVE2_BITPERM", "1"); 280 281 if (HasSVE2 && HasSVE2SHA3) 282 Builder.defineMacro("__ARM_FEATURE_SVE2_SHA3", "1"); 283 284 if (HasSVE2 && HasSVE2SM4) 285 Builder.defineMacro("__ARM_FEATURE_SVE2_SM4", "1"); 286 287 if (HasCRC) 288 Builder.defineMacro("__ARM_FEATURE_CRC32", "1"); 289 290 // The __ARM_FEATURE_CRYPTO is deprecated in favor of finer grained feature 291 // macros for AES, SHA2, SHA3 and SM4 292 if (HasAES && HasSHA2) 293 Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1"); 294 295 if (HasAES) 296 Builder.defineMacro("__ARM_FEATURE_AES", "1"); 297 298 if (HasSHA2) 299 Builder.defineMacro("__ARM_FEATURE_SHA2", "1"); 300 301 if (HasSHA3) { 302 Builder.defineMacro("__ARM_FEATURE_SHA3", "1"); 303 Builder.defineMacro("__ARM_FEATURE_SHA512", "1"); 304 } 305 306 if (HasSM4) { 307 Builder.defineMacro("__ARM_FEATURE_SM3", "1"); 308 Builder.defineMacro("__ARM_FEATURE_SM4", "1"); 309 } 310 311 if (HasUnaligned) 312 Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1"); 313 314 if ((FPU & NeonMode) && HasFullFP16) 315 Builder.defineMacro("__ARM_FEATURE_FP16_VECTOR_ARITHMETIC", "1"); 316 if (HasFullFP16) 317 Builder.defineMacro("__ARM_FEATURE_FP16_SCALAR_ARITHMETIC", "1"); 318 319 if (HasDotProd) 320 Builder.defineMacro("__ARM_FEATURE_DOTPROD", "1"); 321 322 if (HasMTE) 323 Builder.defineMacro("__ARM_FEATURE_MEMORY_TAGGING", "1"); 324 325 if (HasTME) 326 Builder.defineMacro("__ARM_FEATURE_TME", "1"); 327 328 if (HasMatMul) 329 Builder.defineMacro("__ARM_FEATURE_MATMUL_INT8", "1"); 330 331 if (HasLSE) 332 Builder.defineMacro("__ARM_FEATURE_ATOMICS", "1"); 333 334 if (HasBFloat16) { 335 Builder.defineMacro("__ARM_FEATURE_BF16", "1"); 336 Builder.defineMacro("__ARM_FEATURE_BF16_VECTOR_ARITHMETIC", "1"); 337 Builder.defineMacro("__ARM_BF16_FORMAT_ALTERNATIVE", "1"); 338 Builder.defineMacro("__ARM_FEATURE_BF16_SCALAR_ARITHMETIC", "1"); 339 } 340 341 if ((FPU & SveMode) && HasBFloat16) { 342 Builder.defineMacro("__ARM_FEATURE_SVE_BF16", "1"); 343 } 344 345 if ((FPU & SveMode) && HasMatmulFP64) 346 Builder.defineMacro("__ARM_FEATURE_SVE_MATMUL_FP64", "1"); 347 348 if ((FPU & SveMode) && HasMatmulFP32) 349 Builder.defineMacro("__ARM_FEATURE_SVE_MATMUL_FP32", "1"); 350 351 if ((FPU & SveMode) && HasMatMul) 352 Builder.defineMacro("__ARM_FEATURE_SVE_MATMUL_INT8", "1"); 353 354 if ((FPU & NeonMode) && HasFP16FML) 355 Builder.defineMacro("__ARM_FEATURE_FP16_FML", "1"); 356 357 if (Opts.hasSignReturnAddress()) { 358 // Bitmask: 359 // 0: Protection using the A key 360 // 1: Protection using the B key 361 // 2: Protection including leaf functions 362 unsigned Value = 0; 363 364 if (Opts.isSignReturnAddressWithAKey()) 365 Value |= (1 << 0); 366 else 367 Value |= (1 << 1); 368 369 if (Opts.isSignReturnAddressScopeAll()) 370 Value |= (1 << 2); 371 372 Builder.defineMacro("__ARM_FEATURE_PAC_DEFAULT", std::to_string(Value)); 373 } 374 375 if (Opts.BranchTargetEnforcement) 376 Builder.defineMacro("__ARM_FEATURE_BTI_DEFAULT", "1"); 377 378 if (HasLS64) 379 Builder.defineMacro("__ARM_FEATURE_LS64", "1"); 380 381 if (HasRandGen) 382 Builder.defineMacro("__ARM_FEATURE_RNG", "1"); 383 384 switch (ArchKind) { 385 default: 386 break; 387 case llvm::AArch64::ArchKind::ARMV8_1A: 388 getTargetDefinesARMV81A(Opts, Builder); 389 break; 390 case llvm::AArch64::ArchKind::ARMV8_2A: 391 getTargetDefinesARMV82A(Opts, Builder); 392 break; 393 case llvm::AArch64::ArchKind::ARMV8_3A: 394 getTargetDefinesARMV83A(Opts, Builder); 395 break; 396 case llvm::AArch64::ArchKind::ARMV8_4A: 397 getTargetDefinesARMV84A(Opts, Builder); 398 break; 399 case llvm::AArch64::ArchKind::ARMV8_5A: 400 getTargetDefinesARMV85A(Opts, Builder); 401 break; 402 case llvm::AArch64::ArchKind::ARMV8_6A: 403 getTargetDefinesARMV86A(Opts, Builder); 404 break; 405 case llvm::AArch64::ArchKind::ARMV8_7A: 406 getTargetDefinesARMV87A(Opts, Builder); 407 break; 408 } 409 410 // All of the __sync_(bool|val)_compare_and_swap_(1|2|4|8) builtins work. 411 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1"); 412 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2"); 413 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4"); 414 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8"); 415 416 if (Opts.ArmSveVectorBits) { 417 Builder.defineMacro("__ARM_FEATURE_SVE_BITS", Twine(Opts.ArmSveVectorBits)); 418 Builder.defineMacro("__ARM_FEATURE_SVE_VECTOR_OPERATORS"); 419 } 420 } 421 422 ArrayRef<Builtin::Info> AArch64TargetInfo::getTargetBuiltins() const { 423 return llvm::makeArrayRef(BuiltinInfo, clang::AArch64::LastTSBuiltin - 424 Builtin::FirstTSBuiltin); 425 } 426 427 Optional<std::pair<unsigned, unsigned>> 428 AArch64TargetInfo::getVScaleRange(const LangOptions &LangOpts) const { 429 if (LangOpts.ArmSveVectorBits) { 430 unsigned VScale = LangOpts.ArmSveVectorBits / 128; 431 return std::pair<unsigned, unsigned>(VScale, VScale); 432 } 433 if (hasFeature("sve")) 434 return std::pair<unsigned, unsigned>(0, 16); 435 return None; 436 } 437 438 bool AArch64TargetInfo::hasFeature(StringRef Feature) const { 439 return Feature == "aarch64" || Feature == "arm64" || Feature == "arm" || 440 (Feature == "neon" && (FPU & NeonMode)) || 441 ((Feature == "sve" || Feature == "sve2" || Feature == "sve2-bitperm" || 442 Feature == "sve2-aes" || Feature == "sve2-sha3" || 443 Feature == "sve2-sm4" || Feature == "f64mm" || Feature == "f32mm" || 444 Feature == "i8mm" || Feature == "bf16") && 445 (FPU & SveMode)) || 446 (Feature == "ls64" && HasLS64); 447 } 448 449 bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features, 450 DiagnosticsEngine &Diags) { 451 FPU = FPUMode; 452 HasCRC = false; 453 HasCrypto = false; 454 HasAES = false; 455 HasSHA2 = false; 456 HasSHA3 = false; 457 HasSM4 = false; 458 HasUnaligned = true; 459 HasFullFP16 = false; 460 HasDotProd = false; 461 HasFP16FML = false; 462 HasMTE = false; 463 HasTME = false; 464 HasLS64 = false; 465 HasRandGen = false; 466 HasMatMul = false; 467 HasBFloat16 = false; 468 HasSVE2 = false; 469 HasSVE2AES = false; 470 HasSVE2SHA3 = false; 471 HasSVE2SM4 = false; 472 HasSVE2BitPerm = false; 473 HasMatmulFP64 = false; 474 HasMatmulFP32 = false; 475 HasLSE = false; 476 477 ArchKind = llvm::AArch64::ArchKind::ARMV8A; 478 479 for (const auto &Feature : Features) { 480 if (Feature == "+neon") 481 FPU |= NeonMode; 482 if (Feature == "+sve") { 483 FPU |= SveMode; 484 HasFullFP16 = 1; 485 } 486 if (Feature == "+sve2") { 487 FPU |= SveMode; 488 HasFullFP16 = 1; 489 HasSVE2 = 1; 490 } 491 if (Feature == "+sve2-aes") { 492 FPU |= SveMode; 493 HasFullFP16 = 1; 494 HasSVE2 = 1; 495 HasSVE2AES = 1; 496 } 497 if (Feature == "+sve2-sha3") { 498 FPU |= SveMode; 499 HasFullFP16 = 1; 500 HasSVE2 = 1; 501 HasSVE2SHA3 = 1; 502 } 503 if (Feature == "+sve2-sm4") { 504 FPU |= SveMode; 505 HasFullFP16 = 1; 506 HasSVE2 = 1; 507 HasSVE2SM4 = 1; 508 } 509 if (Feature == "+sve2-bitperm") { 510 FPU |= SveMode; 511 HasFullFP16 = 1; 512 HasSVE2 = 1; 513 HasSVE2BitPerm = 1; 514 } 515 if (Feature == "+f32mm") { 516 FPU |= SveMode; 517 HasMatmulFP32 = true; 518 } 519 if (Feature == "+f64mm") { 520 FPU |= SveMode; 521 HasMatmulFP64 = true; 522 } 523 if (Feature == "+crc") 524 HasCRC = true; 525 if (Feature == "+crypto") 526 HasCrypto = true; 527 if (Feature == "+aes") 528 HasAES = true; 529 if (Feature == "+sha2") 530 HasSHA2 = true; 531 if (Feature == "+sha3") { 532 HasSHA2 = true; 533 HasSHA3 = true; 534 } 535 if (Feature == "+sm4") 536 HasSM4 = true; 537 if (Feature == "+strict-align") 538 HasUnaligned = false; 539 if (Feature == "+v8.1a") 540 ArchKind = llvm::AArch64::ArchKind::ARMV8_1A; 541 if (Feature == "+v8.2a") 542 ArchKind = llvm::AArch64::ArchKind::ARMV8_2A; 543 if (Feature == "+v8.3a") 544 ArchKind = llvm::AArch64::ArchKind::ARMV8_3A; 545 if (Feature == "+v8.4a") 546 ArchKind = llvm::AArch64::ArchKind::ARMV8_4A; 547 if (Feature == "+v8.5a") 548 ArchKind = llvm::AArch64::ArchKind::ARMV8_5A; 549 if (Feature == "+v8.6a") 550 ArchKind = llvm::AArch64::ArchKind::ARMV8_6A; 551 if (Feature == "+v8.7a") 552 ArchKind = llvm::AArch64::ArchKind::ARMV8_7A; 553 if (Feature == "+v8r") 554 ArchKind = llvm::AArch64::ArchKind::ARMV8R; 555 if (Feature == "+fullfp16") 556 HasFullFP16 = true; 557 if (Feature == "+dotprod") 558 HasDotProd = true; 559 if (Feature == "+fp16fml") 560 HasFP16FML = true; 561 if (Feature == "+mte") 562 HasMTE = true; 563 if (Feature == "+tme") 564 HasTME = true; 565 if (Feature == "+pauth") 566 HasPAuth = true; 567 if (Feature == "+i8mm") 568 HasMatMul = true; 569 if (Feature == "+bf16") 570 HasBFloat16 = true; 571 if (Feature == "+lse") 572 HasLSE = true; 573 if (Feature == "+ls64") 574 HasLS64 = true; 575 if (Feature == "+rand") 576 HasRandGen = true; 577 if (Feature == "+flagm") 578 HasFlagM = true; 579 } 580 581 setDataLayout(); 582 583 return true; 584 } 585 586 TargetInfo::CallingConvCheckResult 587 AArch64TargetInfo::checkCallingConvention(CallingConv CC) const { 588 switch (CC) { 589 case CC_C: 590 case CC_Swift: 591 case CC_SwiftAsync: 592 case CC_PreserveMost: 593 case CC_PreserveAll: 594 case CC_OpenCLKernel: 595 case CC_AArch64VectorCall: 596 case CC_Win64: 597 return CCCR_OK; 598 default: 599 return CCCR_Warning; 600 } 601 } 602 603 bool AArch64TargetInfo::isCLZForZeroUndef() const { return false; } 604 605 TargetInfo::BuiltinVaListKind AArch64TargetInfo::getBuiltinVaListKind() const { 606 return TargetInfo::AArch64ABIBuiltinVaList; 607 } 608 609 const char *const AArch64TargetInfo::GCCRegNames[] = { 610 // 32-bit Integer registers 611 "w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7", "w8", "w9", "w10", "w11", 612 "w12", "w13", "w14", "w15", "w16", "w17", "w18", "w19", "w20", "w21", "w22", 613 "w23", "w24", "w25", "w26", "w27", "w28", "w29", "w30", "wsp", 614 615 // 64-bit Integer registers 616 "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", 617 "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22", 618 "x23", "x24", "x25", "x26", "x27", "x28", "fp", "lr", "sp", 619 620 // 32-bit floating point regsisters 621 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", 622 "s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22", 623 "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31", 624 625 // 64-bit floating point regsisters 626 "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11", 627 "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19", "d20", "d21", "d22", 628 "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31", 629 630 // Neon vector registers 631 "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11", 632 "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", "v20", "v21", "v22", 633 "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31", 634 635 // SVE vector registers 636 "z0", "z1", "z2", "z3", "z4", "z5", "z6", "z7", "z8", "z9", "z10", 637 "z11", "z12", "z13", "z14", "z15", "z16", "z17", "z18", "z19", "z20", "z21", 638 "z22", "z23", "z24", "z25", "z26", "z27", "z28", "z29", "z30", "z31", 639 640 // SVE predicate registers 641 "p0", "p1", "p2", "p3", "p4", "p5", "p6", "p7", "p8", "p9", "p10", 642 "p11", "p12", "p13", "p14", "p15" 643 }; 644 645 ArrayRef<const char *> AArch64TargetInfo::getGCCRegNames() const { 646 return llvm::makeArrayRef(GCCRegNames); 647 } 648 649 const TargetInfo::GCCRegAlias AArch64TargetInfo::GCCRegAliases[] = { 650 {{"w31"}, "wsp"}, 651 {{"x31"}, "sp"}, 652 // GCC rN registers are aliases of xN registers. 653 {{"r0"}, "x0"}, 654 {{"r1"}, "x1"}, 655 {{"r2"}, "x2"}, 656 {{"r3"}, "x3"}, 657 {{"r4"}, "x4"}, 658 {{"r5"}, "x5"}, 659 {{"r6"}, "x6"}, 660 {{"r7"}, "x7"}, 661 {{"r8"}, "x8"}, 662 {{"r9"}, "x9"}, 663 {{"r10"}, "x10"}, 664 {{"r11"}, "x11"}, 665 {{"r12"}, "x12"}, 666 {{"r13"}, "x13"}, 667 {{"r14"}, "x14"}, 668 {{"r15"}, "x15"}, 669 {{"r16"}, "x16"}, 670 {{"r17"}, "x17"}, 671 {{"r18"}, "x18"}, 672 {{"r19"}, "x19"}, 673 {{"r20"}, "x20"}, 674 {{"r21"}, "x21"}, 675 {{"r22"}, "x22"}, 676 {{"r23"}, "x23"}, 677 {{"r24"}, "x24"}, 678 {{"r25"}, "x25"}, 679 {{"r26"}, "x26"}, 680 {{"r27"}, "x27"}, 681 {{"r28"}, "x28"}, 682 {{"r29", "x29"}, "fp"}, 683 {{"r30", "x30"}, "lr"}, 684 // The S/D/Q and W/X registers overlap, but aren't really aliases; we 685 // don't want to substitute one of these for a different-sized one. 686 }; 687 688 ArrayRef<TargetInfo::GCCRegAlias> AArch64TargetInfo::getGCCRegAliases() const { 689 return llvm::makeArrayRef(GCCRegAliases); 690 } 691 692 bool AArch64TargetInfo::validateAsmConstraint( 693 const char *&Name, TargetInfo::ConstraintInfo &Info) const { 694 switch (*Name) { 695 default: 696 return false; 697 case 'w': // Floating point and SIMD registers (V0-V31) 698 Info.setAllowsRegister(); 699 return true; 700 case 'I': // Constant that can be used with an ADD instruction 701 case 'J': // Constant that can be used with a SUB instruction 702 case 'K': // Constant that can be used with a 32-bit logical instruction 703 case 'L': // Constant that can be used with a 64-bit logical instruction 704 case 'M': // Constant that can be used as a 32-bit MOV immediate 705 case 'N': // Constant that can be used as a 64-bit MOV immediate 706 case 'Y': // Floating point constant zero 707 case 'Z': // Integer constant zero 708 return true; 709 case 'Q': // A memory reference with base register and no offset 710 Info.setAllowsMemory(); 711 return true; 712 case 'S': // A symbolic address 713 Info.setAllowsRegister(); 714 return true; 715 case 'U': 716 if (Name[1] == 'p' && (Name[2] == 'l' || Name[2] == 'a')) { 717 // SVE predicate registers ("Upa"=P0-15, "Upl"=P0-P7) 718 Info.setAllowsRegister(); 719 Name += 2; 720 return true; 721 } 722 // Ump: A memory address suitable for ldp/stp in SI, DI, SF and DF modes. 723 // Utf: A memory address suitable for ldp/stp in TF mode. 724 // Usa: An absolute symbolic address. 725 // Ush: The high part (bits 32:12) of a pc-relative symbolic address. 726 727 // Better to return an error saying that it's an unrecognised constraint 728 // even if this is a valid constraint in gcc. 729 return false; 730 case 'z': // Zero register, wzr or xzr 731 Info.setAllowsRegister(); 732 return true; 733 case 'x': // Floating point and SIMD registers (V0-V15) 734 Info.setAllowsRegister(); 735 return true; 736 case 'y': // SVE registers (V0-V7) 737 Info.setAllowsRegister(); 738 return true; 739 } 740 return false; 741 } 742 743 bool AArch64TargetInfo::validateConstraintModifier( 744 StringRef Constraint, char Modifier, unsigned Size, 745 std::string &SuggestedModifier) const { 746 // Strip off constraint modifiers. 747 while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&') 748 Constraint = Constraint.substr(1); 749 750 switch (Constraint[0]) { 751 default: 752 return true; 753 case 'z': 754 case 'r': { 755 switch (Modifier) { 756 case 'x': 757 case 'w': 758 // For now assume that the person knows what they're 759 // doing with the modifier. 760 return true; 761 default: 762 // By default an 'r' constraint will be in the 'x' 763 // registers. 764 if (Size == 64) 765 return true; 766 767 if (Size == 512) 768 return HasLS64; 769 770 SuggestedModifier = "w"; 771 return false; 772 } 773 } 774 } 775 } 776 777 const char *AArch64TargetInfo::getClobbers() const { return ""; } 778 779 int AArch64TargetInfo::getEHDataRegisterNumber(unsigned RegNo) const { 780 if (RegNo == 0) 781 return 0; 782 if (RegNo == 1) 783 return 1; 784 return -1; 785 } 786 787 bool AArch64TargetInfo::hasInt128Type() const { return true; } 788 789 AArch64leTargetInfo::AArch64leTargetInfo(const llvm::Triple &Triple, 790 const TargetOptions &Opts) 791 : AArch64TargetInfo(Triple, Opts) {} 792 793 void AArch64leTargetInfo::setDataLayout() { 794 if (getTriple().isOSBinFormatMachO()) { 795 if(getTriple().isArch32Bit()) 796 resetDataLayout("e-m:o-p:32:32-i64:64-i128:128-n32:64-S128", "_"); 797 else 798 resetDataLayout("e-m:o-i64:64-i128:128-n32:64-S128", "_"); 799 } else 800 resetDataLayout("e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"); 801 } 802 803 void AArch64leTargetInfo::getTargetDefines(const LangOptions &Opts, 804 MacroBuilder &Builder) const { 805 Builder.defineMacro("__AARCH64EL__"); 806 AArch64TargetInfo::getTargetDefines(Opts, Builder); 807 } 808 809 AArch64beTargetInfo::AArch64beTargetInfo(const llvm::Triple &Triple, 810 const TargetOptions &Opts) 811 : AArch64TargetInfo(Triple, Opts) {} 812 813 void AArch64beTargetInfo::getTargetDefines(const LangOptions &Opts, 814 MacroBuilder &Builder) const { 815 Builder.defineMacro("__AARCH64EB__"); 816 Builder.defineMacro("__AARCH_BIG_ENDIAN"); 817 Builder.defineMacro("__ARM_BIG_ENDIAN"); 818 AArch64TargetInfo::getTargetDefines(Opts, Builder); 819 } 820 821 void AArch64beTargetInfo::setDataLayout() { 822 assert(!getTriple().isOSBinFormatMachO()); 823 resetDataLayout("E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"); 824 } 825 826 WindowsARM64TargetInfo::WindowsARM64TargetInfo(const llvm::Triple &Triple, 827 const TargetOptions &Opts) 828 : WindowsTargetInfo<AArch64leTargetInfo>(Triple, Opts), Triple(Triple) { 829 830 // This is an LLP64 platform. 831 // int:4, long:4, long long:8, long double:8. 832 IntWidth = IntAlign = 32; 833 LongWidth = LongAlign = 32; 834 DoubleAlign = LongLongAlign = 64; 835 LongDoubleWidth = LongDoubleAlign = 64; 836 LongDoubleFormat = &llvm::APFloat::IEEEdouble(); 837 IntMaxType = SignedLongLong; 838 Int64Type = SignedLongLong; 839 SizeType = UnsignedLongLong; 840 PtrDiffType = SignedLongLong; 841 IntPtrType = SignedLongLong; 842 } 843 844 void WindowsARM64TargetInfo::setDataLayout() { 845 resetDataLayout(Triple.isOSBinFormatMachO() 846 ? "e-m:o-i64:64-i128:128-n32:64-S128" 847 : "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128", 848 Triple.isOSBinFormatMachO() ? "_" : ""); 849 } 850 851 TargetInfo::BuiltinVaListKind 852 WindowsARM64TargetInfo::getBuiltinVaListKind() const { 853 return TargetInfo::CharPtrBuiltinVaList; 854 } 855 856 TargetInfo::CallingConvCheckResult 857 WindowsARM64TargetInfo::checkCallingConvention(CallingConv CC) const { 858 switch (CC) { 859 case CC_X86StdCall: 860 case CC_X86ThisCall: 861 case CC_X86FastCall: 862 case CC_X86VectorCall: 863 return CCCR_Ignore; 864 case CC_C: 865 case CC_OpenCLKernel: 866 case CC_PreserveMost: 867 case CC_PreserveAll: 868 case CC_Swift: 869 case CC_SwiftAsync: 870 case CC_Win64: 871 return CCCR_OK; 872 default: 873 return CCCR_Warning; 874 } 875 } 876 877 MicrosoftARM64TargetInfo::MicrosoftARM64TargetInfo(const llvm::Triple &Triple, 878 const TargetOptions &Opts) 879 : WindowsARM64TargetInfo(Triple, Opts) { 880 TheCXXABI.set(TargetCXXABI::Microsoft); 881 } 882 883 void MicrosoftARM64TargetInfo::getTargetDefines(const LangOptions &Opts, 884 MacroBuilder &Builder) const { 885 WindowsARM64TargetInfo::getTargetDefines(Opts, Builder); 886 Builder.defineMacro("_M_ARM64", "1"); 887 } 888 889 TargetInfo::CallingConvKind 890 MicrosoftARM64TargetInfo::getCallingConvKind(bool ClangABICompat4) const { 891 return CCK_MicrosoftWin64; 892 } 893 894 unsigned MicrosoftARM64TargetInfo::getMinGlobalAlign(uint64_t TypeSize) const { 895 unsigned Align = WindowsARM64TargetInfo::getMinGlobalAlign(TypeSize); 896 897 // MSVC does size based alignment for arm64 based on alignment section in 898 // below document, replicate that to keep alignment consistent with object 899 // files compiled by MSVC. 900 // https://docs.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions 901 if (TypeSize >= 512) { // TypeSize >= 64 bytes 902 Align = std::max(Align, 128u); // align type at least 16 bytes 903 } else if (TypeSize >= 64) { // TypeSize >= 8 bytes 904 Align = std::max(Align, 64u); // align type at least 8 butes 905 } else if (TypeSize >= 16) { // TypeSize >= 2 bytes 906 Align = std::max(Align, 32u); // align type at least 4 bytes 907 } 908 return Align; 909 } 910 911 MinGWARM64TargetInfo::MinGWARM64TargetInfo(const llvm::Triple &Triple, 912 const TargetOptions &Opts) 913 : WindowsARM64TargetInfo(Triple, Opts) { 914 TheCXXABI.set(TargetCXXABI::GenericAArch64); 915 } 916 917 DarwinAArch64TargetInfo::DarwinAArch64TargetInfo(const llvm::Triple &Triple, 918 const TargetOptions &Opts) 919 : DarwinTargetInfo<AArch64leTargetInfo>(Triple, Opts) { 920 Int64Type = SignedLongLong; 921 if (getTriple().isArch32Bit()) 922 IntMaxType = SignedLongLong; 923 924 WCharType = SignedInt; 925 UseSignedCharForObjCBool = false; 926 927 LongDoubleWidth = LongDoubleAlign = SuitableAlign = 64; 928 LongDoubleFormat = &llvm::APFloat::IEEEdouble(); 929 930 UseZeroLengthBitfieldAlignment = false; 931 932 if (getTriple().isArch32Bit()) { 933 UseBitFieldTypeAlignment = false; 934 ZeroLengthBitfieldBoundary = 32; 935 UseZeroLengthBitfieldAlignment = true; 936 TheCXXABI.set(TargetCXXABI::WatchOS); 937 } else 938 TheCXXABI.set(TargetCXXABI::AppleARM64); 939 } 940 941 void DarwinAArch64TargetInfo::getOSDefines(const LangOptions &Opts, 942 const llvm::Triple &Triple, 943 MacroBuilder &Builder) const { 944 Builder.defineMacro("__AARCH64_SIMD__"); 945 if (Triple.isArch32Bit()) 946 Builder.defineMacro("__ARM64_ARCH_8_32__"); 947 else 948 Builder.defineMacro("__ARM64_ARCH_8__"); 949 Builder.defineMacro("__ARM_NEON__"); 950 Builder.defineMacro("__LITTLE_ENDIAN__"); 951 Builder.defineMacro("__REGISTER_PREFIX__", ""); 952 Builder.defineMacro("__arm64", "1"); 953 Builder.defineMacro("__arm64__", "1"); 954 955 if (Triple.isArm64e()) 956 Builder.defineMacro("__arm64e__", "1"); 957 958 getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion); 959 } 960 961 TargetInfo::BuiltinVaListKind 962 DarwinAArch64TargetInfo::getBuiltinVaListKind() const { 963 return TargetInfo::CharPtrBuiltinVaList; 964 } 965 966 // 64-bit RenderScript is aarch64 967 RenderScript64TargetInfo::RenderScript64TargetInfo(const llvm::Triple &Triple, 968 const TargetOptions &Opts) 969 : AArch64leTargetInfo(llvm::Triple("aarch64", Triple.getVendorName(), 970 Triple.getOSName(), 971 Triple.getEnvironmentName()), 972 Opts) { 973 IsRenderScriptTarget = true; 974 } 975 976 void RenderScript64TargetInfo::getTargetDefines(const LangOptions &Opts, 977 MacroBuilder &Builder) const { 978 Builder.defineMacro("__RENDERSCRIPT__"); 979 AArch64leTargetInfo::getTargetDefines(Opts, Builder); 980 } 981