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