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