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