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<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_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<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   return getHWDivFeatures(Extensions, Features);
    238 }
    239 
    240 bool llvm::ARM::getFPUFeatures(unsigned FPUKind,
    241                                std::vector<StringRef> &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 StringRef 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 StringRef(AE.NegFeature);
    360     }
    361   }
    362   for (const auto AE : ARCHExtNames) {
    363     if (AE.Feature && ArchExt == AE.getName())
    364       return StringRef(AE.Feature);
    365   }
    366 
    367   return StringRef();
    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<StringRef> &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<StringRef> &Features) {
    457   return ARM::getFPUFeatures(FPUKind, Features);
    458 }
    459 
    460 bool llvm::AArch64::getArchFeatures(unsigned ArchKind,
    461                                      std::vector<StringRef> &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 StringRef 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 StringRef(AE.NegFeature);
    510     }
    511   }
    512 
    513   for (const auto &AE : AArch64ARCHExtNames)
    514     if (AE.Feature && ArchExt == AE.getName())
    515       return StringRef(AE.Feature);
    516   return StringRef();
    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("v8r", "v8-r")
    582       .Case("v8m.base", "v8-m.base")
    583       .Case("v8m.main", "v8-m.main")
    584       .Default(Arch);
    585 }
    586 
    587 // MArch is expected to be of the form (arm|thumb)?(eb)?(v.+)?(eb)?, but
    588 // (iwmmxt|xscale)(eb)? is also permitted. If the former, return
    589 // "v.+", if the latter, return unmodified string, minus 'eb'.
    590 // If invalid, return empty string.
    591 StringRef llvm::ARM::getCanonicalArchName(StringRef Arch) {
    592   size_t offset = StringRef::npos;
    593   StringRef A = Arch;
    594   StringRef Error = "";
    595 
    596   // Begins with "arm" / "thumb", move past it.
    597   if (A.startswith("arm64"))
    598     offset = 5;
    599   else if (A.startswith("arm"))
    600     offset = 3;
    601   else if (A.startswith("thumb"))
    602     offset = 5;
    603   else if (A.startswith("aarch64")) {
    604     offset = 7;
    605     // AArch64 uses "_be", not "eb" suffix.
    606     if (A.find("eb") != StringRef::npos)
    607       return Error;
    608     if (A.substr(offset, 3) == "_be")
    609       offset += 3;
    610   }
    611 
    612   // Ex. "armebv7", move past the "eb".
    613   if (offset != StringRef::npos && A.substr(offset, 2) == "eb")
    614     offset += 2;
    615   // Or, if it ends with eb ("armv7eb"), chop it off.
    616   else if (A.endswith("eb"))
    617     A = A.substr(0, A.size() - 2);
    618   // Trim the head
    619   if (offset != StringRef::npos)
    620     A = A.substr(offset);
    621 
    622   // Empty string means offset reached the end, which means it's valid.
    623   if (A.empty())
    624     return Arch;
    625 
    626   // Only match non-marketing names
    627   if (offset != StringRef::npos) {
    628     // Must start with 'vN'.
    629     if (A[0] != 'v' || !std::isdigit(A[1]))
    630       return Error;
    631     // Can't have an extra 'eb'.
    632     if (A.find("eb") != StringRef::npos)
    633       return Error;
    634   }
    635 
    636   // Arch will either be a 'v' name (v7a) or a marketing name (xscale).
    637   return A;
    638 }
    639 
    640 unsigned llvm::ARM::parseHWDiv(StringRef HWDiv) {
    641   StringRef Syn = getHWDivSynonym(HWDiv);
    642   for (const auto D : HWDivNames) {
    643     if (Syn == D.getName())
    644       return D.ID;
    645   }
    646   return ARM::AEK_INVALID;
    647 }
    648 
    649 unsigned llvm::ARM::parseFPU(StringRef FPU) {
    650   StringRef Syn = getFPUSynonym(FPU);
    651   for (const auto F : FPUNames) {
    652     if (Syn == F.getName())
    653       return F.ID;
    654   }
    655   return ARM::FK_INVALID;
    656 }
    657 
    658 // Allows partial match, ex. "v7a" matches "armv7a".
    659 unsigned llvm::ARM::parseArch(StringRef Arch) {
    660   Arch = getCanonicalArchName(Arch);
    661   StringRef Syn = getArchSynonym(Arch);
    662   for (const auto A : ARCHNames) {
    663     if (A.getName().endswith(Syn))
    664       return A.ID;
    665   }
    666   return ARM::AK_INVALID;
    667 }
    668 
    669 unsigned llvm::ARM::parseArchExt(StringRef ArchExt) {
    670   for (const auto A : ARCHExtNames) {
    671     if (ArchExt == A.getName())
    672       return A.ID;
    673   }
    674   return ARM::AEK_INVALID;
    675 }
    676 
    677 unsigned llvm::ARM::parseCPUArch(StringRef CPU) {
    678   for (const auto C : CPUNames) {
    679     if (CPU == C.getName())
    680       return C.ArchID;
    681   }
    682   return ARM::AK_INVALID;
    683 }
    684 
    685 // ARM, Thumb, AArch64
    686 unsigned llvm::ARM::parseArchISA(StringRef Arch) {
    687   return StringSwitch<unsigned>(Arch)
    688       .StartsWith("aarch64", ARM::IK_AARCH64)
    689       .StartsWith("arm64", ARM::IK_AARCH64)
    690       .StartsWith("thumb", ARM::IK_THUMB)
    691       .StartsWith("arm", ARM::IK_ARM)
    692       .Default(ARM::IK_INVALID);
    693 }
    694 
    695 // Little/Big endian
    696 unsigned llvm::ARM::parseArchEndian(StringRef Arch) {
    697   if (Arch.startswith("armeb") || Arch.startswith("thumbeb") ||
    698       Arch.startswith("aarch64_be"))
    699     return ARM::EK_BIG;
    700 
    701   if (Arch.startswith("arm") || Arch.startswith("thumb")) {
    702     if (Arch.endswith("eb"))
    703       return ARM::EK_BIG;
    704     else
    705       return ARM::EK_LITTLE;
    706   }
    707 
    708   if (Arch.startswith("aarch64"))
    709     return ARM::EK_LITTLE;
    710 
    711   return ARM::EK_INVALID;
    712 }
    713 
    714 // Profile A/R/M
    715 unsigned llvm::ARM::parseArchProfile(StringRef Arch) {
    716   Arch = getCanonicalArchName(Arch);
    717   switch (parseArch(Arch)) {
    718   case ARM::AK_ARMV6M:
    719   case ARM::AK_ARMV7M:
    720   case ARM::AK_ARMV7EM:
    721   case ARM::AK_ARMV8MMainline:
    722   case ARM::AK_ARMV8MBaseline:
    723     return ARM::PK_M;
    724   case ARM::AK_ARMV7R:
    725   case ARM::AK_ARMV8R:
    726     return ARM::PK_R;
    727   case ARM::AK_ARMV7A:
    728   case ARM::AK_ARMV7K:
    729   case ARM::AK_ARMV8A:
    730   case ARM::AK_ARMV8_1A:
    731   case ARM::AK_ARMV8_2A:
    732     return ARM::PK_A;
    733   }
    734   return ARM::PK_INVALID;
    735 }
    736 
    737 // Version number (ex. v7 = 7).
    738 unsigned llvm::ARM::parseArchVersion(StringRef Arch) {
    739   Arch = getCanonicalArchName(Arch);
    740   switch (parseArch(Arch)) {
    741   case ARM::AK_ARMV2:
    742   case ARM::AK_ARMV2A:
    743     return 2;
    744   case ARM::AK_ARMV3:
    745   case ARM::AK_ARMV3M:
    746     return 3;
    747   case ARM::AK_ARMV4:
    748   case ARM::AK_ARMV4T:
    749     return 4;
    750   case ARM::AK_ARMV5T:
    751   case ARM::AK_ARMV5TE:
    752   case ARM::AK_IWMMXT:
    753   case ARM::AK_IWMMXT2:
    754   case ARM::AK_XSCALE:
    755   case ARM::AK_ARMV5TEJ:
    756     return 5;
    757   case ARM::AK_ARMV6:
    758   case ARM::AK_ARMV6K:
    759   case ARM::AK_ARMV6T2:
    760   case ARM::AK_ARMV6KZ:
    761   case ARM::AK_ARMV6M:
    762     return 6;
    763   case ARM::AK_ARMV7A:
    764   case ARM::AK_ARMV7R:
    765   case ARM::AK_ARMV7M:
    766   case ARM::AK_ARMV7S:
    767   case ARM::AK_ARMV7EM:
    768   case ARM::AK_ARMV7K:
    769     return 7;
    770   case ARM::AK_ARMV8A:
    771   case ARM::AK_ARMV8_1A:
    772   case ARM::AK_ARMV8_2A:
    773   case ARM::AK_ARMV8R:
    774   case ARM::AK_ARMV8MBaseline:
    775   case ARM::AK_ARMV8MMainline:
    776     return 8;
    777   }
    778   return 0;
    779 }
    780 
    781 StringRef llvm::AArch64::getCanonicalArchName(StringRef Arch) {
    782   return ARM::getCanonicalArchName(Arch);
    783 }
    784 
    785 unsigned llvm::AArch64::parseFPU(StringRef FPU) {
    786   return ARM::parseFPU(FPU);
    787 }
    788 
    789 // Allows partial match, ex. "v8a" matches "armv8a".
    790 unsigned llvm::AArch64::parseArch(StringRef Arch) {
    791   Arch = getCanonicalArchName(Arch);
    792   if (checkArchVersion(Arch) < 8)
    793     return static_cast<unsigned>(AArch64::ArchKind::AK_INVALID);
    794 
    795   StringRef Syn = getArchSynonym(Arch);
    796   for (const auto A : AArch64ARCHNames) {
    797     if (A.getName().endswith(Syn))
    798       return static_cast<unsigned>(A.ID);
    799   }
    800   return static_cast<unsigned>(AArch64::ArchKind::AK_INVALID);
    801 }
    802 
    803 unsigned llvm::AArch64::parseArchExt(StringRef ArchExt) {
    804   for (const auto A : AArch64ARCHExtNames) {
    805     if (ArchExt == A.getName())
    806       return A.ID;
    807   }
    808   return AArch64::AEK_INVALID;
    809 }
    810 
    811 unsigned llvm::AArch64::parseCPUArch(StringRef CPU) {
    812   for (const auto C : AArch64CPUNames) {
    813     if (CPU == C.getName())
    814       return static_cast<unsigned>(C.ArchID);
    815   }
    816   return static_cast<unsigned>(AArch64::ArchKind::AK_INVALID);
    817 }
    818 
    819 // ARM, Thumb, AArch64
    820 unsigned llvm::AArch64::parseArchISA(StringRef Arch) {
    821   return ARM::parseArchISA(Arch);
    822 }
    823 
    824 // Little/Big endian
    825 unsigned llvm::AArch64::parseArchEndian(StringRef Arch) {
    826   return ARM::parseArchEndian(Arch);
    827 }
    828 
    829 // Profile A/R/M
    830 unsigned llvm::AArch64::parseArchProfile(StringRef Arch) {
    831   return ARM::parseArchProfile(Arch);
    832 }
    833 
    834 // Version number (ex. v8 = 8).
    835 unsigned llvm::AArch64::parseArchVersion(StringRef Arch) {
    836   return ARM::parseArchVersion(Arch);
    837 }
    838