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