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