Home | History | Annotate | Download | only in Support
      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/StringExtras.h"
     18 #include "llvm/ADT/StringSwitch.h"
     19 #include "llvm/ADT/Twine.h"
     20 #include <cctype>
     21 
     22 using namespace llvm;
     23 using namespace ARM;
     24 using namespace AArch64;
     25 
     26 namespace {
     27 
     28 // List of canonical FPU names (use getFPUSynonym) and which architectural
     29 // features they correspond to (use getFPUFeatures).
     30 // FIXME: TableGen this.
     31 // The entries must appear in the order listed in ARM::FPUKind for correct indexing
     32 static const struct {
     33   const char *NameCStr;
     34   size_t NameLength;
     35   ARM::FPUKind ID;
     36   ARM::FPUVersion FPUVersion;
     37   ARM::NeonSupportLevel NeonSupport;
     38   ARM::FPURestriction Restriction;
     39 
     40   StringRef getName() const { return StringRef(NameCStr, NameLength); }
     41 } FPUNames[] = {
     42 #define ARM_FPU(NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION) \
     43   { NAME, sizeof(NAME) - 1, KIND, VERSION, NEON_SUPPORT, RESTRICTION },
     44 #include "llvm/Support/ARMTargetParser.def"
     45 };
     46 
     47 // List of canonical arch names (use getArchSynonym).
     48 // This table also provides the build attribute fields for CPU arch
     49 // and Arch ID, according to the Addenda to the ARM ABI, chapters
     50 // 2.4 and 2.3.5.2 respectively.
     51 // FIXME: SubArch values were simplified to fit into the expectations
     52 // of the triples and are not conforming with their official names.
     53 // Check to see if the expectation should be changed.
     54 // FIXME: TableGen this.
     55 template <typename T> struct ArchNames {
     56   const char *NameCStr;
     57   size_t NameLength;
     58   const char *CPUAttrCStr;
     59   size_t CPUAttrLength;
     60   const char *SubArchCStr;
     61   size_t SubArchLength;
     62   unsigned DefaultFPU;
     63   unsigned ArchBaseExtensions;
     64   T ID;
     65   ARMBuildAttrs::CPUArch ArchAttr; // Arch ID in build attributes.
     66 
     67   StringRef getName() const { return StringRef(NameCStr, NameLength); }
     68 
     69   // CPU class in build attributes.
     70   StringRef getCPUAttr() const { return StringRef(CPUAttrCStr, CPUAttrLength); }
     71 
     72   // Sub-Arch name.
     73   StringRef getSubArch() const { return StringRef(SubArchCStr, SubArchLength); }
     74 };
     75 ArchNames<ARM::ArchKind> ARCHNames[] = {
     76 #define ARM_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT)       \
     77   {NAME, sizeof(NAME) - 1, CPU_ATTR, sizeof(CPU_ATTR) - 1, SUB_ARCH,       \
     78    sizeof(SUB_ARCH) - 1, ARCH_FPU, ARCH_BASE_EXT, ID, ARCH_ATTR},
     79 #include "llvm/Support/ARMTargetParser.def"
     80 };
     81 
     82 ArchNames<AArch64::ArchKind> AArch64ARCHNames[] = {
     83  #define AARCH64_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT)       \
     84    {NAME, sizeof(NAME) - 1, CPU_ATTR, sizeof(CPU_ATTR) - 1, SUB_ARCH,       \
     85     sizeof(SUB_ARCH) - 1, ARCH_FPU, ARCH_BASE_EXT, AArch64::ArchKind::ID, ARCH_ATTR},
     86  #include "llvm/Support/AArch64TargetParser.def"
     87  };
     88 
     89 
     90 // List of Arch Extension names.
     91 // FIXME: TableGen this.
     92 static const struct {
     93   const char *NameCStr;
     94   size_t NameLength;
     95   unsigned ID;
     96   const char *Feature;
     97   const char *NegFeature;
     98 
     99   StringRef getName() const { return StringRef(NameCStr, NameLength); }
    100 } ARCHExtNames[] = {
    101 #define ARM_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE) \
    102   { NAME, sizeof(NAME) - 1, ID, FEATURE, NEGFEATURE },
    103 #include "llvm/Support/ARMTargetParser.def"
    104 },AArch64ARCHExtNames[] = {
    105 #define AARCH64_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE) \
    106   { NAME, sizeof(NAME) - 1, ID, FEATURE, NEGFEATURE },
    107 #include "llvm/Support/AArch64TargetParser.def"
    108 };
    109 
    110 // List of HWDiv names (use getHWDivSynonym) and which architectural
    111 // features they correspond to (use getHWDivFeatures).
    112 // FIXME: TableGen this.
    113 static const struct {
    114   const char *NameCStr;
    115   size_t NameLength;
    116   unsigned ID;
    117 
    118   StringRef getName() const { return StringRef(NameCStr, NameLength); }
    119 } HWDivNames[] = {
    120 #define ARM_HW_DIV_NAME(NAME, ID) { NAME, sizeof(NAME) - 1, ID },
    121 #include "llvm/Support/ARMTargetParser.def"
    122 };
    123 
    124 // List of CPU names and their arches.
    125 // The same CPU can have multiple arches and can be default on multiple arches.
    126 // When finding the Arch for a CPU, first-found prevails. Sort them accordingly.
    127 // When this becomes table-generated, we'd probably need two tables.
    128 // FIXME: TableGen this.
    129 template <typename T> struct CpuNames {
    130   const char *NameCStr;
    131   size_t NameLength;
    132   T ArchID;
    133   bool Default; // is $Name the default CPU for $ArchID ?
    134   unsigned DefaultExtensions;
    135 
    136   StringRef getName() const { return StringRef(NameCStr, NameLength); }
    137 };
    138 CpuNames<ARM::ArchKind> CPUNames[] = {
    139 #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
    140   { NAME, sizeof(NAME) - 1, ID, IS_DEFAULT, DEFAULT_EXT },
    141 #include "llvm/Support/ARMTargetParser.def"
    142 };
    143 
    144 CpuNames<AArch64::ArchKind> AArch64CPUNames[] = {
    145  #define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
    146    { NAME, sizeof(NAME) - 1, AArch64::ArchKind::ID, IS_DEFAULT, DEFAULT_EXT },
    147  #include "llvm/Support/AArch64TargetParser.def"
    148  };
    149 
    150 } // namespace
    151 
    152 // ======================================================= //
    153 // Information by ID
    154 // ======================================================= //
    155 
    156 StringRef llvm::ARM::getFPUName(unsigned FPUKind) {
    157   if (FPUKind >= ARM::FK_LAST)
    158     return StringRef();
    159   return FPUNames[FPUKind].getName();
    160 }
    161 
    162 unsigned llvm::ARM::getFPUVersion(unsigned FPUKind) {
    163   if (FPUKind >= ARM::FK_LAST)
    164     return 0;
    165   return FPUNames[FPUKind].FPUVersion;
    166 }
    167 
    168 unsigned llvm::ARM::getFPUNeonSupportLevel(unsigned FPUKind) {
    169   if (FPUKind >= ARM::FK_LAST)
    170     return 0;
    171   return FPUNames[FPUKind].NeonSupport;
    172 }
    173 
    174 unsigned llvm::ARM::getFPURestriction(unsigned FPUKind) {
    175   if (FPUKind >= ARM::FK_LAST)
    176     return 0;
    177   return FPUNames[FPUKind].Restriction;
    178 }
    179 
    180 unsigned llvm::ARM::getDefaultFPU(StringRef CPU, unsigned ArchKind) {
    181   if (CPU == "generic")
    182     return ARCHNames[ArchKind].DefaultFPU;
    183 
    184   return StringSwitch<unsigned>(CPU)
    185 #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
    186     .Case(NAME, DEFAULT_FPU)
    187 #include "llvm/Support/ARMTargetParser.def"
    188     .Default(ARM::FK_INVALID);
    189 }
    190 
    191 unsigned llvm::ARM::getDefaultExtensions(StringRef CPU, unsigned ArchKind) {
    192   if (CPU == "generic")
    193     return ARCHNames[ArchKind].ArchBaseExtensions;
    194 
    195   return StringSwitch<unsigned>(CPU)
    196 #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
    197     .Case(NAME, ARCHNames[ID].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<const char *> &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_HWDIV)
    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<const char *> &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   return getHWDivFeatures(Extensions, Features);
    238 }
    239 
    240 bool llvm::ARM::getFPUFeatures(unsigned FPUKind,
    241                                std::vector<const char *> &Features) {
    242 
    243   if (FPUKind >= ARM::FK_LAST || FPUKind == ARM::FK_INVALID)
    244     return false;
    245 
    246   // fp-only-sp and d16 subtarget features are independent of each other, so we
    247   // must enable/disable both.
    248   switch (FPUNames[FPUKind].Restriction) {
    249   case ARM::FR_SP_D16:
    250     Features.push_back("+fp-only-sp");
    251     Features.push_back("+d16");
    252     break;
    253   case ARM::FR_D16:
    254     Features.push_back("-fp-only-sp");
    255     Features.push_back("+d16");
    256     break;
    257   case ARM::FR_None:
    258     Features.push_back("-fp-only-sp");
    259     Features.push_back("-d16");
    260     break;
    261   }
    262 
    263   // FPU version subtarget features are inclusive of lower-numbered ones, so
    264   // enable the one corresponding to this version and disable all that are
    265   // higher. We also have to make sure to disable fp16 when vfp4 is disabled,
    266   // as +vfp4 implies +fp16 but -vfp4 does not imply -fp16.
    267   switch (FPUNames[FPUKind].FPUVersion) {
    268   case ARM::FV_VFPV5:
    269     Features.push_back("+fp-armv8");
    270     break;
    271   case ARM::FV_VFPV4:
    272     Features.push_back("+vfp4");
    273     Features.push_back("-fp-armv8");
    274     break;
    275   case ARM::FV_VFPV3_FP16:
    276     Features.push_back("+vfp3");
    277     Features.push_back("+fp16");
    278     Features.push_back("-vfp4");
    279     Features.push_back("-fp-armv8");
    280     break;
    281   case ARM::FV_VFPV3:
    282     Features.push_back("+vfp3");
    283     Features.push_back("-fp16");
    284     Features.push_back("-vfp4");
    285     Features.push_back("-fp-armv8");
    286     break;
    287   case ARM::FV_VFPV2:
    288     Features.push_back("+vfp2");
    289     Features.push_back("-vfp3");
    290     Features.push_back("-fp16");
    291     Features.push_back("-vfp4");
    292     Features.push_back("-fp-armv8");
    293     break;
    294   case ARM::FV_NONE:
    295     Features.push_back("-vfp2");
    296     Features.push_back("-vfp3");
    297     Features.push_back("-fp16");
    298     Features.push_back("-vfp4");
    299     Features.push_back("-fp-armv8");
    300     break;
    301   }
    302 
    303   // crypto includes neon, so we handle this similarly to FPU version.
    304   switch (FPUNames[FPUKind].NeonSupport) {
    305   case ARM::NS_Crypto:
    306     Features.push_back("+neon");
    307     Features.push_back("+crypto");
    308     break;
    309   case ARM::NS_Neon:
    310     Features.push_back("+neon");
    311     Features.push_back("-crypto");
    312     break;
    313   case ARM::NS_None:
    314     Features.push_back("-neon");
    315     Features.push_back("-crypto");
    316     break;
    317   }
    318 
    319   return true;
    320 }
    321 
    322 StringRef llvm::ARM::getArchName(unsigned ArchKind) {
    323   if (ArchKind >= ARM::AK_LAST)
    324     return StringRef();
    325   return ARCHNames[ArchKind].getName();
    326 }
    327 
    328 StringRef llvm::ARM::getCPUAttr(unsigned ArchKind) {
    329   if (ArchKind == ARM::AK_INVALID || ArchKind >= ARM::AK_LAST)
    330     return StringRef();
    331   return ARCHNames[ArchKind].getCPUAttr();
    332 }
    333 
    334 StringRef llvm::ARM::getSubArch(unsigned ArchKind) {
    335   if (ArchKind == ARM::AK_INVALID || ArchKind >= ARM::AK_LAST)
    336     return StringRef();
    337   return ARCHNames[ArchKind].getSubArch();
    338 }
    339 
    340 unsigned llvm::ARM::getArchAttr(unsigned ArchKind) {
    341   if (ArchKind >= ARM::AK_LAST)
    342     return ARMBuildAttrs::CPUArch::Pre_v4;
    343   return ARCHNames[ArchKind].ArchAttr;
    344 }
    345 
    346 StringRef llvm::ARM::getArchExtName(unsigned ArchExtKind) {
    347   for (const auto AE : ARCHExtNames) {
    348     if (ArchExtKind == AE.ID)
    349       return AE.getName();
    350   }
    351   return StringRef();
    352 }
    353 
    354 const char *llvm::ARM::getArchExtFeature(StringRef ArchExt) {
    355   if (ArchExt.startswith("no")) {
    356     StringRef ArchExtBase(ArchExt.substr(2));
    357     for (const auto AE : ARCHExtNames) {
    358       if (AE.NegFeature && ArchExtBase == AE.getName())
    359         return AE.NegFeature;
    360     }
    361   }
    362   for (const auto AE : ARCHExtNames) {
    363     if (AE.Feature && ArchExt == AE.getName())
    364       return AE.Feature;
    365   }
    366 
    367   return nullptr;
    368 }
    369 
    370 StringRef llvm::ARM::getHWDivName(unsigned HWDivKind) {
    371   for (const auto D : HWDivNames) {
    372     if (HWDivKind == D.ID)
    373       return D.getName();
    374   }
    375   return StringRef();
    376 }
    377 
    378 StringRef llvm::ARM::getDefaultCPU(StringRef Arch) {
    379   unsigned AK = parseArch(Arch);
    380   if (AK == ARM::AK_INVALID)
    381     return StringRef();
    382 
    383   // Look for multiple AKs to find the default for pair AK+Name.
    384   for (const auto CPU : CPUNames) {
    385     if (CPU.ArchID == AK && CPU.Default)
    386       return CPU.getName();
    387   }
    388 
    389   // If we can't find a default then target the architecture instead
    390   return "generic";
    391 }
    392 
    393 StringRef llvm::AArch64::getFPUName(unsigned FPUKind) {
    394   return ARM::getFPUName(FPUKind);
    395 }
    396 
    397 unsigned llvm::AArch64::getFPUVersion(unsigned FPUKind) {
    398   return ARM::getFPUVersion(FPUKind);
    399 }
    400 
    401 unsigned llvm::AArch64::getFPUNeonSupportLevel(unsigned FPUKind) {
    402   return ARM::getFPUNeonSupportLevel( FPUKind);
    403 }
    404 
    405 unsigned llvm::AArch64::getFPURestriction(unsigned FPUKind) {
    406   return ARM::getFPURestriction(FPUKind);
    407 }
    408 
    409 unsigned llvm::AArch64::getDefaultFPU(StringRef CPU, unsigned ArchKind) {
    410   if (CPU == "generic")
    411     return AArch64ARCHNames[ArchKind].DefaultFPU;
    412 
    413   return StringSwitch<unsigned>(CPU)
    414 #define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
    415     .Case(NAME, DEFAULT_FPU)
    416 #include "llvm/Support/AArch64TargetParser.def"
    417     .Default(ARM::FK_INVALID);
    418 }
    419 
    420 unsigned llvm::AArch64::getDefaultExtensions(StringRef CPU, unsigned ArchKind) {
    421   if (CPU == "generic")
    422     return AArch64ARCHNames[ArchKind].ArchBaseExtensions;
    423 
    424   return StringSwitch<unsigned>(CPU)
    425 #define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
    426     .Case(NAME, DEFAULT_EXT)
    427 #include "llvm/Support/AArch64TargetParser.def"
    428     .Default(AArch64::AEK_INVALID);
    429 }
    430 
    431 bool llvm::AArch64::getExtensionFeatures(unsigned Extensions,
    432                                      std::vector<const char *> &Features) {
    433 
    434   if (Extensions == AArch64::AEK_INVALID)
    435     return false;
    436 
    437   if (Extensions & AArch64::AEK_FP)
    438     Features.push_back("+fp-armv8");
    439   if (Extensions & AArch64::AEK_SIMD)
    440     Features.push_back("+neon");
    441   if (Extensions & AArch64::AEK_CRC)
    442     Features.push_back("+crc");
    443   if (Extensions & AArch64::AEK_CRYPTO)
    444     Features.push_back("+crypto");
    445   if (Extensions & AArch64::AEK_FP16)
    446     Features.push_back("+fullfp16");
    447   if (Extensions & AArch64::AEK_PROFILE)
    448     Features.push_back("+spe");
    449   if (Extensions & AArch64::AEK_RAS)
    450     Features.push_back("+ras");
    451 
    452   return true;
    453 }
    454 
    455 bool llvm::AArch64::getFPUFeatures(unsigned FPUKind,
    456                                std::vector<const char *> &Features) {
    457   return ARM::getFPUFeatures(FPUKind, Features);
    458 }
    459 
    460 bool llvm::AArch64::getArchFeatures(unsigned ArchKind,
    461                                      std::vector<const char *> &Features) {
    462   if (ArchKind == static_cast<unsigned>(AArch64::ArchKind::AK_ARMV8_1A))
    463     Features.push_back("+v8.1a");
    464   if (ArchKind == static_cast<unsigned>(AArch64::ArchKind::AK_ARMV8_2A))
    465     Features.push_back("+v8.2a");
    466 
    467   return ArchKind > static_cast<unsigned>(AArch64::ArchKind::AK_INVALID) &&
    468          ArchKind < static_cast<unsigned>(AArch64::ArchKind::AK_LAST);
    469 }
    470 
    471 StringRef llvm::AArch64::getArchName(unsigned ArchKind) {
    472   if (ArchKind >= static_cast<unsigned>(AArch64::ArchKind::AK_LAST))
    473     return StringRef();
    474   return AArch64ARCHNames[ArchKind].getName();
    475 }
    476 
    477 StringRef llvm::AArch64::getCPUAttr(unsigned ArchKind) {
    478   if (ArchKind == static_cast<unsigned>(AArch64::ArchKind::AK_INVALID) ||
    479       ArchKind >= static_cast<unsigned>(AArch64::ArchKind::AK_LAST))
    480     return StringRef();
    481   return AArch64ARCHNames[ArchKind].getCPUAttr();
    482 }
    483 
    484 StringRef llvm::AArch64::getSubArch(unsigned ArchKind) {
    485   if (ArchKind == static_cast<unsigned>(AArch64::ArchKind::AK_INVALID) ||
    486       ArchKind >= static_cast<unsigned>(AArch64::ArchKind::AK_LAST))
    487     return StringRef();
    488   return AArch64ARCHNames[ArchKind].getSubArch();
    489 }
    490 
    491 unsigned llvm::AArch64::getArchAttr(unsigned ArchKind) {
    492   if (ArchKind >= static_cast<unsigned>(AArch64::ArchKind::AK_LAST))
    493     return ARMBuildAttrs::CPUArch::v8_A;
    494   return AArch64ARCHNames[ArchKind].ArchAttr;
    495 }
    496 
    497 StringRef llvm::AArch64::getArchExtName(unsigned ArchExtKind) {
    498   for (const auto &AE : AArch64ARCHExtNames)
    499     if (ArchExtKind == AE.ID)
    500       return AE.getName();
    501   return StringRef();
    502 }
    503 
    504 const char *llvm::AArch64::getArchExtFeature(StringRef ArchExt) {
    505   if (ArchExt.startswith("no")) {
    506     StringRef ArchExtBase(ArchExt.substr(2));
    507     for (const auto &AE : AArch64ARCHExtNames) {
    508       if (AE.NegFeature && ArchExtBase == AE.getName())
    509         return AE.NegFeature;
    510     }
    511   }
    512 
    513   for (const auto &AE : AArch64ARCHExtNames)
    514     if (AE.Feature && ArchExt == AE.getName())
    515       return AE.Feature;
    516   return nullptr;
    517 }
    518 
    519 StringRef llvm::AArch64::getDefaultCPU(StringRef Arch) {
    520   unsigned AK = parseArch(Arch);
    521   if (AK == static_cast<unsigned>(AArch64::ArchKind::AK_INVALID))
    522     return StringRef();
    523 
    524   // Look for multiple AKs to find the default for pair AK+Name.
    525   for (const auto &CPU : AArch64CPUNames)
    526     if (static_cast<unsigned>(CPU.ArchID) == AK && CPU.Default)
    527       return CPU.getName();
    528 
    529   // If we can't find a default then target the architecture instead
    530   return "generic";
    531 }
    532 
    533 unsigned llvm::AArch64::checkArchVersion(StringRef Arch) {
    534   if (Arch[0] == 'v' && std::isdigit(Arch[1]))
    535     return (Arch[1] - 48);
    536   return 0;
    537 }
    538 
    539 // ======================================================= //
    540 // Parsers
    541 // ======================================================= //
    542 
    543 static StringRef getHWDivSynonym(StringRef HWDiv) {
    544   return StringSwitch<StringRef>(HWDiv)
    545       .Case("thumb,arm", "arm,thumb")
    546       .Default(HWDiv);
    547 }
    548 
    549 static StringRef getFPUSynonym(StringRef FPU) {
    550   return StringSwitch<StringRef>(FPU)
    551       .Cases("fpa", "fpe2", "fpe3", "maverick", "invalid") // Unsupported
    552       .Case("vfp2", "vfpv2")
    553       .Case("vfp3", "vfpv3")
    554       .Case("vfp4", "vfpv4")
    555       .Case("vfp3-d16", "vfpv3-d16")
    556       .Case("vfp4-d16", "vfpv4-d16")
    557       .Cases("fp4-sp-d16", "vfpv4-sp-d16", "fpv4-sp-d16")
    558       .Cases("fp4-dp-d16", "fpv4-dp-d16", "vfpv4-d16")
    559       .Case("fp5-sp-d16", "fpv5-sp-d16")
    560       .Cases("fp5-dp-d16", "fpv5-dp-d16", "fpv5-d16")
    561       // FIXME: Clang uses it, but it's bogus, since neon defaults to vfpv3.
    562       .Case("neon-vfpv3", "neon")
    563       .Default(FPU);
    564 }
    565 
    566 static StringRef getArchSynonym(StringRef Arch) {
    567   return StringSwitch<StringRef>(Arch)
    568       .Case("v5", "v5t")
    569       .Case("v5e", "v5te")
    570       .Case("v6j", "v6")
    571       .Case("v6hl", "v6k")
    572       .Cases("v6m", "v6sm", "v6s-m", "v6-m")
    573       .Cases("v6z", "v6zk", "v6kz")
    574       .Cases("v7", "v7a", "v7hl", "v7l", "v7-a")
    575       .Case("v7r", "v7-r")
    576       .Case("v7m", "v7-m")
    577       .Case("v7em", "v7e-m")
    578       .Cases("v8", "v8a", "aarch64", "arm64", "v8-a")
    579       .Case("v8.1a", "v8.1-a")
    580       .Case("v8.2a", "v8.2-a")
    581       .Case("v8m.base", "v8-m.base")
    582       .Case("v8m.main", "v8-m.main")
    583       .Default(Arch);
    584 }
    585 
    586 // MArch is expected to be of the form (arm|thumb)?(eb)?(v.+)?(eb)?, but
    587 // (iwmmxt|xscale)(eb)? is also permitted. If the former, return
    588 // "v.+", if the latter, return unmodified string, minus 'eb'.
    589 // If invalid, return empty string.
    590 StringRef llvm::ARM::getCanonicalArchName(StringRef Arch) {
    591   size_t offset = StringRef::npos;
    592   StringRef A = Arch;
    593   StringRef Error = "";
    594 
    595   // Begins with "arm" / "thumb", move past it.
    596   if (A.startswith("arm64"))
    597     offset = 5;
    598   else if (A.startswith("arm"))
    599     offset = 3;
    600   else if (A.startswith("thumb"))
    601     offset = 5;
    602   else if (A.startswith("aarch64")) {
    603     offset = 7;
    604     // AArch64 uses "_be", not "eb" suffix.
    605     if (A.find("eb") != StringRef::npos)
    606       return Error;
    607     if (A.substr(offset, 3) == "_be")
    608       offset += 3;
    609   }
    610 
    611   // Ex. "armebv7", move past the "eb".
    612   if (offset != StringRef::npos && A.substr(offset, 2) == "eb")
    613     offset += 2;
    614   // Or, if it ends with eb ("armv7eb"), chop it off.
    615   else if (A.endswith("eb"))
    616     A = A.substr(0, A.size() - 2);
    617   // Trim the head
    618   if (offset != StringRef::npos)
    619     A = A.substr(offset);
    620 
    621   // Empty string means offset reached the end, which means it's valid.
    622   if (A.empty())
    623     return Arch;
    624 
    625   // Only match non-marketing names
    626   if (offset != StringRef::npos) {
    627     // Must start with 'vN'.
    628     if (A[0] != 'v' || !std::isdigit(A[1]))
    629       return Error;
    630     // Can't have an extra 'eb'.
    631     if (A.find("eb") != StringRef::npos)
    632       return Error;
    633   }
    634 
    635   // Arch will either be a 'v' name (v7a) or a marketing name (xscale).
    636   return A;
    637 }
    638 
    639 unsigned llvm::ARM::parseHWDiv(StringRef HWDiv) {
    640   StringRef Syn = getHWDivSynonym(HWDiv);
    641   for (const auto D : HWDivNames) {
    642     if (Syn == D.getName())
    643       return D.ID;
    644   }
    645   return ARM::AEK_INVALID;
    646 }
    647 
    648 unsigned llvm::ARM::parseFPU(StringRef FPU) {
    649   StringRef Syn = getFPUSynonym(FPU);
    650   for (const auto F : FPUNames) {
    651     if (Syn == F.getName())
    652       return F.ID;
    653   }
    654   return ARM::FK_INVALID;
    655 }
    656 
    657 // Allows partial match, ex. "v7a" matches "armv7a".
    658 unsigned llvm::ARM::parseArch(StringRef Arch) {
    659   Arch = getCanonicalArchName(Arch);
    660   StringRef Syn = getArchSynonym(Arch);
    661   for (const auto A : ARCHNames) {
    662     if (A.getName().endswith(Syn))
    663       return A.ID;
    664   }
    665   return ARM::AK_INVALID;
    666 }
    667 
    668 unsigned llvm::ARM::parseArchExt(StringRef ArchExt) {
    669   for (const auto A : ARCHExtNames) {
    670     if (ArchExt == A.getName())
    671       return A.ID;
    672   }
    673   return ARM::AEK_INVALID;
    674 }
    675 
    676 unsigned llvm::ARM::parseCPUArch(StringRef CPU) {
    677   for (const auto C : CPUNames) {
    678     if (CPU == C.getName())
    679       return C.ArchID;
    680   }
    681   return ARM::AK_INVALID;
    682 }
    683 
    684 // ARM, Thumb, AArch64
    685 unsigned llvm::ARM::parseArchISA(StringRef Arch) {
    686   return StringSwitch<unsigned>(Arch)
    687       .StartsWith("aarch64", ARM::IK_AARCH64)
    688       .StartsWith("arm64", ARM::IK_AARCH64)
    689       .StartsWith("thumb", ARM::IK_THUMB)
    690       .StartsWith("arm", ARM::IK_ARM)
    691       .Default(ARM::IK_INVALID);
    692 }
    693 
    694 // Little/Big endian
    695 unsigned llvm::ARM::parseArchEndian(StringRef Arch) {
    696   if (Arch.startswith("armeb") || Arch.startswith("thumbeb") ||
    697       Arch.startswith("aarch64_be"))
    698     return ARM::EK_BIG;
    699 
    700   if (Arch.startswith("arm") || Arch.startswith("thumb")) {
    701     if (Arch.endswith("eb"))
    702       return ARM::EK_BIG;
    703     else
    704       return ARM::EK_LITTLE;
    705   }
    706 
    707   if (Arch.startswith("aarch64"))
    708     return ARM::EK_LITTLE;
    709 
    710   return ARM::EK_INVALID;
    711 }
    712 
    713 // Profile A/R/M
    714 unsigned llvm::ARM::parseArchProfile(StringRef Arch) {
    715   Arch = getCanonicalArchName(Arch);
    716   switch (parseArch(Arch)) {
    717   case ARM::AK_ARMV6M:
    718   case ARM::AK_ARMV7M:
    719   case ARM::AK_ARMV7EM:
    720   case ARM::AK_ARMV8MMainline:
    721   case ARM::AK_ARMV8MBaseline:
    722     return ARM::PK_M;
    723   case ARM::AK_ARMV7R:
    724     return ARM::PK_R;
    725   case ARM::AK_ARMV7A:
    726   case ARM::AK_ARMV7K:
    727   case ARM::AK_ARMV8A:
    728   case ARM::AK_ARMV8_1A:
    729   case ARM::AK_ARMV8_2A:
    730     return ARM::PK_A;
    731   }
    732   return ARM::PK_INVALID;
    733 }
    734 
    735 // Version number (ex. v7 = 7).
    736 unsigned llvm::ARM::parseArchVersion(StringRef Arch) {
    737   Arch = getCanonicalArchName(Arch);
    738   switch (parseArch(Arch)) {
    739   case ARM::AK_ARMV2:
    740   case ARM::AK_ARMV2A:
    741     return 2;
    742   case ARM::AK_ARMV3:
    743   case ARM::AK_ARMV3M:
    744     return 3;
    745   case ARM::AK_ARMV4:
    746   case ARM::AK_ARMV4T:
    747     return 4;
    748   case ARM::AK_ARMV5T:
    749   case ARM::AK_ARMV5TE:
    750   case ARM::AK_IWMMXT:
    751   case ARM::AK_IWMMXT2:
    752   case ARM::AK_XSCALE:
    753   case ARM::AK_ARMV5TEJ:
    754     return 5;
    755   case ARM::AK_ARMV6:
    756   case ARM::AK_ARMV6K:
    757   case ARM::AK_ARMV6T2:
    758   case ARM::AK_ARMV6KZ:
    759   case ARM::AK_ARMV6M:
    760     return 6;
    761   case ARM::AK_ARMV7A:
    762   case ARM::AK_ARMV7R:
    763   case ARM::AK_ARMV7M:
    764   case ARM::AK_ARMV7S:
    765   case ARM::AK_ARMV7EM:
    766   case ARM::AK_ARMV7K:
    767     return 7;
    768   case ARM::AK_ARMV8A:
    769   case ARM::AK_ARMV8_1A:
    770   case ARM::AK_ARMV8_2A:
    771   case ARM::AK_ARMV8MBaseline:
    772   case ARM::AK_ARMV8MMainline:
    773     return 8;
    774   }
    775   return 0;
    776 }
    777 
    778 StringRef llvm::AArch64::getCanonicalArchName(StringRef Arch) {
    779   return ARM::getCanonicalArchName(Arch);
    780 }
    781 
    782 unsigned llvm::AArch64::parseFPU(StringRef FPU) {
    783   return ARM::parseFPU(FPU);
    784 }
    785 
    786 // Allows partial match, ex. "v8a" matches "armv8a".
    787 unsigned llvm::AArch64::parseArch(StringRef Arch) {
    788   Arch = getCanonicalArchName(Arch);
    789   if (checkArchVersion(Arch) < 8)
    790     return static_cast<unsigned>(AArch64::ArchKind::AK_INVALID);
    791 
    792   StringRef Syn = getArchSynonym(Arch);
    793   for (const auto A : AArch64ARCHNames) {
    794     if (A.getName().endswith(Syn))
    795       return static_cast<unsigned>(A.ID);
    796   }
    797   return static_cast<unsigned>(AArch64::ArchKind::AK_INVALID);
    798 }
    799 
    800 unsigned llvm::AArch64::parseArchExt(StringRef ArchExt) {
    801   for (const auto A : AArch64ARCHExtNames) {
    802     if (ArchExt == A.getName())
    803       return A.ID;
    804   }
    805   return AArch64::AEK_INVALID;
    806 }
    807 
    808 unsigned llvm::AArch64::parseCPUArch(StringRef CPU) {
    809   for (const auto C : AArch64CPUNames) {
    810     if (CPU == C.getName())
    811       return static_cast<unsigned>(C.ArchID);
    812   }
    813   return static_cast<unsigned>(AArch64::ArchKind::AK_INVALID);
    814 }
    815 
    816 // ARM, Thumb, AArch64
    817 unsigned llvm::AArch64::parseArchISA(StringRef Arch) {
    818   return ARM::parseArchISA(Arch);
    819 }
    820 
    821 // Little/Big endian
    822 unsigned llvm::AArch64::parseArchEndian(StringRef Arch) {
    823   return ARM::parseArchEndian(Arch);
    824 }
    825 
    826 // Profile A/R/M
    827 unsigned llvm::AArch64::parseArchProfile(StringRef Arch) {
    828   return ARM::parseArchProfile(Arch);
    829 }
    830 
    831 // Version number (ex. v8 = 8).
    832 unsigned llvm::AArch64::parseArchVersion(StringRef Arch) {
    833   return ARM::parseArchVersion(Arch);
    834 }
    835