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 == "+pauth") 514 HasPAuth = true; 515 if (Feature == "+i8mm") 516 HasMatMul = true; 517 if (Feature == "+bf16") 518 HasBFloat16 = true; 519 if (Feature == "+lse") 520 HasLSE = true; 521 if (Feature == "+ls64") 522 HasLS64 = true; 523 if (Feature == "+flagm") 524 HasFlagM = true; 525 } 526 527 setDataLayout(); 528 529 return true; 530 } 531 532 TargetInfo::CallingConvCheckResult 533 AArch64TargetInfo::checkCallingConvention(CallingConv CC) const { 534 switch (CC) { 535 case CC_C: 536 case CC_Swift: 537 case CC_PreserveMost: 538 case CC_PreserveAll: 539 case CC_OpenCLKernel: 540 case CC_AArch64VectorCall: 541 case CC_Win64: 542 return CCCR_OK; 543 default: 544 return CCCR_Warning; 545 } 546 } 547 548 bool AArch64TargetInfo::isCLZForZeroUndef() const { return false; } 549 550 TargetInfo::BuiltinVaListKind AArch64TargetInfo::getBuiltinVaListKind() const { 551 return TargetInfo::AArch64ABIBuiltinVaList; 552 } 553 554 const char *const AArch64TargetInfo::GCCRegNames[] = { 555 // 32-bit Integer registers 556 "w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7", "w8", "w9", "w10", "w11", 557 "w12", "w13", "w14", "w15", "w16", "w17", "w18", "w19", "w20", "w21", "w22", 558 "w23", "w24", "w25", "w26", "w27", "w28", "w29", "w30", "wsp", 559 560 // 64-bit Integer registers 561 "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", 562 "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22", 563 "x23", "x24", "x25", "x26", "x27", "x28", "fp", "lr", "sp", 564 565 // 32-bit floating point regsisters 566 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", 567 "s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22", 568 "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31", 569 570 // 64-bit floating point regsisters 571 "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11", 572 "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19", "d20", "d21", "d22", 573 "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31", 574 575 // Neon vector registers 576 "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11", 577 "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", "v20", "v21", "v22", 578 "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31", 579 580 // SVE vector registers 581 "z0", "z1", "z2", "z3", "z4", "z5", "z6", "z7", "z8", "z9", "z10", 582 "z11", "z12", "z13", "z14", "z15", "z16", "z17", "z18", "z19", "z20", "z21", 583 "z22", "z23", "z24", "z25", "z26", "z27", "z28", "z29", "z30", "z31", 584 585 // SVE predicate registers 586 "p0", "p1", "p2", "p3", "p4", "p5", "p6", "p7", "p8", "p9", "p10", 587 "p11", "p12", "p13", "p14", "p15" 588 }; 589 590 ArrayRef<const char *> AArch64TargetInfo::getGCCRegNames() const { 591 return llvm::makeArrayRef(GCCRegNames); 592 } 593 594 const TargetInfo::GCCRegAlias AArch64TargetInfo::GCCRegAliases[] = { 595 {{"w31"}, "wsp"}, 596 {{"x31"}, "sp"}, 597 // GCC rN registers are aliases of xN registers. 598 {{"r0"}, "x0"}, 599 {{"r1"}, "x1"}, 600 {{"r2"}, "x2"}, 601 {{"r3"}, "x3"}, 602 {{"r4"}, "x4"}, 603 {{"r5"}, "x5"}, 604 {{"r6"}, "x6"}, 605 {{"r7"}, "x7"}, 606 {{"r8"}, "x8"}, 607 {{"r9"}, "x9"}, 608 {{"r10"}, "x10"}, 609 {{"r11"}, "x11"}, 610 {{"r12"}, "x12"}, 611 {{"r13"}, "x13"}, 612 {{"r14"}, "x14"}, 613 {{"r15"}, "x15"}, 614 {{"r16"}, "x16"}, 615 {{"r17"}, "x17"}, 616 {{"r18"}, "x18"}, 617 {{"r19"}, "x19"}, 618 {{"r20"}, "x20"}, 619 {{"r21"}, "x21"}, 620 {{"r22"}, "x22"}, 621 {{"r23"}, "x23"}, 622 {{"r24"}, "x24"}, 623 {{"r25"}, "x25"}, 624 {{"r26"}, "x26"}, 625 {{"r27"}, "x27"}, 626 {{"r28"}, "x28"}, 627 {{"r29", "x29"}, "fp"}, 628 {{"r30", "x30"}, "lr"}, 629 // The S/D/Q and W/X registers overlap, but aren't really aliases; we 630 // don't want to substitute one of these for a different-sized one. 631 }; 632 633 ArrayRef<TargetInfo::GCCRegAlias> AArch64TargetInfo::getGCCRegAliases() const { 634 return llvm::makeArrayRef(GCCRegAliases); 635 } 636 637 bool AArch64TargetInfo::validateAsmConstraint( 638 const char *&Name, TargetInfo::ConstraintInfo &Info) const { 639 switch (*Name) { 640 default: 641 return false; 642 case 'w': // Floating point and SIMD registers (V0-V31) 643 Info.setAllowsRegister(); 644 return true; 645 case 'I': // Constant that can be used with an ADD instruction 646 case 'J': // Constant that can be used with a SUB instruction 647 case 'K': // Constant that can be used with a 32-bit logical instruction 648 case 'L': // Constant that can be used with a 64-bit logical instruction 649 case 'M': // Constant that can be used as a 32-bit MOV immediate 650 case 'N': // Constant that can be used as a 64-bit MOV immediate 651 case 'Y': // Floating point constant zero 652 case 'Z': // Integer constant zero 653 return true; 654 case 'Q': // A memory reference with base register and no offset 655 Info.setAllowsMemory(); 656 return true; 657 case 'S': // A symbolic address 658 Info.setAllowsRegister(); 659 return true; 660 case 'U': 661 if (Name[1] == 'p' && (Name[2] == 'l' || Name[2] == 'a')) { 662 // SVE predicate registers ("Upa"=P0-15, "Upl"=P0-P7) 663 Info.setAllowsRegister(); 664 Name += 2; 665 return true; 666 } 667 // Ump: A memory address suitable for ldp/stp in SI, DI, SF and DF modes. 668 // Utf: A memory address suitable for ldp/stp in TF mode. 669 // Usa: An absolute symbolic address. 670 // Ush: The high part (bits 32:12) of a pc-relative symbolic address. 671 672 // Better to return an error saying that it's an unrecognised constraint 673 // even if this is a valid constraint in gcc. 674 return false; 675 case 'z': // Zero register, wzr or xzr 676 Info.setAllowsRegister(); 677 return true; 678 case 'x': // Floating point and SIMD registers (V0-V15) 679 Info.setAllowsRegister(); 680 return true; 681 case 'y': // SVE registers (V0-V7) 682 Info.setAllowsRegister(); 683 return true; 684 } 685 return false; 686 } 687 688 bool AArch64TargetInfo::validateConstraintModifier( 689 StringRef Constraint, char Modifier, unsigned Size, 690 std::string &SuggestedModifier) const { 691 // Strip off constraint modifiers. 692 while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&') 693 Constraint = Constraint.substr(1); 694 695 switch (Constraint[0]) { 696 default: 697 return true; 698 case 'z': 699 case 'r': { 700 switch (Modifier) { 701 case 'x': 702 case 'w': 703 // For now assume that the person knows what they're 704 // doing with the modifier. 705 return true; 706 default: 707 // By default an 'r' constraint will be in the 'x' 708 // registers. 709 if (Size == 64) 710 return true; 711 712 SuggestedModifier = "w"; 713 return false; 714 } 715 } 716 } 717 } 718 719 const char *AArch64TargetInfo::getClobbers() const { return ""; } 720 721 int AArch64TargetInfo::getEHDataRegisterNumber(unsigned RegNo) const { 722 if (RegNo == 0) 723 return 0; 724 if (RegNo == 1) 725 return 1; 726 return -1; 727 } 728 729 bool AArch64TargetInfo::hasInt128Type() const { return true; } 730 731 AArch64leTargetInfo::AArch64leTargetInfo(const llvm::Triple &Triple, 732 const TargetOptions &Opts) 733 : AArch64TargetInfo(Triple, Opts) {} 734 735 void AArch64leTargetInfo::setDataLayout() { 736 if (getTriple().isOSBinFormatMachO()) { 737 if(getTriple().isArch32Bit()) 738 resetDataLayout("e-m:o-p:32:32-i64:64-i128:128-n32:64-S128"); 739 else 740 resetDataLayout("e-m:o-i64:64-i128:128-n32:64-S128"); 741 } else 742 resetDataLayout("e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"); 743 } 744 745 void AArch64leTargetInfo::getTargetDefines(const LangOptions &Opts, 746 MacroBuilder &Builder) const { 747 Builder.defineMacro("__AARCH64EL__"); 748 AArch64TargetInfo::getTargetDefines(Opts, Builder); 749 } 750 751 AArch64beTargetInfo::AArch64beTargetInfo(const llvm::Triple &Triple, 752 const TargetOptions &Opts) 753 : AArch64TargetInfo(Triple, Opts) {} 754 755 void AArch64beTargetInfo::getTargetDefines(const LangOptions &Opts, 756 MacroBuilder &Builder) const { 757 Builder.defineMacro("__AARCH64EB__"); 758 Builder.defineMacro("__AARCH_BIG_ENDIAN"); 759 Builder.defineMacro("__ARM_BIG_ENDIAN"); 760 AArch64TargetInfo::getTargetDefines(Opts, Builder); 761 } 762 763 void AArch64beTargetInfo::setDataLayout() { 764 assert(!getTriple().isOSBinFormatMachO()); 765 resetDataLayout("E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"); 766 } 767 768 WindowsARM64TargetInfo::WindowsARM64TargetInfo(const llvm::Triple &Triple, 769 const TargetOptions &Opts) 770 : WindowsTargetInfo<AArch64leTargetInfo>(Triple, Opts), Triple(Triple) { 771 772 // This is an LLP64 platform. 773 // int:4, long:4, long long:8, long double:8. 774 IntWidth = IntAlign = 32; 775 LongWidth = LongAlign = 32; 776 DoubleAlign = LongLongAlign = 64; 777 LongDoubleWidth = LongDoubleAlign = 64; 778 LongDoubleFormat = &llvm::APFloat::IEEEdouble(); 779 IntMaxType = SignedLongLong; 780 Int64Type = SignedLongLong; 781 SizeType = UnsignedLongLong; 782 PtrDiffType = SignedLongLong; 783 IntPtrType = SignedLongLong; 784 } 785 786 void WindowsARM64TargetInfo::setDataLayout() { 787 resetDataLayout(Triple.isOSBinFormatMachO() 788 ? "e-m:o-i64:64-i128:128-n32:64-S128" 789 : "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128"); 790 } 791 792 TargetInfo::BuiltinVaListKind 793 WindowsARM64TargetInfo::getBuiltinVaListKind() const { 794 return TargetInfo::CharPtrBuiltinVaList; 795 } 796 797 TargetInfo::CallingConvCheckResult 798 WindowsARM64TargetInfo::checkCallingConvention(CallingConv CC) const { 799 switch (CC) { 800 case CC_X86StdCall: 801 case CC_X86ThisCall: 802 case CC_X86FastCall: 803 case CC_X86VectorCall: 804 return CCCR_Ignore; 805 case CC_C: 806 case CC_OpenCLKernel: 807 case CC_PreserveMost: 808 case CC_PreserveAll: 809 case CC_Swift: 810 case CC_Win64: 811 return CCCR_OK; 812 default: 813 return CCCR_Warning; 814 } 815 } 816 817 MicrosoftARM64TargetInfo::MicrosoftARM64TargetInfo(const llvm::Triple &Triple, 818 const TargetOptions &Opts) 819 : WindowsARM64TargetInfo(Triple, Opts) { 820 TheCXXABI.set(TargetCXXABI::Microsoft); 821 } 822 823 void MicrosoftARM64TargetInfo::getTargetDefines(const LangOptions &Opts, 824 MacroBuilder &Builder) const { 825 WindowsARM64TargetInfo::getTargetDefines(Opts, Builder); 826 Builder.defineMacro("_M_ARM64", "1"); 827 } 828 829 TargetInfo::CallingConvKind 830 MicrosoftARM64TargetInfo::getCallingConvKind(bool ClangABICompat4) const { 831 return CCK_MicrosoftWin64; 832 } 833 834 unsigned MicrosoftARM64TargetInfo::getMinGlobalAlign(uint64_t TypeSize) const { 835 unsigned Align = WindowsARM64TargetInfo::getMinGlobalAlign(TypeSize); 836 837 // MSVC does size based alignment for arm64 based on alignment section in 838 // below document, replicate that to keep alignment consistent with object 839 // files compiled by MSVC. 840 // https://docs.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions 841 if (TypeSize >= 512) { // TypeSize >= 64 bytes 842 Align = std::max(Align, 128u); // align type at least 16 bytes 843 } else if (TypeSize >= 64) { // TypeSize >= 8 bytes 844 Align = std::max(Align, 64u); // align type at least 8 butes 845 } else if (TypeSize >= 16) { // TypeSize >= 2 bytes 846 Align = std::max(Align, 32u); // align type at least 4 bytes 847 } 848 return Align; 849 } 850 851 MinGWARM64TargetInfo::MinGWARM64TargetInfo(const llvm::Triple &Triple, 852 const TargetOptions &Opts) 853 : WindowsARM64TargetInfo(Triple, Opts) { 854 TheCXXABI.set(TargetCXXABI::GenericAArch64); 855 } 856 857 DarwinAArch64TargetInfo::DarwinAArch64TargetInfo(const llvm::Triple &Triple, 858 const TargetOptions &Opts) 859 : DarwinTargetInfo<AArch64leTargetInfo>(Triple, Opts) { 860 Int64Type = SignedLongLong; 861 if (getTriple().isArch32Bit()) 862 IntMaxType = SignedLongLong; 863 864 WCharType = SignedInt; 865 UseSignedCharForObjCBool = false; 866 867 LongDoubleWidth = LongDoubleAlign = SuitableAlign = 64; 868 LongDoubleFormat = &llvm::APFloat::IEEEdouble(); 869 870 UseZeroLengthBitfieldAlignment = false; 871 872 if (getTriple().isArch32Bit()) { 873 UseBitFieldTypeAlignment = false; 874 ZeroLengthBitfieldBoundary = 32; 875 UseZeroLengthBitfieldAlignment = true; 876 TheCXXABI.set(TargetCXXABI::WatchOS); 877 } else 878 TheCXXABI.set(TargetCXXABI::AppleARM64); 879 } 880 881 void DarwinAArch64TargetInfo::getOSDefines(const LangOptions &Opts, 882 const llvm::Triple &Triple, 883 MacroBuilder &Builder) const { 884 Builder.defineMacro("__AARCH64_SIMD__"); 885 if (Triple.isArch32Bit()) 886 Builder.defineMacro("__ARM64_ARCH_8_32__"); 887 else 888 Builder.defineMacro("__ARM64_ARCH_8__"); 889 Builder.defineMacro("__ARM_NEON__"); 890 Builder.defineMacro("__LITTLE_ENDIAN__"); 891 Builder.defineMacro("__REGISTER_PREFIX__", ""); 892 Builder.defineMacro("__arm64", "1"); 893 Builder.defineMacro("__arm64__", "1"); 894 895 if (Triple.isArm64e()) 896 Builder.defineMacro("__arm64e__", "1"); 897 898 getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion); 899 } 900 901 TargetInfo::BuiltinVaListKind 902 DarwinAArch64TargetInfo::getBuiltinVaListKind() const { 903 return TargetInfo::CharPtrBuiltinVaList; 904 } 905 906 // 64-bit RenderScript is aarch64 907 RenderScript64TargetInfo::RenderScript64TargetInfo(const llvm::Triple &Triple, 908 const TargetOptions &Opts) 909 : AArch64leTargetInfo(llvm::Triple("aarch64", Triple.getVendorName(), 910 Triple.getOSName(), 911 Triple.getEnvironmentName()), 912 Opts) { 913 IsRenderScriptTarget = true; 914 } 915 916 void RenderScript64TargetInfo::getTargetDefines(const LangOptions &Opts, 917 MacroBuilder &Builder) const { 918 Builder.defineMacro("__RENDERSCRIPT__"); 919 AArch64leTargetInfo::getTargetDefines(Opts, Builder); 920 } 921