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