1 //===-- TargetParser - Parser for target features ---------------*- C++ -*-===// 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 a target parser to recognise hardware features such as 11 // FPU/CPU/ARCH names as well as specific support such as HDIV, etc. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "llvm/Support/ARMBuildAttributes.h" 16 #include "llvm/Support/TargetParser.h" 17 #include "llvm/ADT/StringSwitch.h" 18 #include "llvm/ADT/Twine.h" 19 #include <cctype> 20 21 using namespace llvm; 22 using namespace ARM; 23 using namespace AArch64; 24 25 namespace { 26 27 // List of canonical FPU names (use getFPUSynonym) and which architectural 28 // features they correspond to (use getFPUFeatures). 29 // FIXME: TableGen this. 30 // The entries must appear in the order listed in ARM::FPUKind for correct indexing 31 static const struct { 32 const char *NameCStr; 33 size_t NameLength; 34 ARM::FPUKind ID; 35 ARM::FPUVersion FPUVersion; 36 ARM::NeonSupportLevel NeonSupport; 37 ARM::FPURestriction Restriction; 38 39 StringRef getName() const { return StringRef(NameCStr, NameLength); } 40 } FPUNames[] = { 41 #define ARM_FPU(NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION) \ 42 { NAME, sizeof(NAME) - 1, KIND, VERSION, NEON_SUPPORT, RESTRICTION }, 43 #include "llvm/Support/ARMTargetParser.def" 44 }; 45 46 // List of canonical arch names (use getArchSynonym). 47 // This table also provides the build attribute fields for CPU arch 48 // and Arch ID, according to the Addenda to the ARM ABI, chapters 49 // 2.4 and 2.3.5.2 respectively. 50 // FIXME: SubArch values were simplified to fit into the expectations 51 // of the triples and are not conforming with their official names. 52 // Check to see if the expectation should be changed. 53 // FIXME: TableGen this. 54 template <typename T> struct ArchNames { 55 const char *NameCStr; 56 size_t NameLength; 57 const char *CPUAttrCStr; 58 size_t CPUAttrLength; 59 const char *SubArchCStr; 60 size_t SubArchLength; 61 unsigned DefaultFPU; 62 unsigned ArchBaseExtensions; 63 T ID; 64 ARMBuildAttrs::CPUArch ArchAttr; // Arch ID in build attributes. 65 66 StringRef getName() const { return StringRef(NameCStr, NameLength); } 67 68 // CPU class in build attributes. 69 StringRef getCPUAttr() const { return StringRef(CPUAttrCStr, CPUAttrLength); } 70 71 // Sub-Arch name. 72 StringRef getSubArch() const { return StringRef(SubArchCStr, SubArchLength); } 73 }; 74 ArchNames<ARM::ArchKind> ARCHNames[] = { 75 #define ARM_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT) \ 76 {NAME, sizeof(NAME) - 1, CPU_ATTR, sizeof(CPU_ATTR) - 1, SUB_ARCH, \ 77 sizeof(SUB_ARCH) - 1, ARCH_FPU, ARCH_BASE_EXT, ARM::ArchKind::ID, ARCH_ATTR}, 78 #include "llvm/Support/ARMTargetParser.def" 79 }; 80 81 ArchNames<AArch64::ArchKind> AArch64ARCHNames[] = { 82 #define AARCH64_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT) \ 83 {NAME, sizeof(NAME) - 1, CPU_ATTR, sizeof(CPU_ATTR) - 1, SUB_ARCH, \ 84 sizeof(SUB_ARCH) - 1, ARCH_FPU, ARCH_BASE_EXT, AArch64::ArchKind::ID, ARCH_ATTR}, 85 #include "llvm/Support/AArch64TargetParser.def" 86 }; 87 88 89 // List of Arch Extension names. 90 // FIXME: TableGen this. 91 static const struct { 92 const char *NameCStr; 93 size_t NameLength; 94 unsigned ID; 95 const char *Feature; 96 const char *NegFeature; 97 98 StringRef getName() const { return StringRef(NameCStr, NameLength); } 99 } ARCHExtNames[] = { 100 #define ARM_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE) \ 101 { NAME, sizeof(NAME) - 1, ID, FEATURE, NEGFEATURE }, 102 #include "llvm/Support/ARMTargetParser.def" 103 },AArch64ARCHExtNames[] = { 104 #define AARCH64_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE) \ 105 { NAME, sizeof(NAME) - 1, ID, FEATURE, NEGFEATURE }, 106 #include "llvm/Support/AArch64TargetParser.def" 107 }; 108 109 // List of HWDiv names (use getHWDivSynonym) and which architectural 110 // features they correspond to (use getHWDivFeatures). 111 // FIXME: TableGen this. 112 static const struct { 113 const char *NameCStr; 114 size_t NameLength; 115 unsigned ID; 116 117 StringRef getName() const { return StringRef(NameCStr, NameLength); } 118 } HWDivNames[] = { 119 #define ARM_HW_DIV_NAME(NAME, ID) { NAME, sizeof(NAME) - 1, ID }, 120 #include "llvm/Support/ARMTargetParser.def" 121 }; 122 123 // List of CPU names and their arches. 124 // The same CPU can have multiple arches and can be default on multiple arches. 125 // When finding the Arch for a CPU, first-found prevails. Sort them accordingly. 126 // When this becomes table-generated, we'd probably need two tables. 127 // FIXME: TableGen this. 128 template <typename T> struct CpuNames { 129 const char *NameCStr; 130 size_t NameLength; 131 T ArchID; 132 bool Default; // is $Name the default CPU for $ArchID ? 133 unsigned DefaultExtensions; 134 135 StringRef getName() const { return StringRef(NameCStr, NameLength); } 136 }; 137 CpuNames<ARM::ArchKind> CPUNames[] = { 138 #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \ 139 { NAME, sizeof(NAME) - 1, ARM::ArchKind::ID, IS_DEFAULT, DEFAULT_EXT }, 140 #include "llvm/Support/ARMTargetParser.def" 141 }; 142 143 CpuNames<AArch64::ArchKind> AArch64CPUNames[] = { 144 #define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \ 145 { NAME, sizeof(NAME) - 1, AArch64::ArchKind::ID, IS_DEFAULT, DEFAULT_EXT }, 146 #include "llvm/Support/AArch64TargetParser.def" 147 }; 148 149 } // namespace 150 151 // ======================================================= // 152 // Information by ID 153 // ======================================================= // 154 155 StringRef ARM::getFPUName(unsigned FPUKind) { 156 if (FPUKind >= ARM::FK_LAST) 157 return StringRef(); 158 return FPUNames[FPUKind].getName(); 159 } 160 161 FPUVersion ARM::getFPUVersion(unsigned FPUKind) { 162 if (FPUKind >= ARM::FK_LAST) 163 return FPUVersion::NONE; 164 return FPUNames[FPUKind].FPUVersion; 165 } 166 167 ARM::NeonSupportLevel ARM::getFPUNeonSupportLevel(unsigned FPUKind) { 168 if (FPUKind >= ARM::FK_LAST) 169 return ARM::NeonSupportLevel::None; 170 return FPUNames[FPUKind].NeonSupport; 171 } 172 173 ARM::FPURestriction ARM::getFPURestriction(unsigned FPUKind) { 174 if (FPUKind >= ARM::FK_LAST) 175 return ARM::FPURestriction::None; 176 return FPUNames[FPUKind].Restriction; 177 } 178 179 unsigned llvm::ARM::getDefaultFPU(StringRef CPU, ArchKind AK) { 180 if (CPU == "generic") 181 return ARCHNames[static_cast<unsigned>(AK)].DefaultFPU; 182 183 return StringSwitch<unsigned>(CPU) 184 #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \ 185 .Case(NAME, DEFAULT_FPU) 186 #include "llvm/Support/ARMTargetParser.def" 187 .Default(ARM::FK_INVALID); 188 } 189 190 unsigned llvm::ARM::getDefaultExtensions(StringRef CPU, ArchKind AK) { 191 if (CPU == "generic") 192 return ARCHNames[static_cast<unsigned>(AK)].ArchBaseExtensions; 193 194 return StringSwitch<unsigned>(CPU) 195 #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \ 196 .Case(NAME, ARCHNames[static_cast<unsigned>(ARM::ArchKind::ID)]\ 197 .ArchBaseExtensions | DEFAULT_EXT) 198 #include "llvm/Support/ARMTargetParser.def" 199 .Default(ARM::AEK_INVALID); 200 } 201 202 bool llvm::ARM::getHWDivFeatures(unsigned HWDivKind, 203 std::vector<StringRef> &Features) { 204 205 if (HWDivKind == ARM::AEK_INVALID) 206 return false; 207 208 if (HWDivKind & ARM::AEK_HWDIVARM) 209 Features.push_back("+hwdiv-arm"); 210 else 211 Features.push_back("-hwdiv-arm"); 212 213 if (HWDivKind & ARM::AEK_HWDIVTHUMB) 214 Features.push_back("+hwdiv"); 215 else 216 Features.push_back("-hwdiv"); 217 218 return true; 219 } 220 221 bool llvm::ARM::getExtensionFeatures(unsigned Extensions, 222 std::vector<StringRef> &Features) { 223 224 if (Extensions == ARM::AEK_INVALID) 225 return false; 226 227 if (Extensions & ARM::AEK_CRC) 228 Features.push_back("+crc"); 229 else 230 Features.push_back("-crc"); 231 232 if (Extensions & ARM::AEK_DSP) 233 Features.push_back("+dsp"); 234 else 235 Features.push_back("-dsp"); 236 237 if (Extensions & ARM::AEK_RAS) 238 Features.push_back("+ras"); 239 else 240 Features.push_back("-ras"); 241 242 if (Extensions & ARM::AEK_DOTPROD) 243 Features.push_back("+dotprod"); 244 else 245 Features.push_back("-dotprod"); 246 247 return getHWDivFeatures(Extensions, Features); 248 } 249 250 bool llvm::ARM::getFPUFeatures(unsigned FPUKind, 251 std::vector<StringRef> &Features) { 252 253 if (FPUKind >= ARM::FK_LAST || FPUKind == ARM::FK_INVALID) 254 return false; 255 256 // fp-only-sp and d16 subtarget features are independent of each other, so we 257 // must enable/disable both. 258 switch (FPUNames[FPUKind].Restriction) { 259 case ARM::FPURestriction::SP_D16: 260 Features.push_back("+fp-only-sp"); 261 Features.push_back("+d16"); 262 break; 263 case ARM::FPURestriction::D16: 264 Features.push_back("-fp-only-sp"); 265 Features.push_back("+d16"); 266 break; 267 case ARM::FPURestriction::None: 268 Features.push_back("-fp-only-sp"); 269 Features.push_back("-d16"); 270 break; 271 } 272 273 // FPU version subtarget features are inclusive of lower-numbered ones, so 274 // enable the one corresponding to this version and disable all that are 275 // higher. We also have to make sure to disable fp16 when vfp4 is disabled, 276 // as +vfp4 implies +fp16 but -vfp4 does not imply -fp16. 277 switch (FPUNames[FPUKind].FPUVersion) { 278 case ARM::FPUVersion::VFPV5: 279 Features.push_back("+fp-armv8"); 280 break; 281 case ARM::FPUVersion::VFPV4: 282 Features.push_back("+vfp4"); 283 Features.push_back("-fp-armv8"); 284 break; 285 case ARM::FPUVersion::VFPV3_FP16: 286 Features.push_back("+vfp3"); 287 Features.push_back("+fp16"); 288 Features.push_back("-vfp4"); 289 Features.push_back("-fp-armv8"); 290 break; 291 case ARM::FPUVersion::VFPV3: 292 Features.push_back("+vfp3"); 293 Features.push_back("-fp16"); 294 Features.push_back("-vfp4"); 295 Features.push_back("-fp-armv8"); 296 break; 297 case ARM::FPUVersion::VFPV2: 298 Features.push_back("+vfp2"); 299 Features.push_back("-vfp3"); 300 Features.push_back("-fp16"); 301 Features.push_back("-vfp4"); 302 Features.push_back("-fp-armv8"); 303 break; 304 case ARM::FPUVersion::NONE: 305 Features.push_back("-vfp2"); 306 Features.push_back("-vfp3"); 307 Features.push_back("-fp16"); 308 Features.push_back("-vfp4"); 309 Features.push_back("-fp-armv8"); 310 break; 311 } 312 313 // crypto includes neon, so we handle this similarly to FPU version. 314 switch (FPUNames[FPUKind].NeonSupport) { 315 case ARM::NeonSupportLevel::Crypto: 316 Features.push_back("+neon"); 317 Features.push_back("+crypto"); 318 break; 319 case ARM::NeonSupportLevel::Neon: 320 Features.push_back("+neon"); 321 Features.push_back("-crypto"); 322 break; 323 case ARM::NeonSupportLevel::None: 324 Features.push_back("-neon"); 325 Features.push_back("-crypto"); 326 break; 327 } 328 329 return true; 330 } 331 332 StringRef llvm::ARM::getArchName(ArchKind AK) { 333 return ARCHNames[static_cast<unsigned>(AK)].getName(); 334 } 335 336 StringRef llvm::ARM::getCPUAttr(ArchKind AK) { 337 return ARCHNames[static_cast<unsigned>(AK)].getCPUAttr(); 338 } 339 340 StringRef llvm::ARM::getSubArch(ArchKind AK) { 341 return ARCHNames[static_cast<unsigned>(AK)].getSubArch(); 342 } 343 344 unsigned llvm::ARM::getArchAttr(ArchKind AK) { 345 return ARCHNames[static_cast<unsigned>(AK)].ArchAttr; 346 } 347 348 StringRef llvm::ARM::getArchExtName(unsigned ArchExtKind) { 349 for (const auto AE : ARCHExtNames) { 350 if (ArchExtKind == AE.ID) 351 return AE.getName(); 352 } 353 return StringRef(); 354 } 355 356 StringRef llvm::ARM::getArchExtFeature(StringRef ArchExt) { 357 if (ArchExt.startswith("no")) { 358 StringRef ArchExtBase(ArchExt.substr(2)); 359 for (const auto AE : ARCHExtNames) { 360 if (AE.NegFeature && ArchExtBase == AE.getName()) 361 return StringRef(AE.NegFeature); 362 } 363 } 364 for (const auto AE : ARCHExtNames) { 365 if (AE.Feature && ArchExt == AE.getName()) 366 return StringRef(AE.Feature); 367 } 368 369 return StringRef(); 370 } 371 372 StringRef llvm::ARM::getHWDivName(unsigned HWDivKind) { 373 for (const auto D : HWDivNames) { 374 if (HWDivKind == D.ID) 375 return D.getName(); 376 } 377 return StringRef(); 378 } 379 380 StringRef llvm::ARM::getDefaultCPU(StringRef Arch) { 381 ArchKind AK = parseArch(Arch); 382 if (AK == ARM::ArchKind::INVALID) 383 return StringRef(); 384 385 // Look for multiple AKs to find the default for pair AK+Name. 386 for (const auto CPU : CPUNames) { 387 if (CPU.ArchID == AK && CPU.Default) 388 return CPU.getName(); 389 } 390 391 // If we can't find a default then target the architecture instead 392 return "generic"; 393 } 394 395 StringRef llvm::AArch64::getFPUName(unsigned FPUKind) { 396 return ARM::getFPUName(FPUKind); 397 } 398 399 ARM::FPUVersion AArch64::getFPUVersion(unsigned FPUKind) { 400 return ARM::getFPUVersion(FPUKind); 401 } 402 403 ARM::NeonSupportLevel AArch64::getFPUNeonSupportLevel(unsigned FPUKind) { 404 return ARM::getFPUNeonSupportLevel( FPUKind); 405 } 406 407 ARM::FPURestriction AArch64::getFPURestriction(unsigned FPUKind) { 408 return ARM::getFPURestriction(FPUKind); 409 } 410 411 unsigned llvm::AArch64::getDefaultFPU(StringRef CPU, ArchKind AK) { 412 if (CPU == "generic") 413 return AArch64ARCHNames[static_cast<unsigned>(AK)].DefaultFPU; 414 415 return StringSwitch<unsigned>(CPU) 416 #define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \ 417 .Case(NAME, DEFAULT_FPU) 418 #include "llvm/Support/AArch64TargetParser.def" 419 .Default(ARM::FK_INVALID); 420 } 421 422 unsigned llvm::AArch64::getDefaultExtensions(StringRef CPU, ArchKind AK) { 423 if (CPU == "generic") 424 return AArch64ARCHNames[static_cast<unsigned>(AK)].ArchBaseExtensions; 425 426 return StringSwitch<unsigned>(CPU) 427 #define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \ 428 .Case(NAME, \ 429 AArch64ARCHNames[static_cast<unsigned>(AArch64::ArchKind::ID)] \ 430 .ArchBaseExtensions | \ 431 DEFAULT_EXT) 432 #include "llvm/Support/AArch64TargetParser.def" 433 .Default(AArch64::AEK_INVALID); 434 } 435 436 bool llvm::AArch64::getExtensionFeatures(unsigned Extensions, 437 std::vector<StringRef> &Features) { 438 439 if (Extensions == AArch64::AEK_INVALID) 440 return false; 441 442 if (Extensions & AArch64::AEK_FP) 443 Features.push_back("+fp-armv8"); 444 if (Extensions & AArch64::AEK_SIMD) 445 Features.push_back("+neon"); 446 if (Extensions & AArch64::AEK_CRC) 447 Features.push_back("+crc"); 448 if (Extensions & AArch64::AEK_CRYPTO) 449 Features.push_back("+crypto"); 450 if (Extensions & AArch64::AEK_DOTPROD) 451 Features.push_back("+dotprod"); 452 if (Extensions & AArch64::AEK_FP16) 453 Features.push_back("+fullfp16"); 454 if (Extensions & AArch64::AEK_PROFILE) 455 Features.push_back("+spe"); 456 if (Extensions & AArch64::AEK_RAS) 457 Features.push_back("+ras"); 458 if (Extensions & AArch64::AEK_LSE) 459 Features.push_back("+lse"); 460 if (Extensions & AArch64::AEK_RDM) 461 Features.push_back("+rdm"); 462 if (Extensions & AArch64::AEK_SVE) 463 Features.push_back("+sve"); 464 if (Extensions & AArch64::AEK_RCPC) 465 Features.push_back("+rcpc"); 466 467 return true; 468 } 469 470 bool llvm::AArch64::getFPUFeatures(unsigned FPUKind, 471 std::vector<StringRef> &Features) { 472 return ARM::getFPUFeatures(FPUKind, Features); 473 } 474 475 bool llvm::AArch64::getArchFeatures(AArch64::ArchKind AK, 476 std::vector<StringRef> &Features) { 477 if (AK == AArch64::ArchKind::ARMV8_1A) 478 Features.push_back("+v8.1a"); 479 if (AK == AArch64::ArchKind::ARMV8_2A) 480 Features.push_back("+v8.2a"); 481 if (AK == AArch64::ArchKind::ARMV8_3A) 482 Features.push_back("+v8.3a"); 483 if (AK == AArch64::ArchKind::ARMV8_4A) 484 Features.push_back("+v8.4a"); 485 486 return AK != AArch64::ArchKind::INVALID; 487 } 488 489 StringRef llvm::AArch64::getArchName(ArchKind AK) { 490 return AArch64ARCHNames[static_cast<unsigned>(AK)].getName(); 491 } 492 493 StringRef llvm::AArch64::getCPUAttr(ArchKind AK) { 494 return AArch64ARCHNames[static_cast<unsigned>(AK)].getCPUAttr(); 495 } 496 497 StringRef llvm::AArch64::getSubArch(ArchKind AK) { 498 return AArch64ARCHNames[static_cast<unsigned>(AK)].getSubArch(); 499 } 500 501 unsigned llvm::AArch64::getArchAttr(ArchKind AK) { 502 return AArch64ARCHNames[static_cast<unsigned>(AK)].ArchAttr; 503 } 504 505 StringRef llvm::AArch64::getArchExtName(unsigned ArchExtKind) { 506 for (const auto &AE : AArch64ARCHExtNames) 507 if (ArchExtKind == AE.ID) 508 return AE.getName(); 509 return StringRef(); 510 } 511 512 StringRef llvm::AArch64::getArchExtFeature(StringRef ArchExt) { 513 if (ArchExt.startswith("no")) { 514 StringRef ArchExtBase(ArchExt.substr(2)); 515 for (const auto &AE : AArch64ARCHExtNames) { 516 if (AE.NegFeature && ArchExtBase == AE.getName()) 517 return StringRef(AE.NegFeature); 518 } 519 } 520 521 for (const auto &AE : AArch64ARCHExtNames) 522 if (AE.Feature && ArchExt == AE.getName()) 523 return StringRef(AE.Feature); 524 return StringRef(); 525 } 526 527 StringRef llvm::AArch64::getDefaultCPU(StringRef Arch) { 528 AArch64::ArchKind AK = parseArch(Arch); 529 if (AK == ArchKind::INVALID) 530 return StringRef(); 531 532 // Look for multiple AKs to find the default for pair AK+Name. 533 for (const auto &CPU : AArch64CPUNames) 534 if (CPU.ArchID == AK && CPU.Default) 535 return CPU.getName(); 536 537 // If we can't find a default then target the architecture instead 538 return "generic"; 539 } 540 541 unsigned llvm::AArch64::checkArchVersion(StringRef Arch) { 542 if (Arch.size() >= 2 && Arch[0] == 'v' && std::isdigit(Arch[1])) 543 return (Arch[1] - 48); 544 return 0; 545 } 546 547 // ======================================================= // 548 // Parsers 549 // ======================================================= // 550 551 static StringRef getHWDivSynonym(StringRef HWDiv) { 552 return StringSwitch<StringRef>(HWDiv) 553 .Case("thumb,arm", "arm,thumb") 554 .Default(HWDiv); 555 } 556 557 static StringRef getFPUSynonym(StringRef FPU) { 558 return StringSwitch<StringRef>(FPU) 559 .Cases("fpa", "fpe2", "fpe3", "maverick", "invalid") // Unsupported 560 .Case("vfp2", "vfpv2") 561 .Case("vfp3", "vfpv3") 562 .Case("vfp4", "vfpv4") 563 .Case("vfp3-d16", "vfpv3-d16") 564 .Case("vfp4-d16", "vfpv4-d16") 565 .Cases("fp4-sp-d16", "vfpv4-sp-d16", "fpv4-sp-d16") 566 .Cases("fp4-dp-d16", "fpv4-dp-d16", "vfpv4-d16") 567 .Case("fp5-sp-d16", "fpv5-sp-d16") 568 .Cases("fp5-dp-d16", "fpv5-dp-d16", "fpv5-d16") 569 // FIXME: Clang uses it, but it's bogus, since neon defaults to vfpv3. 570 .Case("neon-vfpv3", "neon") 571 .Default(FPU); 572 } 573 574 static StringRef getArchSynonym(StringRef Arch) { 575 return StringSwitch<StringRef>(Arch) 576 .Case("v5", "v5t") 577 .Case("v5e", "v5te") 578 .Case("v6j", "v6") 579 .Case("v6hl", "v6k") 580 .Cases("v6m", "v6sm", "v6s-m", "v6-m") 581 .Cases("v6z", "v6zk", "v6kz") 582 .Cases("v7", "v7a", "v7hl", "v7l", "v7-a") 583 .Case("v7r", "v7-r") 584 .Case("v7m", "v7-m") 585 .Case("v7em", "v7e-m") 586 .Cases("v8", "v8a", "v8l", "aarch64", "arm64", "v8-a") 587 .Case("v8.1a", "v8.1-a") 588 .Case("v8.2a", "v8.2-a") 589 .Case("v8.3a", "v8.3-a") 590 .Case("v8.4a", "v8.4-a") 591 .Case("v8r", "v8-r") 592 .Case("v8m.base", "v8-m.base") 593 .Case("v8m.main", "v8-m.main") 594 .Default(Arch); 595 } 596 597 // MArch is expected to be of the form (arm|thumb)?(eb)?(v.+)?(eb)?, but 598 // (iwmmxt|xscale)(eb)? is also permitted. If the former, return 599 // "v.+", if the latter, return unmodified string, minus 'eb'. 600 // If invalid, return empty string. 601 StringRef llvm::ARM::getCanonicalArchName(StringRef Arch) { 602 size_t offset = StringRef::npos; 603 StringRef A = Arch; 604 StringRef Error = ""; 605 606 // Begins with "arm" / "thumb", move past it. 607 if (A.startswith("arm64")) 608 offset = 5; 609 else if (A.startswith("arm")) 610 offset = 3; 611 else if (A.startswith("thumb")) 612 offset = 5; 613 else if (A.startswith("aarch64")) { 614 offset = 7; 615 // AArch64 uses "_be", not "eb" suffix. 616 if (A.find("eb") != StringRef::npos) 617 return Error; 618 if (A.substr(offset, 3) == "_be") 619 offset += 3; 620 } 621 622 // Ex. "armebv7", move past the "eb". 623 if (offset != StringRef::npos && A.substr(offset, 2) == "eb") 624 offset += 2; 625 // Or, if it ends with eb ("armv7eb"), chop it off. 626 else if (A.endswith("eb")) 627 A = A.substr(0, A.size() - 2); 628 // Trim the head 629 if (offset != StringRef::npos) 630 A = A.substr(offset); 631 632 // Empty string means offset reached the end, which means it's valid. 633 if (A.empty()) 634 return Arch; 635 636 // Only match non-marketing names 637 if (offset != StringRef::npos) { 638 // Must start with 'vN'. 639 if (A.size() >= 2 && (A[0] != 'v' || !std::isdigit(A[1]))) 640 return Error; 641 // Can't have an extra 'eb'. 642 if (A.find("eb") != StringRef::npos) 643 return Error; 644 } 645 646 // Arch will either be a 'v' name (v7a) or a marketing name (xscale). 647 return A; 648 } 649 650 unsigned llvm::ARM::parseHWDiv(StringRef HWDiv) { 651 StringRef Syn = getHWDivSynonym(HWDiv); 652 for (const auto D : HWDivNames) { 653 if (Syn == D.getName()) 654 return D.ID; 655 } 656 return ARM::AEK_INVALID; 657 } 658 659 unsigned llvm::ARM::parseFPU(StringRef FPU) { 660 StringRef Syn = getFPUSynonym(FPU); 661 for (const auto F : FPUNames) { 662 if (Syn == F.getName()) 663 return F.ID; 664 } 665 return ARM::FK_INVALID; 666 } 667 668 // Allows partial match, ex. "v7a" matches "armv7a". 669 ARM::ArchKind ARM::parseArch(StringRef Arch) { 670 Arch = getCanonicalArchName(Arch); 671 StringRef Syn = getArchSynonym(Arch); 672 for (const auto A : ARCHNames) { 673 if (A.getName().endswith(Syn)) 674 return A.ID; 675 } 676 return ARM::ArchKind::INVALID; 677 } 678 679 unsigned llvm::ARM::parseArchExt(StringRef ArchExt) { 680 for (const auto A : ARCHExtNames) { 681 if (ArchExt == A.getName()) 682 return A.ID; 683 } 684 return ARM::AEK_INVALID; 685 } 686 687 ARM::ArchKind llvm::ARM::parseCPUArch(StringRef CPU) { 688 for (const auto C : CPUNames) { 689 if (CPU == C.getName()) 690 return C.ArchID; 691 } 692 return ARM::ArchKind::INVALID; 693 } 694 695 void llvm::ARM::fillValidCPUArchList(SmallVectorImpl<StringRef> &Values) { 696 for (const CpuNames<ARM::ArchKind> &Arch : CPUNames) { 697 if (Arch.ArchID != ARM::ArchKind::INVALID) 698 Values.push_back(Arch.getName()); 699 } 700 } 701 702 void llvm::AArch64::fillValidCPUArchList(SmallVectorImpl<StringRef> &Values) { 703 for (const CpuNames<AArch64::ArchKind> &Arch : AArch64CPUNames) { 704 if (Arch.ArchID != AArch64::ArchKind::INVALID) 705 Values.push_back(Arch.getName()); 706 } 707 } 708 709 // ARM, Thumb, AArch64 710 ARM::ISAKind ARM::parseArchISA(StringRef Arch) { 711 return StringSwitch<ARM::ISAKind>(Arch) 712 .StartsWith("aarch64", ARM::ISAKind::AARCH64) 713 .StartsWith("arm64", ARM::ISAKind::AARCH64) 714 .StartsWith("thumb", ARM::ISAKind::THUMB) 715 .StartsWith("arm", ARM::ISAKind::ARM) 716 .Default(ARM::ISAKind::INVALID); 717 } 718 719 // Little/Big endian 720 ARM::EndianKind ARM::parseArchEndian(StringRef Arch) { 721 if (Arch.startswith("armeb") || Arch.startswith("thumbeb") || 722 Arch.startswith("aarch64_be")) 723 return ARM::EndianKind::BIG; 724 725 if (Arch.startswith("arm") || Arch.startswith("thumb")) { 726 if (Arch.endswith("eb")) 727 return ARM::EndianKind::BIG; 728 else 729 return ARM::EndianKind::LITTLE; 730 } 731 732 if (Arch.startswith("aarch64")) 733 return ARM::EndianKind::LITTLE; 734 735 return ARM::EndianKind::INVALID; 736 } 737 738 // Profile A/R/M 739 ARM::ProfileKind ARM::parseArchProfile(StringRef Arch) { 740 Arch = getCanonicalArchName(Arch); 741 switch (parseArch(Arch)) { 742 case ARM::ArchKind::ARMV6M: 743 case ARM::ArchKind::ARMV7M: 744 case ARM::ArchKind::ARMV7EM: 745 case ARM::ArchKind::ARMV8MMainline: 746 case ARM::ArchKind::ARMV8MBaseline: 747 return ARM::ProfileKind::M; 748 case ARM::ArchKind::ARMV7R: 749 case ARM::ArchKind::ARMV8R: 750 return ARM::ProfileKind::R; 751 case ARM::ArchKind::ARMV7A: 752 case ARM::ArchKind::ARMV7VE: 753 case ARM::ArchKind::ARMV7K: 754 case ARM::ArchKind::ARMV8A: 755 case ARM::ArchKind::ARMV8_1A: 756 case ARM::ArchKind::ARMV8_2A: 757 case ARM::ArchKind::ARMV8_3A: 758 case ARM::ArchKind::ARMV8_4A: 759 return ARM::ProfileKind::A; 760 case ARM::ArchKind::ARMV2: 761 case ARM::ArchKind::ARMV2A: 762 case ARM::ArchKind::ARMV3: 763 case ARM::ArchKind::ARMV3M: 764 case ARM::ArchKind::ARMV4: 765 case ARM::ArchKind::ARMV4T: 766 case ARM::ArchKind::ARMV5T: 767 case ARM::ArchKind::ARMV5TE: 768 case ARM::ArchKind::ARMV5TEJ: 769 case ARM::ArchKind::ARMV6: 770 case ARM::ArchKind::ARMV6K: 771 case ARM::ArchKind::ARMV6T2: 772 case ARM::ArchKind::ARMV6KZ: 773 case ARM::ArchKind::ARMV7S: 774 case ARM::ArchKind::IWMMXT: 775 case ARM::ArchKind::IWMMXT2: 776 case ARM::ArchKind::XSCALE: 777 case ARM::ArchKind::INVALID: 778 return ARM::ProfileKind::INVALID; 779 } 780 llvm_unreachable("Unhandled architecture"); 781 } 782 783 // Version number (ex. v7 = 7). 784 unsigned llvm::ARM::parseArchVersion(StringRef Arch) { 785 Arch = getCanonicalArchName(Arch); 786 switch (parseArch(Arch)) { 787 case ARM::ArchKind::ARMV2: 788 case ARM::ArchKind::ARMV2A: 789 return 2; 790 case ARM::ArchKind::ARMV3: 791 case ARM::ArchKind::ARMV3M: 792 return 3; 793 case ARM::ArchKind::ARMV4: 794 case ARM::ArchKind::ARMV4T: 795 return 4; 796 case ARM::ArchKind::ARMV5T: 797 case ARM::ArchKind::ARMV5TE: 798 case ARM::ArchKind::IWMMXT: 799 case ARM::ArchKind::IWMMXT2: 800 case ARM::ArchKind::XSCALE: 801 case ARM::ArchKind::ARMV5TEJ: 802 return 5; 803 case ARM::ArchKind::ARMV6: 804 case ARM::ArchKind::ARMV6K: 805 case ARM::ArchKind::ARMV6T2: 806 case ARM::ArchKind::ARMV6KZ: 807 case ARM::ArchKind::ARMV6M: 808 return 6; 809 case ARM::ArchKind::ARMV7A: 810 case ARM::ArchKind::ARMV7VE: 811 case ARM::ArchKind::ARMV7R: 812 case ARM::ArchKind::ARMV7M: 813 case ARM::ArchKind::ARMV7S: 814 case ARM::ArchKind::ARMV7EM: 815 case ARM::ArchKind::ARMV7K: 816 return 7; 817 case ARM::ArchKind::ARMV8A: 818 case ARM::ArchKind::ARMV8_1A: 819 case ARM::ArchKind::ARMV8_2A: 820 case ARM::ArchKind::ARMV8_3A: 821 case ARM::ArchKind::ARMV8_4A: 822 case ARM::ArchKind::ARMV8R: 823 case ARM::ArchKind::ARMV8MBaseline: 824 case ARM::ArchKind::ARMV8MMainline: 825 return 8; 826 case ARM::ArchKind::INVALID: 827 return 0; 828 } 829 llvm_unreachable("Unhandled architecture"); 830 } 831 832 StringRef llvm::ARM::computeDefaultTargetABI(const Triple &TT, StringRef CPU) { 833 StringRef ArchName = 834 CPU.empty() ? TT.getArchName() : ARM::getArchName(ARM::parseCPUArch(CPU)); 835 836 if (TT.isOSBinFormatMachO()) { 837 if (TT.getEnvironment() == Triple::EABI || 838 TT.getOS() == Triple::UnknownOS || 839 llvm::ARM::parseArchProfile(ArchName) == ARM::ProfileKind::M) 840 return "aapcs"; 841 if (TT.isWatchABI()) 842 return "aapcs16"; 843 return "apcs-gnu"; 844 } else if (TT.isOSWindows()) 845 // FIXME: this is invalid for WindowsCE. 846 return "aapcs"; 847 848 // Select the default based on the platform. 849 switch (TT.getEnvironment()) { 850 case Triple::Android: 851 case Triple::GNUEABI: 852 case Triple::GNUEABIHF: 853 case Triple::MuslEABI: 854 case Triple::MuslEABIHF: 855 return "aapcs-linux"; 856 case Triple::EABIHF: 857 case Triple::EABI: 858 return "aapcs"; 859 default: 860 if (TT.isOSNetBSD()) 861 return "apcs-gnu"; 862 if (TT.isOSOpenBSD()) 863 return "aapcs-linux"; 864 return "aapcs"; 865 } 866 } 867 868 StringRef llvm::AArch64::getCanonicalArchName(StringRef Arch) { 869 return ARM::getCanonicalArchName(Arch); 870 } 871 872 unsigned llvm::AArch64::parseFPU(StringRef FPU) { 873 return ARM::parseFPU(FPU); 874 } 875 876 // Allows partial match, ex. "v8a" matches "armv8a". 877 AArch64::ArchKind AArch64::parseArch(StringRef Arch) { 878 Arch = getCanonicalArchName(Arch); 879 if (checkArchVersion(Arch) < 8) 880 return ArchKind::INVALID; 881 882 StringRef Syn = getArchSynonym(Arch); 883 for (const auto A : AArch64ARCHNames) { 884 if (A.getName().endswith(Syn)) 885 return A.ID; 886 } 887 return ArchKind::INVALID; 888 } 889 890 AArch64::ArchExtKind llvm::AArch64::parseArchExt(StringRef ArchExt) { 891 for (const auto A : AArch64ARCHExtNames) { 892 if (ArchExt == A.getName()) 893 return static_cast<ArchExtKind>(A.ID); 894 } 895 return AArch64::AEK_INVALID; 896 } 897 898 AArch64::ArchKind llvm::AArch64::parseCPUArch(StringRef CPU) { 899 for (const auto C : AArch64CPUNames) { 900 if (CPU == C.getName()) 901 return C.ArchID; 902 } 903 return ArchKind::INVALID; 904 } 905 906 // ARM, Thumb, AArch64 907 ARM::ISAKind AArch64::parseArchISA(StringRef Arch) { 908 return ARM::parseArchISA(Arch); 909 } 910 911 // Little/Big endian 912 ARM::EndianKind AArch64::parseArchEndian(StringRef Arch) { 913 return ARM::parseArchEndian(Arch); 914 } 915 916 // Profile A/R/M 917 ARM::ProfileKind AArch64::parseArchProfile(StringRef Arch) { 918 return ARM::parseArchProfile(Arch); 919 } 920 921 // Version number (ex. v8 = 8). 922 unsigned llvm::AArch64::parseArchVersion(StringRef Arch) { 923 return ARM::parseArchVersion(Arch); 924 } 925 926 bool llvm::AArch64::isX18ReservedByDefault(const Triple &TT) { 927 return TT.isOSDarwin() || TT.isOSFuchsia() || TT.isOSWindows(); 928 } 929