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