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 (HasCRC) 200 Builder.defineMacro("__ARM_FEATURE_CRC32", "1"); 201 202 if (HasCrypto) 203 Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1"); 204 205 if (HasUnaligned) 206 Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1"); 207 208 if ((FPU & NeonMode) && HasFullFP16) 209 Builder.defineMacro("__ARM_FEATURE_FP16_VECTOR_ARITHMETIC", "1"); 210 if (HasFullFP16) 211 Builder.defineMacro("__ARM_FEATURE_FP16_SCALAR_ARITHMETIC", "1"); 212 213 if (HasDotProd) 214 Builder.defineMacro("__ARM_FEATURE_DOTPROD", "1"); 215 216 if (HasMTE) 217 Builder.defineMacro("__ARM_FEATURE_MEMORY_TAGGING", "1"); 218 219 if ((FPU & NeonMode) && HasFP16FML) 220 Builder.defineMacro("__ARM_FEATURE_FP16FML", "1"); 221 222 switch (ArchKind) { 223 default: 224 break; 225 case llvm::AArch64::ArchKind::ARMV8_1A: 226 getTargetDefinesARMV81A(Opts, Builder); 227 break; 228 case llvm::AArch64::ArchKind::ARMV8_2A: 229 getTargetDefinesARMV82A(Opts, Builder); 230 break; 231 case llvm::AArch64::ArchKind::ARMV8_3A: 232 getTargetDefinesARMV83A(Opts, Builder); 233 break; 234 case llvm::AArch64::ArchKind::ARMV8_4A: 235 getTargetDefinesARMV84A(Opts, Builder); 236 break; 237 case llvm::AArch64::ArchKind::ARMV8_5A: 238 getTargetDefinesARMV85A(Opts, Builder); 239 break; 240 } 241 242 // All of the __sync_(bool|val)_compare_and_swap_(1|2|4|8) builtins work. 243 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1"); 244 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2"); 245 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4"); 246 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8"); 247 } 248 249 ArrayRef<Builtin::Info> AArch64TargetInfo::getTargetBuiltins() const { 250 return llvm::makeArrayRef(BuiltinInfo, clang::AArch64::LastTSBuiltin - 251 Builtin::FirstTSBuiltin); 252 } 253 254 bool AArch64TargetInfo::hasFeature(StringRef Feature) const { 255 return Feature == "aarch64" || Feature == "arm64" || Feature == "arm" || 256 (Feature == "neon" && (FPU & NeonMode)) || 257 (Feature == "sve" && (FPU & SveMode)); 258 } 259 260 bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features, 261 DiagnosticsEngine &Diags) { 262 FPU = FPUMode; 263 HasCRC = false; 264 HasCrypto = false; 265 HasUnaligned = true; 266 HasFullFP16 = false; 267 HasDotProd = false; 268 HasFP16FML = false; 269 HasMTE = false; 270 ArchKind = llvm::AArch64::ArchKind::ARMV8A; 271 272 for (const auto &Feature : Features) { 273 if (Feature == "+neon") 274 FPU |= NeonMode; 275 if (Feature == "+sve") 276 FPU |= SveMode; 277 if (Feature == "+crc") 278 HasCRC = true; 279 if (Feature == "+crypto") 280 HasCrypto = true; 281 if (Feature == "+strict-align") 282 HasUnaligned = false; 283 if (Feature == "+v8.1a") 284 ArchKind = llvm::AArch64::ArchKind::ARMV8_1A; 285 if (Feature == "+v8.2a") 286 ArchKind = llvm::AArch64::ArchKind::ARMV8_2A; 287 if (Feature == "+v8.3a") 288 ArchKind = llvm::AArch64::ArchKind::ARMV8_3A; 289 if (Feature == "+v8.4a") 290 ArchKind = llvm::AArch64::ArchKind::ARMV8_4A; 291 if (Feature == "+v8.5a") 292 ArchKind = llvm::AArch64::ArchKind::ARMV8_5A; 293 if (Feature == "+fullfp16") 294 HasFullFP16 = true; 295 if (Feature == "+dotprod") 296 HasDotProd = true; 297 if (Feature == "+fp16fml") 298 HasFP16FML = true; 299 if (Feature == "+mte") 300 HasMTE = true; 301 } 302 303 setDataLayout(); 304 305 return true; 306 } 307 308 TargetInfo::CallingConvCheckResult 309 AArch64TargetInfo::checkCallingConvention(CallingConv CC) const { 310 switch (CC) { 311 case CC_C: 312 case CC_Swift: 313 case CC_PreserveMost: 314 case CC_PreserveAll: 315 case CC_OpenCLKernel: 316 case CC_AArch64VectorCall: 317 case CC_Win64: 318 return CCCR_OK; 319 default: 320 return CCCR_Warning; 321 } 322 } 323 324 bool AArch64TargetInfo::isCLZForZeroUndef() const { return false; } 325 326 TargetInfo::BuiltinVaListKind AArch64TargetInfo::getBuiltinVaListKind() const { 327 return TargetInfo::AArch64ABIBuiltinVaList; 328 } 329 330 const char *const AArch64TargetInfo::GCCRegNames[] = { 331 // 32-bit Integer registers 332 "w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7", "w8", "w9", "w10", "w11", 333 "w12", "w13", "w14", "w15", "w16", "w17", "w18", "w19", "w20", "w21", "w22", 334 "w23", "w24", "w25", "w26", "w27", "w28", "w29", "w30", "wsp", 335 336 // 64-bit Integer registers 337 "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", 338 "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22", 339 "x23", "x24", "x25", "x26", "x27", "x28", "fp", "lr", "sp", 340 341 // 32-bit floating point regsisters 342 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", 343 "s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22", 344 "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31", 345 346 // 64-bit floating point regsisters 347 "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11", 348 "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19", "d20", "d21", "d22", 349 "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31", 350 351 // Neon vector registers 352 "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11", 353 "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", "v20", "v21", "v22", 354 "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31", 355 356 // SVE vector registers 357 "z0", "z1", "z2", "z3", "z4", "z5", "z6", "z7", "z8", "z9", "z10", 358 "z11", "z12", "z13", "z14", "z15", "z16", "z17", "z18", "z19", "z20", "z21", 359 "z22", "z23", "z24", "z25", "z26", "z27", "z28", "z29", "z30", "z31", 360 361 // SVE predicate registers 362 "p0", "p1", "p2", "p3", "p4", "p5", "p6", "p7", "p8", "p9", "p10", 363 "p11", "p12", "p13", "p14", "p15" 364 }; 365 366 ArrayRef<const char *> AArch64TargetInfo::getGCCRegNames() const { 367 return llvm::makeArrayRef(GCCRegNames); 368 } 369 370 const TargetInfo::GCCRegAlias AArch64TargetInfo::GCCRegAliases[] = { 371 {{"w31"}, "wsp"}, 372 {{"x31"}, "sp"}, 373 // GCC rN registers are aliases of xN registers. 374 {{"r0"}, "x0"}, 375 {{"r1"}, "x1"}, 376 {{"r2"}, "x2"}, 377 {{"r3"}, "x3"}, 378 {{"r4"}, "x4"}, 379 {{"r5"}, "x5"}, 380 {{"r6"}, "x6"}, 381 {{"r7"}, "x7"}, 382 {{"r8"}, "x8"}, 383 {{"r9"}, "x9"}, 384 {{"r10"}, "x10"}, 385 {{"r11"}, "x11"}, 386 {{"r12"}, "x12"}, 387 {{"r13"}, "x13"}, 388 {{"r14"}, "x14"}, 389 {{"r15"}, "x15"}, 390 {{"r16"}, "x16"}, 391 {{"r17"}, "x17"}, 392 {{"r18"}, "x18"}, 393 {{"r19"}, "x19"}, 394 {{"r20"}, "x20"}, 395 {{"r21"}, "x21"}, 396 {{"r22"}, "x22"}, 397 {{"r23"}, "x23"}, 398 {{"r24"}, "x24"}, 399 {{"r25"}, "x25"}, 400 {{"r26"}, "x26"}, 401 {{"r27"}, "x27"}, 402 {{"r28"}, "x28"}, 403 {{"r29", "x29"}, "fp"}, 404 {{"r30", "x30"}, "lr"}, 405 // The S/D/Q and W/X registers overlap, but aren't really aliases; we 406 // don't want to substitute one of these for a different-sized one. 407 }; 408 409 ArrayRef<TargetInfo::GCCRegAlias> AArch64TargetInfo::getGCCRegAliases() const { 410 return llvm::makeArrayRef(GCCRegAliases); 411 } 412 413 bool AArch64TargetInfo::validateAsmConstraint( 414 const char *&Name, TargetInfo::ConstraintInfo &Info) const { 415 switch (*Name) { 416 default: 417 return false; 418 case 'w': // Floating point and SIMD registers (V0-V31) 419 Info.setAllowsRegister(); 420 return true; 421 case 'I': // Constant that can be used with an ADD instruction 422 case 'J': // Constant that can be used with a SUB instruction 423 case 'K': // Constant that can be used with a 32-bit logical instruction 424 case 'L': // Constant that can be used with a 64-bit logical instruction 425 case 'M': // Constant that can be used as a 32-bit MOV immediate 426 case 'N': // Constant that can be used as a 64-bit MOV immediate 427 case 'Y': // Floating point constant zero 428 case 'Z': // Integer constant zero 429 return true; 430 case 'Q': // A memory reference with base register and no offset 431 Info.setAllowsMemory(); 432 return true; 433 case 'S': // A symbolic address 434 Info.setAllowsRegister(); 435 return true; 436 case 'U': 437 // Ump: A memory address suitable for ldp/stp in SI, DI, SF and DF modes. 438 // Utf: A memory address suitable for ldp/stp in TF mode. 439 // Usa: An absolute symbolic address. 440 // Ush: The high part (bits 32:12) of a pc-relative symbolic address. 441 llvm_unreachable("FIXME: Unimplemented support for U* constraints."); 442 case 'z': // Zero register, wzr or xzr 443 Info.setAllowsRegister(); 444 return true; 445 case 'x': // Floating point and SIMD registers (V0-V15) 446 Info.setAllowsRegister(); 447 return true; 448 } 449 return false; 450 } 451 452 bool AArch64TargetInfo::validateConstraintModifier( 453 StringRef Constraint, char Modifier, unsigned Size, 454 std::string &SuggestedModifier) const { 455 // Strip off constraint modifiers. 456 while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&') 457 Constraint = Constraint.substr(1); 458 459 switch (Constraint[0]) { 460 default: 461 return true; 462 case 'z': 463 case 'r': { 464 switch (Modifier) { 465 case 'x': 466 case 'w': 467 // For now assume that the person knows what they're 468 // doing with the modifier. 469 return true; 470 default: 471 // By default an 'r' constraint will be in the 'x' 472 // registers. 473 if (Size == 64) 474 return true; 475 476 SuggestedModifier = "w"; 477 return false; 478 } 479 } 480 } 481 } 482 483 const char *AArch64TargetInfo::getClobbers() const { return ""; } 484 485 int AArch64TargetInfo::getEHDataRegisterNumber(unsigned RegNo) const { 486 if (RegNo == 0) 487 return 0; 488 if (RegNo == 1) 489 return 1; 490 return -1; 491 } 492 493 AArch64leTargetInfo::AArch64leTargetInfo(const llvm::Triple &Triple, 494 const TargetOptions &Opts) 495 : AArch64TargetInfo(Triple, Opts) {} 496 497 void AArch64leTargetInfo::setDataLayout() { 498 if (getTriple().isOSBinFormatMachO()) 499 resetDataLayout("e-m:o-i64:64-i128:128-n32:64-S128"); 500 else 501 resetDataLayout("e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"); 502 } 503 504 void AArch64leTargetInfo::getTargetDefines(const LangOptions &Opts, 505 MacroBuilder &Builder) const { 506 Builder.defineMacro("__AARCH64EL__"); 507 AArch64TargetInfo::getTargetDefines(Opts, Builder); 508 } 509 510 AArch64beTargetInfo::AArch64beTargetInfo(const llvm::Triple &Triple, 511 const TargetOptions &Opts) 512 : AArch64TargetInfo(Triple, Opts) {} 513 514 void AArch64beTargetInfo::getTargetDefines(const LangOptions &Opts, 515 MacroBuilder &Builder) const { 516 Builder.defineMacro("__AARCH64EB__"); 517 Builder.defineMacro("__AARCH_BIG_ENDIAN"); 518 Builder.defineMacro("__ARM_BIG_ENDIAN"); 519 AArch64TargetInfo::getTargetDefines(Opts, Builder); 520 } 521 522 void AArch64beTargetInfo::setDataLayout() { 523 assert(!getTriple().isOSBinFormatMachO()); 524 resetDataLayout("E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"); 525 } 526 527 WindowsARM64TargetInfo::WindowsARM64TargetInfo(const llvm::Triple &Triple, 528 const TargetOptions &Opts) 529 : WindowsTargetInfo<AArch64leTargetInfo>(Triple, Opts), Triple(Triple) { 530 531 // This is an LLP64 platform. 532 // int:4, long:4, long long:8, long double:8. 533 IntWidth = IntAlign = 32; 534 LongWidth = LongAlign = 32; 535 DoubleAlign = LongLongAlign = 64; 536 LongDoubleWidth = LongDoubleAlign = 64; 537 LongDoubleFormat = &llvm::APFloat::IEEEdouble(); 538 IntMaxType = SignedLongLong; 539 Int64Type = SignedLongLong; 540 SizeType = UnsignedLongLong; 541 PtrDiffType = SignedLongLong; 542 IntPtrType = SignedLongLong; 543 } 544 545 void WindowsARM64TargetInfo::setDataLayout() { 546 resetDataLayout("e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128"); 547 } 548 549 TargetInfo::BuiltinVaListKind 550 WindowsARM64TargetInfo::getBuiltinVaListKind() const { 551 return TargetInfo::CharPtrBuiltinVaList; 552 } 553 554 TargetInfo::CallingConvCheckResult 555 WindowsARM64TargetInfo::checkCallingConvention(CallingConv CC) const { 556 switch (CC) { 557 case CC_X86StdCall: 558 case CC_X86ThisCall: 559 case CC_X86FastCall: 560 case CC_X86VectorCall: 561 return CCCR_Ignore; 562 case CC_C: 563 case CC_OpenCLKernel: 564 case CC_PreserveMost: 565 case CC_PreserveAll: 566 case CC_Swift: 567 case CC_Win64: 568 return CCCR_OK; 569 default: 570 return CCCR_Warning; 571 } 572 } 573 574 MicrosoftARM64TargetInfo::MicrosoftARM64TargetInfo(const llvm::Triple &Triple, 575 const TargetOptions &Opts) 576 : WindowsARM64TargetInfo(Triple, Opts) { 577 TheCXXABI.set(TargetCXXABI::Microsoft); 578 } 579 580 void MicrosoftARM64TargetInfo::getTargetDefines(const LangOptions &Opts, 581 MacroBuilder &Builder) const { 582 WindowsARM64TargetInfo::getTargetDefines(Opts, Builder); 583 Builder.defineMacro("_M_ARM64", "1"); 584 } 585 586 TargetInfo::CallingConvKind 587 MicrosoftARM64TargetInfo::getCallingConvKind(bool ClangABICompat4) const { 588 return CCK_MicrosoftWin64; 589 } 590 591 unsigned MicrosoftARM64TargetInfo::getMinGlobalAlign(uint64_t TypeSize) const { 592 unsigned Align = WindowsARM64TargetInfo::getMinGlobalAlign(TypeSize); 593 594 // MSVC does size based alignment for arm64 based on alignment section in 595 // below document, replicate that to keep alignment consistent with object 596 // files compiled by MSVC. 597 // https://docs.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions 598 if (TypeSize >= 512) { // TypeSize >= 64 bytes 599 Align = std::max(Align, 128u); // align type at least 16 bytes 600 } else if (TypeSize >= 64) { // TypeSize >= 8 bytes 601 Align = std::max(Align, 64u); // align type at least 8 butes 602 } else if (TypeSize >= 16) { // TypeSize >= 2 bytes 603 Align = std::max(Align, 32u); // align type at least 4 bytes 604 } 605 return Align; 606 } 607 608 MinGWARM64TargetInfo::MinGWARM64TargetInfo(const llvm::Triple &Triple, 609 const TargetOptions &Opts) 610 : WindowsARM64TargetInfo(Triple, Opts) { 611 TheCXXABI.set(TargetCXXABI::GenericAArch64); 612 } 613 614 DarwinAArch64TargetInfo::DarwinAArch64TargetInfo(const llvm::Triple &Triple, 615 const TargetOptions &Opts) 616 : DarwinTargetInfo<AArch64leTargetInfo>(Triple, Opts) { 617 Int64Type = SignedLongLong; 618 UseSignedCharForObjCBool = false; 619 620 LongDoubleWidth = LongDoubleAlign = SuitableAlign = 64; 621 LongDoubleFormat = &llvm::APFloat::IEEEdouble(); 622 623 TheCXXABI.set(TargetCXXABI::iOS64); 624 } 625 626 void DarwinAArch64TargetInfo::getOSDefines(const LangOptions &Opts, 627 const llvm::Triple &Triple, 628 MacroBuilder &Builder) const { 629 Builder.defineMacro("__AARCH64_SIMD__"); 630 Builder.defineMacro("__ARM64_ARCH_8__"); 631 Builder.defineMacro("__ARM_NEON__"); 632 Builder.defineMacro("__LITTLE_ENDIAN__"); 633 Builder.defineMacro("__REGISTER_PREFIX__", ""); 634 Builder.defineMacro("__arm64", "1"); 635 Builder.defineMacro("__arm64__", "1"); 636 637 getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion); 638 } 639 640 TargetInfo::BuiltinVaListKind 641 DarwinAArch64TargetInfo::getBuiltinVaListKind() const { 642 return TargetInfo::CharPtrBuiltinVaList; 643 } 644 645 // 64-bit RenderScript is aarch64 646 RenderScript64TargetInfo::RenderScript64TargetInfo(const llvm::Triple &Triple, 647 const TargetOptions &Opts) 648 : AArch64leTargetInfo(llvm::Triple("aarch64", Triple.getVendorName(), 649 Triple.getOSName(), 650 Triple.getEnvironmentName()), 651 Opts) { 652 IsRenderScriptTarget = true; 653 } 654 655 void RenderScript64TargetInfo::getTargetDefines(const LangOptions &Opts, 656 MacroBuilder &Builder) const { 657 Builder.defineMacro("__RENDERSCRIPT__"); 658 AArch64leTargetInfo::getTargetDefines(Opts, Builder); 659 } 660