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