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