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