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