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 484 return AK != AArch64::ArchKind::INVALID; 485 } 486 487 StringRef llvm::AArch64::getArchName(ArchKind AK) { 488 return AArch64ARCHNames[static_cast<unsigned>(AK)].getName(); 489 } 490 491 StringRef llvm::AArch64::getCPUAttr(ArchKind AK) { 492 return AArch64ARCHNames[static_cast<unsigned>(AK)].getCPUAttr(); 493 } 494 495 StringRef llvm::AArch64::getSubArch(ArchKind AK) { 496 return AArch64ARCHNames[static_cast<unsigned>(AK)].getSubArch(); 497 } 498 499 unsigned llvm::AArch64::getArchAttr(ArchKind AK) { 500 return AArch64ARCHNames[static_cast<unsigned>(AK)].ArchAttr; 501 } 502 503 StringRef llvm::AArch64::getArchExtName(unsigned ArchExtKind) { 504 for (const auto &AE : AArch64ARCHExtNames) 505 if (ArchExtKind == AE.ID) 506 return AE.getName(); 507 return StringRef(); 508 } 509 510 StringRef llvm::AArch64::getArchExtFeature(StringRef ArchExt) { 511 if (ArchExt.startswith("no")) { 512 StringRef ArchExtBase(ArchExt.substr(2)); 513 for (const auto &AE : AArch64ARCHExtNames) { 514 if (AE.NegFeature && ArchExtBase == AE.getName()) 515 return StringRef(AE.NegFeature); 516 } 517 } 518 519 for (const auto &AE : AArch64ARCHExtNames) 520 if (AE.Feature && ArchExt == AE.getName()) 521 return StringRef(AE.Feature); 522 return StringRef(); 523 } 524 525 StringRef llvm::AArch64::getDefaultCPU(StringRef Arch) { 526 AArch64::ArchKind AK = parseArch(Arch); 527 if (AK == ArchKind::INVALID) 528 return StringRef(); 529 530 // Look for multiple AKs to find the default for pair AK+Name. 531 for (const auto &CPU : AArch64CPUNames) 532 if (CPU.ArchID == AK && CPU.Default) 533 return CPU.getName(); 534 535 // If we can't find a default then target the architecture instead 536 return "generic"; 537 } 538 539 unsigned llvm::AArch64::checkArchVersion(StringRef Arch) { 540 if (Arch.size() >= 2 && Arch[0] == 'v' && std::isdigit(Arch[1])) 541 return (Arch[1] - 48); 542 return 0; 543 } 544 545 // ======================================================= // 546 // Parsers 547 // ======================================================= // 548 549 static StringRef getHWDivSynonym(StringRef HWDiv) { 550 return StringSwitch<StringRef>(HWDiv) 551 .Case("thumb,arm", "arm,thumb") 552 .Default(HWDiv); 553 } 554 555 static StringRef getFPUSynonym(StringRef FPU) { 556 return StringSwitch<StringRef>(FPU) 557 .Cases("fpa", "fpe2", "fpe3", "maverick", "invalid") // Unsupported 558 .Case("vfp2", "vfpv2") 559 .Case("vfp3", "vfpv3") 560 .Case("vfp4", "vfpv4") 561 .Case("vfp3-d16", "vfpv3-d16") 562 .Case("vfp4-d16", "vfpv4-d16") 563 .Cases("fp4-sp-d16", "vfpv4-sp-d16", "fpv4-sp-d16") 564 .Cases("fp4-dp-d16", "fpv4-dp-d16", "vfpv4-d16") 565 .Case("fp5-sp-d16", "fpv5-sp-d16") 566 .Cases("fp5-dp-d16", "fpv5-dp-d16", "fpv5-d16") 567 // FIXME: Clang uses it, but it's bogus, since neon defaults to vfpv3. 568 .Case("neon-vfpv3", "neon") 569 .Default(FPU); 570 } 571 572 static StringRef getArchSynonym(StringRef Arch) { 573 return StringSwitch<StringRef>(Arch) 574 .Case("v5", "v5t") 575 .Case("v5e", "v5te") 576 .Case("v6j", "v6") 577 .Case("v6hl", "v6k") 578 .Cases("v6m", "v6sm", "v6s-m", "v6-m") 579 .Cases("v6z", "v6zk", "v6kz") 580 .Cases("v7", "v7a", "v7hl", "v7l", "v7-a") 581 .Case("v7r", "v7-r") 582 .Case("v7m", "v7-m") 583 .Case("v7em", "v7e-m") 584 .Cases("v8", "v8a", "v8l", "aarch64", "arm64", "v8-a") 585 .Case("v8.1a", "v8.1-a") 586 .Case("v8.2a", "v8.2-a") 587 .Case("v8.3a", "v8.3-a") 588 .Case("v8r", "v8-r") 589 .Case("v8m.base", "v8-m.base") 590 .Case("v8m.main", "v8-m.main") 591 .Default(Arch); 592 } 593 594 // MArch is expected to be of the form (arm|thumb)?(eb)?(v.+)?(eb)?, but 595 // (iwmmxt|xscale)(eb)? is also permitted. If the former, return 596 // "v.+", if the latter, return unmodified string, minus 'eb'. 597 // If invalid, return empty string. 598 StringRef llvm::ARM::getCanonicalArchName(StringRef Arch) { 599 size_t offset = StringRef::npos; 600 StringRef A = Arch; 601 StringRef Error = ""; 602 603 // Begins with "arm" / "thumb", move past it. 604 if (A.startswith("arm64")) 605 offset = 5; 606 else if (A.startswith("arm")) 607 offset = 3; 608 else if (A.startswith("thumb")) 609 offset = 5; 610 else if (A.startswith("aarch64")) { 611 offset = 7; 612 // AArch64 uses "_be", not "eb" suffix. 613 if (A.find("eb") != StringRef::npos) 614 return Error; 615 if (A.substr(offset, 3) == "_be") 616 offset += 3; 617 } 618 619 // Ex. "armebv7", move past the "eb". 620 if (offset != StringRef::npos && A.substr(offset, 2) == "eb") 621 offset += 2; 622 // Or, if it ends with eb ("armv7eb"), chop it off. 623 else if (A.endswith("eb")) 624 A = A.substr(0, A.size() - 2); 625 // Trim the head 626 if (offset != StringRef::npos) 627 A = A.substr(offset); 628 629 // Empty string means offset reached the end, which means it's valid. 630 if (A.empty()) 631 return Arch; 632 633 // Only match non-marketing names 634 if (offset != StringRef::npos) { 635 // Must start with 'vN'. 636 if (A.size() >= 2 && (A[0] != 'v' || !std::isdigit(A[1]))) 637 return Error; 638 // Can't have an extra 'eb'. 639 if (A.find("eb") != StringRef::npos) 640 return Error; 641 } 642 643 // Arch will either be a 'v' name (v7a) or a marketing name (xscale). 644 return A; 645 } 646 647 unsigned llvm::ARM::parseHWDiv(StringRef HWDiv) { 648 StringRef Syn = getHWDivSynonym(HWDiv); 649 for (const auto D : HWDivNames) { 650 if (Syn == D.getName()) 651 return D.ID; 652 } 653 return ARM::AEK_INVALID; 654 } 655 656 unsigned llvm::ARM::parseFPU(StringRef FPU) { 657 StringRef Syn = getFPUSynonym(FPU); 658 for (const auto F : FPUNames) { 659 if (Syn == F.getName()) 660 return F.ID; 661 } 662 return ARM::FK_INVALID; 663 } 664 665 // Allows partial match, ex. "v7a" matches "armv7a". 666 ARM::ArchKind ARM::parseArch(StringRef Arch) { 667 Arch = getCanonicalArchName(Arch); 668 StringRef Syn = getArchSynonym(Arch); 669 for (const auto A : ARCHNames) { 670 if (A.getName().endswith(Syn)) 671 return A.ID; 672 } 673 return ARM::ArchKind::INVALID; 674 } 675 676 unsigned llvm::ARM::parseArchExt(StringRef ArchExt) { 677 for (const auto A : ARCHExtNames) { 678 if (ArchExt == A.getName()) 679 return A.ID; 680 } 681 return ARM::AEK_INVALID; 682 } 683 684 ARM::ArchKind llvm::ARM::parseCPUArch(StringRef CPU) { 685 for (const auto C : CPUNames) { 686 if (CPU == C.getName()) 687 return C.ArchID; 688 } 689 return ARM::ArchKind::INVALID; 690 } 691 692 // ARM, Thumb, AArch64 693 ARM::ISAKind ARM::parseArchISA(StringRef Arch) { 694 return StringSwitch<ARM::ISAKind>(Arch) 695 .StartsWith("aarch64", ARM::ISAKind::AARCH64) 696 .StartsWith("arm64", ARM::ISAKind::AARCH64) 697 .StartsWith("thumb", ARM::ISAKind::THUMB) 698 .StartsWith("arm", ARM::ISAKind::ARM) 699 .Default(ARM::ISAKind::INVALID); 700 } 701 702 // Little/Big endian 703 ARM::EndianKind ARM::parseArchEndian(StringRef Arch) { 704 if (Arch.startswith("armeb") || Arch.startswith("thumbeb") || 705 Arch.startswith("aarch64_be")) 706 return ARM::EndianKind::BIG; 707 708 if (Arch.startswith("arm") || Arch.startswith("thumb")) { 709 if (Arch.endswith("eb")) 710 return ARM::EndianKind::BIG; 711 else 712 return ARM::EndianKind::LITTLE; 713 } 714 715 if (Arch.startswith("aarch64")) 716 return ARM::EndianKind::LITTLE; 717 718 return ARM::EndianKind::INVALID; 719 } 720 721 // Profile A/R/M 722 ARM::ProfileKind ARM::parseArchProfile(StringRef Arch) { 723 Arch = getCanonicalArchName(Arch); 724 switch (parseArch(Arch)) { 725 case ARM::ArchKind::ARMV6M: 726 case ARM::ArchKind::ARMV7M: 727 case ARM::ArchKind::ARMV7EM: 728 case ARM::ArchKind::ARMV8MMainline: 729 case ARM::ArchKind::ARMV8MBaseline: 730 return ARM::ProfileKind::M; 731 case ARM::ArchKind::ARMV7R: 732 case ARM::ArchKind::ARMV8R: 733 return ARM::ProfileKind::R; 734 case ARM::ArchKind::ARMV7A: 735 case ARM::ArchKind::ARMV7VE: 736 case ARM::ArchKind::ARMV7K: 737 case ARM::ArchKind::ARMV8A: 738 case ARM::ArchKind::ARMV8_1A: 739 case ARM::ArchKind::ARMV8_2A: 740 case ARM::ArchKind::ARMV8_3A: 741 return ARM::ProfileKind::A; 742 case ARM::ArchKind::ARMV2: 743 case ARM::ArchKind::ARMV2A: 744 case ARM::ArchKind::ARMV3: 745 case ARM::ArchKind::ARMV3M: 746 case ARM::ArchKind::ARMV4: 747 case ARM::ArchKind::ARMV4T: 748 case ARM::ArchKind::ARMV5T: 749 case ARM::ArchKind::ARMV5TE: 750 case ARM::ArchKind::ARMV5TEJ: 751 case ARM::ArchKind::ARMV6: 752 case ARM::ArchKind::ARMV6K: 753 case ARM::ArchKind::ARMV6T2: 754 case ARM::ArchKind::ARMV6KZ: 755 case ARM::ArchKind::ARMV7S: 756 case ARM::ArchKind::IWMMXT: 757 case ARM::ArchKind::IWMMXT2: 758 case ARM::ArchKind::XSCALE: 759 case ARM::ArchKind::INVALID: 760 return ARM::ProfileKind::INVALID; 761 } 762 llvm_unreachable("Unhandled architecture"); 763 } 764 765 // Version number (ex. v7 = 7). 766 unsigned llvm::ARM::parseArchVersion(StringRef Arch) { 767 Arch = getCanonicalArchName(Arch); 768 switch (parseArch(Arch)) { 769 case ARM::ArchKind::ARMV2: 770 case ARM::ArchKind::ARMV2A: 771 return 2; 772 case ARM::ArchKind::ARMV3: 773 case ARM::ArchKind::ARMV3M: 774 return 3; 775 case ARM::ArchKind::ARMV4: 776 case ARM::ArchKind::ARMV4T: 777 return 4; 778 case ARM::ArchKind::ARMV5T: 779 case ARM::ArchKind::ARMV5TE: 780 case ARM::ArchKind::IWMMXT: 781 case ARM::ArchKind::IWMMXT2: 782 case ARM::ArchKind::XSCALE: 783 case ARM::ArchKind::ARMV5TEJ: 784 return 5; 785 case ARM::ArchKind::ARMV6: 786 case ARM::ArchKind::ARMV6K: 787 case ARM::ArchKind::ARMV6T2: 788 case ARM::ArchKind::ARMV6KZ: 789 case ARM::ArchKind::ARMV6M: 790 return 6; 791 case ARM::ArchKind::ARMV7A: 792 case ARM::ArchKind::ARMV7VE: 793 case ARM::ArchKind::ARMV7R: 794 case ARM::ArchKind::ARMV7M: 795 case ARM::ArchKind::ARMV7S: 796 case ARM::ArchKind::ARMV7EM: 797 case ARM::ArchKind::ARMV7K: 798 return 7; 799 case ARM::ArchKind::ARMV8A: 800 case ARM::ArchKind::ARMV8_1A: 801 case ARM::ArchKind::ARMV8_2A: 802 case ARM::ArchKind::ARMV8_3A: 803 case ARM::ArchKind::ARMV8R: 804 case ARM::ArchKind::ARMV8MBaseline: 805 case ARM::ArchKind::ARMV8MMainline: 806 return 8; 807 case ARM::ArchKind::INVALID: 808 return 0; 809 } 810 llvm_unreachable("Unhandled architecture"); 811 } 812 813 StringRef llvm::ARM::computeDefaultTargetABI(const Triple &TT, StringRef CPU) { 814 StringRef ArchName = 815 CPU.empty() ? TT.getArchName() : ARM::getArchName(ARM::parseCPUArch(CPU)); 816 817 if (TT.isOSBinFormatMachO()) { 818 if (TT.getEnvironment() == Triple::EABI || 819 TT.getOS() == Triple::UnknownOS || 820 llvm::ARM::parseArchProfile(ArchName) == ARM::ProfileKind::M) 821 return "aapcs"; 822 if (TT.isWatchABI()) 823 return "aapcs16"; 824 return "apcs-gnu"; 825 } else if (TT.isOSWindows()) 826 // FIXME: this is invalid for WindowsCE. 827 return "aapcs"; 828 829 // Select the default based on the platform. 830 switch (TT.getEnvironment()) { 831 case Triple::Android: 832 case Triple::GNUEABI: 833 case Triple::GNUEABIHF: 834 case Triple::MuslEABI: 835 case Triple::MuslEABIHF: 836 return "aapcs-linux"; 837 case Triple::EABIHF: 838 case Triple::EABI: 839 return "aapcs"; 840 default: 841 if (TT.isOSNetBSD()) 842 return "apcs-gnu"; 843 if (TT.isOSOpenBSD()) 844 return "aapcs-linux"; 845 return "aapcs"; 846 } 847 } 848 849 StringRef llvm::AArch64::getCanonicalArchName(StringRef Arch) { 850 return ARM::getCanonicalArchName(Arch); 851 } 852 853 unsigned llvm::AArch64::parseFPU(StringRef FPU) { 854 return ARM::parseFPU(FPU); 855 } 856 857 // Allows partial match, ex. "v8a" matches "armv8a". 858 AArch64::ArchKind AArch64::parseArch(StringRef Arch) { 859 Arch = getCanonicalArchName(Arch); 860 if (checkArchVersion(Arch) < 8) 861 return ArchKind::INVALID; 862 863 StringRef Syn = getArchSynonym(Arch); 864 for (const auto A : AArch64ARCHNames) { 865 if (A.getName().endswith(Syn)) 866 return A.ID; 867 } 868 return ArchKind::INVALID; 869 } 870 871 AArch64::ArchExtKind llvm::AArch64::parseArchExt(StringRef ArchExt) { 872 for (const auto A : AArch64ARCHExtNames) { 873 if (ArchExt == A.getName()) 874 return static_cast<ArchExtKind>(A.ID); 875 } 876 return AArch64::AEK_INVALID; 877 } 878 879 AArch64::ArchKind llvm::AArch64::parseCPUArch(StringRef CPU) { 880 for (const auto C : AArch64CPUNames) { 881 if (CPU == C.getName()) 882 return C.ArchID; 883 } 884 return ArchKind::INVALID; 885 } 886 887 // ARM, Thumb, AArch64 888 ARM::ISAKind AArch64::parseArchISA(StringRef Arch) { 889 return ARM::parseArchISA(Arch); 890 } 891 892 // Little/Big endian 893 ARM::EndianKind AArch64::parseArchEndian(StringRef Arch) { 894 return ARM::parseArchEndian(Arch); 895 } 896 897 // Profile A/R/M 898 ARM::ProfileKind AArch64::parseArchProfile(StringRef Arch) { 899 return ARM::parseArchProfile(Arch); 900 } 901 902 // Version number (ex. v8 = 8). 903 unsigned llvm::AArch64::parseArchVersion(StringRef Arch) { 904 return ARM::parseArchVersion(Arch); 905 } 906