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