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