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