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