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