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