1 //===--- AArch64.cpp - Implement AArch64 target feature support -----------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file implements AArch64 TargetInfo objects. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "AArch64.h" 15 #include "clang/Basic/TargetBuiltins.h" 16 #include "clang/Basic/TargetInfo.h" 17 #include "llvm/ADT/ArrayRef.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 #include "clang/Basic/BuiltinsAArch64.def" 30 }; 31 32 AArch64TargetInfo::AArch64TargetInfo(const llvm::Triple &Triple, 33 const TargetOptions &Opts) 34 : TargetInfo(Triple), ABI("aapcs") { 35 if (getTriple().getOS() == llvm::Triple::NetBSD || 36 getTriple().getOS() == llvm::Triple::OpenBSD) { 37 WCharType = SignedInt; 38 39 // NetBSD apparently prefers consistency across ARM targets to 40 // consistency across 64-bit targets. 41 Int64Type = SignedLongLong; 42 IntMaxType = SignedLongLong; 43 } else { 44 WCharType = UnsignedInt; 45 Int64Type = SignedLong; 46 IntMaxType = SignedLong; 47 } 48 49 LongWidth = LongAlign = PointerWidth = PointerAlign = 64; 50 MaxVectorAlign = 128; 51 MaxAtomicInlineWidth = 128; 52 MaxAtomicPromoteWidth = 128; 53 54 LongDoubleWidth = LongDoubleAlign = SuitableAlign = 128; 55 LongDoubleFormat = &llvm::APFloat::IEEEquad(); 56 57 // Make __builtin_ms_va_list available. 58 HasBuiltinMSVaList = true; 59 60 // {} in inline assembly are neon specifiers, not assembly variant 61 // specifiers. 62 NoAsmVariants = true; 63 64 // AAPCS gives rules for bitfields. 7.1.7 says: "The container type 65 // contributes to the alignment of the containing aggregate in the same way 66 // a plain (non bit-field) member of that type would, without exception for 67 // zero-sized or anonymous bit-fields." 68 assert(UseBitFieldTypeAlignment && "bitfields affect type alignment"); 69 UseZeroLengthBitfieldAlignment = true; 70 71 // AArch64 targets default to using the ARM C++ ABI. 72 TheCXXABI.set(TargetCXXABI::GenericAArch64); 73 74 if (Triple.getOS() == llvm::Triple::Linux) 75 this->MCountName = "\01_mcount"; 76 else if (Triple.getOS() == llvm::Triple::UnknownOS) 77 this->MCountName = 78 Opts.EABIVersion == llvm::EABI::GNU ? "\01_mcount" : "mcount"; 79 } 80 81 StringRef AArch64TargetInfo::getABI() const { return ABI; } 82 83 bool AArch64TargetInfo::setABI(const std::string &Name) { 84 if (Name != "aapcs" && Name != "darwinpcs") 85 return false; 86 87 ABI = Name; 88 return true; 89 } 90 91 bool AArch64TargetInfo::isValidCPUName(StringRef Name) const { 92 return Name == "generic" || 93 llvm::AArch64::parseCPUArch(Name) != llvm::AArch64::ArchKind::INVALID; 94 } 95 96 bool AArch64TargetInfo::setCPU(const std::string &Name) { 97 return isValidCPUName(Name); 98 } 99 100 void AArch64TargetInfo::getTargetDefinesARMV81A(const LangOptions &Opts, 101 MacroBuilder &Builder) const { 102 Builder.defineMacro("__ARM_FEATURE_QRDMX", "1"); 103 } 104 105 void AArch64TargetInfo::getTargetDefinesARMV82A(const LangOptions &Opts, 106 MacroBuilder &Builder) const { 107 // Also include the ARMv8.1 defines 108 getTargetDefinesARMV81A(Opts, Builder); 109 } 110 111 void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts, 112 MacroBuilder &Builder) const { 113 // Target identification. 114 Builder.defineMacro("__aarch64__"); 115 // For bare-metal none-eabi. 116 if (getTriple().getOS() == llvm::Triple::UnknownOS && 117 (getTriple().getEnvironment() == llvm::Triple::EABI || 118 getTriple().getEnvironment() == llvm::Triple::EABIHF)) 119 Builder.defineMacro("__ELF__"); 120 121 // Target properties. 122 if (!getTriple().isOSWindows()) { 123 Builder.defineMacro("_LP64"); 124 Builder.defineMacro("__LP64__"); 125 } 126 127 // ACLE predefines. Many can only have one possible value on v8 AArch64. 128 Builder.defineMacro("__ARM_ACLE", "200"); 129 Builder.defineMacro("__ARM_ARCH", "8"); 130 Builder.defineMacro("__ARM_ARCH_PROFILE", "'A'"); 131 132 Builder.defineMacro("__ARM_64BIT_STATE", "1"); 133 Builder.defineMacro("__ARM_PCS_AAPCS64", "1"); 134 Builder.defineMacro("__ARM_ARCH_ISA_A64", "1"); 135 136 Builder.defineMacro("__ARM_FEATURE_CLZ", "1"); 137 Builder.defineMacro("__ARM_FEATURE_FMA", "1"); 138 Builder.defineMacro("__ARM_FEATURE_LDREX", "0xF"); 139 Builder.defineMacro("__ARM_FEATURE_IDIV", "1"); // As specified in ACLE 140 Builder.defineMacro("__ARM_FEATURE_DIV"); // For backwards compatibility 141 Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN", "1"); 142 Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING", "1"); 143 144 Builder.defineMacro("__ARM_ALIGN_MAX_STACK_PWR", "4"); 145 146 // 0xe implies support for half, single and double precision operations. 147 Builder.defineMacro("__ARM_FP", "0xE"); 148 149 // PCS specifies this for SysV variants, which is all we support. Other ABIs 150 // may choose __ARM_FP16_FORMAT_ALTERNATIVE. 151 Builder.defineMacro("__ARM_FP16_FORMAT_IEEE", "1"); 152 Builder.defineMacro("__ARM_FP16_ARGS", "1"); 153 154 if (Opts.UnsafeFPMath) 155 Builder.defineMacro("__ARM_FP_FAST", "1"); 156 157 Builder.defineMacro("__ARM_SIZEOF_WCHAR_T", Opts.ShortWChar ? "2" : "4"); 158 159 Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM", Opts.ShortEnums ? "1" : "4"); 160 161 if (FPU & NeonMode) { 162 Builder.defineMacro("__ARM_NEON", "1"); 163 // 64-bit NEON supports half, single and double precision operations. 164 Builder.defineMacro("__ARM_NEON_FP", "0xE"); 165 } 166 167 if (FPU & SveMode) 168 Builder.defineMacro("__ARM_FEATURE_SVE", "1"); 169 170 if (CRC) 171 Builder.defineMacro("__ARM_FEATURE_CRC32", "1"); 172 173 if (Crypto) 174 Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1"); 175 176 if (Unaligned) 177 Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1"); 178 179 switch (ArchKind) { 180 default: 181 break; 182 case llvm::AArch64::ArchKind::ARMV8_1A: 183 getTargetDefinesARMV81A(Opts, Builder); 184 break; 185 case llvm::AArch64::ArchKind::ARMV8_2A: 186 getTargetDefinesARMV82A(Opts, Builder); 187 break; 188 } 189 190 // All of the __sync_(bool|val)_compare_and_swap_(1|2|4|8) builtins work. 191 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1"); 192 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2"); 193 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4"); 194 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8"); 195 } 196 197 ArrayRef<Builtin::Info> AArch64TargetInfo::getTargetBuiltins() const { 198 return llvm::makeArrayRef(BuiltinInfo, clang::AArch64::LastTSBuiltin - 199 Builtin::FirstTSBuiltin); 200 } 201 202 bool AArch64TargetInfo::hasFeature(StringRef Feature) const { 203 return Feature == "aarch64" || Feature == "arm64" || Feature == "arm" || 204 (Feature == "neon" && (FPU & NeonMode)) || 205 (Feature == "sve" && (FPU & SveMode)); 206 } 207 208 bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features, 209 DiagnosticsEngine &Diags) { 210 FPU = FPUMode; 211 CRC = 0; 212 Crypto = 0; 213 Unaligned = 1; 214 HasFullFP16 = 0; 215 ArchKind = llvm::AArch64::ArchKind::ARMV8A; 216 217 for (const auto &Feature : Features) { 218 if (Feature == "+neon") 219 FPU |= NeonMode; 220 if (Feature == "+sve") 221 FPU |= SveMode; 222 if (Feature == "+crc") 223 CRC = 1; 224 if (Feature == "+crypto") 225 Crypto = 1; 226 if (Feature == "+strict-align") 227 Unaligned = 0; 228 if (Feature == "+v8.1a") 229 ArchKind = llvm::AArch64::ArchKind::ARMV8_1A; 230 if (Feature == "+v8.2a") 231 ArchKind = llvm::AArch64::ArchKind::ARMV8_2A; 232 if (Feature == "+fullfp16") 233 HasFullFP16 = 1; 234 } 235 236 setDataLayout(); 237 238 return true; 239 } 240 241 TargetInfo::CallingConvCheckResult 242 AArch64TargetInfo::checkCallingConvention(CallingConv CC) const { 243 switch (CC) { 244 case CC_C: 245 case CC_Swift: 246 case CC_PreserveMost: 247 case CC_PreserveAll: 248 case CC_OpenCLKernel: 249 case CC_Win64: 250 return CCCR_OK; 251 default: 252 return CCCR_Warning; 253 } 254 } 255 256 bool AArch64TargetInfo::isCLZForZeroUndef() const { return false; } 257 258 TargetInfo::BuiltinVaListKind AArch64TargetInfo::getBuiltinVaListKind() const { 259 return TargetInfo::AArch64ABIBuiltinVaList; 260 } 261 262 const char *const AArch64TargetInfo::GCCRegNames[] = { 263 // 32-bit Integer registers 264 "w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7", "w8", "w9", "w10", "w11", 265 "w12", "w13", "w14", "w15", "w16", "w17", "w18", "w19", "w20", "w21", "w22", 266 "w23", "w24", "w25", "w26", "w27", "w28", "w29", "w30", "wsp", 267 268 // 64-bit Integer registers 269 "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", 270 "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22", 271 "x23", "x24", "x25", "x26", "x27", "x28", "fp", "lr", "sp", 272 273 // 32-bit floating point regsisters 274 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", 275 "s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22", 276 "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31", 277 278 // 64-bit floating point regsisters 279 "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11", 280 "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19", "d20", "d21", "d22", 281 "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31", 282 283 // Vector registers 284 "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11", 285 "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", "v20", "v21", "v22", 286 "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31" 287 }; 288 289 ArrayRef<const char *> AArch64TargetInfo::getGCCRegNames() const { 290 return llvm::makeArrayRef(GCCRegNames); 291 } 292 293 const TargetInfo::GCCRegAlias AArch64TargetInfo::GCCRegAliases[] = { 294 {{"w31"}, "wsp"}, {{"x29"}, "fp"}, {{"x30"}, "lr"}, {{"x31"}, "sp"}, 295 // The S/D/Q and W/X registers overlap, but aren't really aliases; we 296 // don't want to substitute one of these for a different-sized one. 297 }; 298 299 ArrayRef<TargetInfo::GCCRegAlias> AArch64TargetInfo::getGCCRegAliases() const { 300 return llvm::makeArrayRef(GCCRegAliases); 301 } 302 303 bool AArch64TargetInfo::validateAsmConstraint( 304 const char *&Name, TargetInfo::ConstraintInfo &Info) const { 305 switch (*Name) { 306 default: 307 return false; 308 case 'w': // Floating point and SIMD registers (V0-V31) 309 Info.setAllowsRegister(); 310 return true; 311 case 'I': // Constant that can be used with an ADD instruction 312 case 'J': // Constant that can be used with a SUB instruction 313 case 'K': // Constant that can be used with a 32-bit logical instruction 314 case 'L': // Constant that can be used with a 64-bit logical instruction 315 case 'M': // Constant that can be used as a 32-bit MOV immediate 316 case 'N': // Constant that can be used as a 64-bit MOV immediate 317 case 'Y': // Floating point constant zero 318 case 'Z': // Integer constant zero 319 return true; 320 case 'Q': // A memory reference with base register and no offset 321 Info.setAllowsMemory(); 322 return true; 323 case 'S': // A symbolic address 324 Info.setAllowsRegister(); 325 return true; 326 case 'U': 327 // Ump: A memory address suitable for ldp/stp in SI, DI, SF and DF modes. 328 // Utf: A memory address suitable for ldp/stp in TF mode. 329 // Usa: An absolute symbolic address. 330 // Ush: The high part (bits 32:12) of a pc-relative symbolic address. 331 llvm_unreachable("FIXME: Unimplemented support for U* constraints."); 332 case 'z': // Zero register, wzr or xzr 333 Info.setAllowsRegister(); 334 return true; 335 case 'x': // Floating point and SIMD registers (V0-V15) 336 Info.setAllowsRegister(); 337 return true; 338 } 339 return false; 340 } 341 342 bool AArch64TargetInfo::validateConstraintModifier( 343 StringRef Constraint, char Modifier, unsigned Size, 344 std::string &SuggestedModifier) const { 345 // Strip off constraint modifiers. 346 while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&') 347 Constraint = Constraint.substr(1); 348 349 switch (Constraint[0]) { 350 default: 351 return true; 352 case 'z': 353 case 'r': { 354 switch (Modifier) { 355 case 'x': 356 case 'w': 357 // For now assume that the person knows what they're 358 // doing with the modifier. 359 return true; 360 default: 361 // By default an 'r' constraint will be in the 'x' 362 // registers. 363 if (Size == 64) 364 return true; 365 366 SuggestedModifier = "w"; 367 return false; 368 } 369 } 370 } 371 } 372 373 const char *AArch64TargetInfo::getClobbers() const { return ""; } 374 375 int AArch64TargetInfo::getEHDataRegisterNumber(unsigned RegNo) const { 376 if (RegNo == 0) 377 return 0; 378 if (RegNo == 1) 379 return 1; 380 return -1; 381 } 382 383 AArch64leTargetInfo::AArch64leTargetInfo(const llvm::Triple &Triple, 384 const TargetOptions &Opts) 385 : AArch64TargetInfo(Triple, Opts) {} 386 387 void AArch64leTargetInfo::setDataLayout() { 388 if (getTriple().isOSBinFormatMachO()) 389 resetDataLayout("e-m:o-i64:64-i128:128-n32:64-S128"); 390 else 391 resetDataLayout("e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"); 392 } 393 394 void AArch64leTargetInfo::getTargetDefines(const LangOptions &Opts, 395 MacroBuilder &Builder) const { 396 Builder.defineMacro("__AARCH64EL__"); 397 AArch64TargetInfo::getTargetDefines(Opts, Builder); 398 } 399 400 AArch64beTargetInfo::AArch64beTargetInfo(const llvm::Triple &Triple, 401 const TargetOptions &Opts) 402 : AArch64TargetInfo(Triple, Opts) {} 403 404 void AArch64beTargetInfo::getTargetDefines(const LangOptions &Opts, 405 MacroBuilder &Builder) const { 406 Builder.defineMacro("__AARCH64EB__"); 407 Builder.defineMacro("__AARCH_BIG_ENDIAN"); 408 Builder.defineMacro("__ARM_BIG_ENDIAN"); 409 AArch64TargetInfo::getTargetDefines(Opts, Builder); 410 } 411 412 void AArch64beTargetInfo::setDataLayout() { 413 assert(!getTriple().isOSBinFormatMachO()); 414 resetDataLayout("E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"); 415 } 416 417 WindowsARM64TargetInfo::WindowsARM64TargetInfo(const llvm::Triple &Triple, 418 const TargetOptions &Opts) 419 : WindowsTargetInfo<AArch64leTargetInfo>(Triple, Opts), Triple(Triple) { 420 421 // This is an LLP64 platform. 422 // int:4, long:4, long long:8, long double:8. 423 WCharType = UnsignedShort; 424 IntWidth = IntAlign = 32; 425 LongWidth = LongAlign = 32; 426 DoubleAlign = LongLongAlign = 64; 427 LongDoubleWidth = LongDoubleAlign = 64; 428 LongDoubleFormat = &llvm::APFloat::IEEEdouble(); 429 IntMaxType = SignedLongLong; 430 Int64Type = SignedLongLong; 431 SizeType = UnsignedLongLong; 432 PtrDiffType = SignedLongLong; 433 IntPtrType = SignedLongLong; 434 } 435 436 void WindowsARM64TargetInfo::setDataLayout() { 437 resetDataLayout("e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128"); 438 } 439 440 TargetInfo::BuiltinVaListKind 441 WindowsARM64TargetInfo::getBuiltinVaListKind() const { 442 return TargetInfo::CharPtrBuiltinVaList; 443 } 444 445 TargetInfo::CallingConvCheckResult 446 WindowsARM64TargetInfo::checkCallingConvention(CallingConv CC) const { 447 switch (CC) { 448 case CC_X86StdCall: 449 case CC_X86ThisCall: 450 case CC_X86FastCall: 451 case CC_X86VectorCall: 452 return CCCR_Ignore; 453 case CC_C: 454 case CC_OpenCLKernel: 455 case CC_Win64: 456 return CCCR_OK; 457 default: 458 return CCCR_Warning; 459 } 460 } 461 462 MicrosoftARM64TargetInfo::MicrosoftARM64TargetInfo(const llvm::Triple &Triple, 463 const TargetOptions &Opts) 464 : WindowsARM64TargetInfo(Triple, Opts) { 465 TheCXXABI.set(TargetCXXABI::Microsoft); 466 } 467 468 void MicrosoftARM64TargetInfo::getVisualStudioDefines( 469 const LangOptions &Opts, MacroBuilder &Builder) const { 470 WindowsTargetInfo<AArch64leTargetInfo>::getVisualStudioDefines(Opts, Builder); 471 Builder.defineMacro("_WIN32", "1"); 472 Builder.defineMacro("_WIN64", "1"); 473 Builder.defineMacro("_M_ARM64", "1"); 474 } 475 476 void MicrosoftARM64TargetInfo::getTargetDefines(const LangOptions &Opts, 477 MacroBuilder &Builder) const { 478 WindowsTargetInfo::getTargetDefines(Opts, Builder); 479 getVisualStudioDefines(Opts, Builder); 480 } 481 482 MinGWARM64TargetInfo::MinGWARM64TargetInfo(const llvm::Triple &Triple, 483 const TargetOptions &Opts) 484 : WindowsARM64TargetInfo(Triple, Opts) { 485 TheCXXABI.set(TargetCXXABI::GenericAArch64); 486 } 487 488 void MinGWARM64TargetInfo::getTargetDefines(const LangOptions &Opts, 489 MacroBuilder &Builder) const { 490 WindowsTargetInfo::getTargetDefines(Opts, Builder); 491 Builder.defineMacro("_WIN32", "1"); 492 Builder.defineMacro("_WIN64", "1"); 493 Builder.defineMacro("WIN32", "1"); 494 Builder.defineMacro("WIN64", "1"); 495 addMinGWDefines(Opts, Builder); 496 } 497 498 499 DarwinAArch64TargetInfo::DarwinAArch64TargetInfo(const llvm::Triple &Triple, 500 const TargetOptions &Opts) 501 : DarwinTargetInfo<AArch64leTargetInfo>(Triple, Opts) { 502 Int64Type = SignedLongLong; 503 WCharType = SignedInt; 504 UseSignedCharForObjCBool = false; 505 506 LongDoubleWidth = LongDoubleAlign = SuitableAlign = 64; 507 LongDoubleFormat = &llvm::APFloat::IEEEdouble(); 508 509 TheCXXABI.set(TargetCXXABI::iOS64); 510 } 511 512 void DarwinAArch64TargetInfo::getOSDefines(const LangOptions &Opts, 513 const llvm::Triple &Triple, 514 MacroBuilder &Builder) const { 515 Builder.defineMacro("__AARCH64_SIMD__"); 516 Builder.defineMacro("__ARM64_ARCH_8__"); 517 Builder.defineMacro("__ARM_NEON__"); 518 Builder.defineMacro("__LITTLE_ENDIAN__"); 519 Builder.defineMacro("__REGISTER_PREFIX__", ""); 520 Builder.defineMacro("__arm64", "1"); 521 Builder.defineMacro("__arm64__", "1"); 522 523 getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion); 524 } 525 526 TargetInfo::BuiltinVaListKind 527 DarwinAArch64TargetInfo::getBuiltinVaListKind() const { 528 return TargetInfo::CharPtrBuiltinVaList; 529 } 530 531 // 64-bit RenderScript is aarch64 532 RenderScript64TargetInfo::RenderScript64TargetInfo(const llvm::Triple &Triple, 533 const TargetOptions &Opts) 534 : AArch64leTargetInfo(llvm::Triple("aarch64", Triple.getVendorName(), 535 Triple.getOSName(), 536 Triple.getEnvironmentName()), 537 Opts) { 538 IsRenderScriptTarget = true; 539 } 540 541 void RenderScript64TargetInfo::getTargetDefines(const LangOptions &Opts, 542 MacroBuilder &Builder) const { 543 Builder.defineMacro("__RENDERSCRIPT__"); 544 AArch64leTargetInfo::getTargetDefines(Opts, Builder); 545 } 546