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