1ff0cc061SDimitry Andric //===-- TargetParser - Parser for target features ---------------*- C++ -*-===//
2ff0cc061SDimitry Andric //
3ff0cc061SDimitry Andric //                     The LLVM Compiler Infrastructure
4ff0cc061SDimitry Andric //
5ff0cc061SDimitry Andric // This file is distributed under the University of Illinois Open Source
6ff0cc061SDimitry Andric // License. See LICENSE.TXT for details.
7ff0cc061SDimitry Andric //
8ff0cc061SDimitry Andric //===----------------------------------------------------------------------===//
9ff0cc061SDimitry Andric //
10ff0cc061SDimitry Andric // This file implements a target parser to recognise hardware features such as
11ff0cc061SDimitry Andric // FPU/CPU/ARCH names as well as specific support such as HDIV, etc.
12ff0cc061SDimitry Andric //
13ff0cc061SDimitry Andric //===----------------------------------------------------------------------===//
14ff0cc061SDimitry Andric 
15ff0cc061SDimitry Andric #include "llvm/Support/ARMBuildAttributes.h"
16ff0cc061SDimitry Andric #include "llvm/Support/TargetParser.h"
17ff0cc061SDimitry Andric #include "llvm/ADT/StringExtras.h"
18ff0cc061SDimitry Andric #include "llvm/ADT/StringSwitch.h"
197d523365SDimitry Andric #include "llvm/ADT/Twine.h"
20ff0cc061SDimitry Andric #include <cctype>
21ff0cc061SDimitry Andric 
22ff0cc061SDimitry Andric using namespace llvm;
237d523365SDimitry Andric using namespace ARM;
243ca95b02SDimitry Andric using namespace AArch64;
25ff0cc061SDimitry Andric 
26ff0cc061SDimitry Andric namespace {
27ff0cc061SDimitry Andric 
2897bc6c73SDimitry Andric // List of canonical FPU names (use getFPUSynonym) and which architectural
2997bc6c73SDimitry Andric // features they correspond to (use getFPUFeatures).
30ff0cc061SDimitry Andric // FIXME: TableGen this.
313dac3a9bSDimitry Andric // The entries must appear in the order listed in ARM::FPUKind for correct indexing
327d523365SDimitry Andric static const struct {
337d523365SDimitry Andric   const char *NameCStr;
347d523365SDimitry Andric   size_t NameLength;
35ff0cc061SDimitry Andric   ARM::FPUKind ID;
363dac3a9bSDimitry Andric   ARM::FPUVersion FPUVersion;
3797bc6c73SDimitry Andric   ARM::NeonSupportLevel NeonSupport;
3897bc6c73SDimitry Andric   ARM::FPURestriction Restriction;
397d523365SDimitry Andric 
407d523365SDimitry Andric   StringRef getName() const { return StringRef(NameCStr, NameLength); }
41ff0cc061SDimitry Andric } FPUNames[] = {
427d523365SDimitry Andric #define ARM_FPU(NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION) \
437d523365SDimitry Andric   { NAME, sizeof(NAME) - 1, KIND, VERSION, NEON_SUPPORT, RESTRICTION },
447d523365SDimitry Andric #include "llvm/Support/ARMTargetParser.def"
45ff0cc061SDimitry Andric };
4697bc6c73SDimitry Andric 
4797bc6c73SDimitry Andric // List of canonical arch names (use getArchSynonym).
4897bc6c73SDimitry Andric // This table also provides the build attribute fields for CPU arch
4997bc6c73SDimitry Andric // and Arch ID, according to the Addenda to the ARM ABI, chapters
5097bc6c73SDimitry Andric // 2.4 and 2.3.5.2 respectively.
5197bc6c73SDimitry Andric // FIXME: SubArch values were simplified to fit into the expectations
5297bc6c73SDimitry Andric // of the triples and are not conforming with their official names.
5397bc6c73SDimitry Andric // Check to see if the expectation should be changed.
54ff0cc061SDimitry Andric // FIXME: TableGen this.
557d523365SDimitry Andric static const struct {
567d523365SDimitry Andric   const char *NameCStr;
577d523365SDimitry Andric   size_t NameLength;
587d523365SDimitry Andric   const char *CPUAttrCStr;
597d523365SDimitry Andric   size_t CPUAttrLength;
607d523365SDimitry Andric   const char *SubArchCStr;
617d523365SDimitry Andric   size_t SubArchLength;
627d523365SDimitry Andric   unsigned DefaultFPU;
637d523365SDimitry Andric   unsigned ArchBaseExtensions;
64ff0cc061SDimitry Andric   ARM::ArchKind ID;
6597bc6c73SDimitry Andric   ARMBuildAttrs::CPUArch ArchAttr; // Arch ID in build attributes.
667d523365SDimitry Andric 
677d523365SDimitry Andric   StringRef getName() const { return StringRef(NameCStr, NameLength); }
687d523365SDimitry Andric 
697d523365SDimitry Andric   // CPU class in build attributes.
707d523365SDimitry Andric   StringRef getCPUAttr() const { return StringRef(CPUAttrCStr, CPUAttrLength); }
717d523365SDimitry Andric 
727d523365SDimitry Andric   // Sub-Arch name.
737d523365SDimitry Andric   StringRef getSubArch() const { return StringRef(SubArchCStr, SubArchLength); }
74ff0cc061SDimitry Andric } ARCHNames[] = {
757d523365SDimitry Andric #define ARM_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT)       \
767d523365SDimitry Andric   {NAME, sizeof(NAME) - 1, CPU_ATTR, sizeof(CPU_ATTR) - 1, SUB_ARCH,       \
777d523365SDimitry Andric    sizeof(SUB_ARCH) - 1, ARCH_FPU, ARCH_BASE_EXT, ID, ARCH_ATTR},
787d523365SDimitry Andric #include "llvm/Support/ARMTargetParser.def"
793ca95b02SDimitry Andric },AArch64ARCHNames[] = {
803ca95b02SDimitry Andric #define AARCH64_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT)       \
813ca95b02SDimitry Andric   {NAME, sizeof(NAME) - 1, CPU_ATTR, sizeof(CPU_ATTR) - 1, SUB_ARCH,       \
823ca95b02SDimitry Andric    sizeof(SUB_ARCH) - 1, ARCH_FPU, ARCH_BASE_EXT, ID, ARCH_ATTR},
833ca95b02SDimitry Andric #include "llvm/Support/AArch64TargetParser.def"
84ff0cc061SDimitry Andric };
857d523365SDimitry Andric 
8697bc6c73SDimitry Andric // List of Arch Extension names.
87ff0cc061SDimitry Andric // FIXME: TableGen this.
887d523365SDimitry Andric static const struct {
897d523365SDimitry Andric   const char *NameCStr;
907d523365SDimitry Andric   size_t NameLength;
917d523365SDimitry Andric   unsigned ID;
927d523365SDimitry Andric   const char *Feature;
937d523365SDimitry Andric   const char *NegFeature;
947d523365SDimitry Andric 
957d523365SDimitry Andric   StringRef getName() const { return StringRef(NameCStr, NameLength); }
96ff0cc061SDimitry Andric } ARCHExtNames[] = {
977d523365SDimitry Andric #define ARM_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE) \
987d523365SDimitry Andric   { NAME, sizeof(NAME) - 1, ID, FEATURE, NEGFEATURE },
997d523365SDimitry Andric #include "llvm/Support/ARMTargetParser.def"
1003ca95b02SDimitry Andric },AArch64ARCHExtNames[] = {
1013ca95b02SDimitry Andric #define AARCH64_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE) \
1023ca95b02SDimitry Andric   { NAME, sizeof(NAME) - 1, ID, FEATURE, NEGFEATURE },
1033ca95b02SDimitry Andric #include "llvm/Support/AArch64TargetParser.def"
104ff0cc061SDimitry Andric };
1057d523365SDimitry Andric 
1067d523365SDimitry Andric // List of HWDiv names (use getHWDivSynonym) and which architectural
1077d523365SDimitry Andric // features they correspond to (use getHWDivFeatures).
1087d523365SDimitry Andric // FIXME: TableGen this.
1097d523365SDimitry Andric static const struct {
1107d523365SDimitry Andric   const char *NameCStr;
1117d523365SDimitry Andric   size_t NameLength;
1127d523365SDimitry Andric   unsigned ID;
1137d523365SDimitry Andric 
1147d523365SDimitry Andric   StringRef getName() const { return StringRef(NameCStr, NameLength); }
1157d523365SDimitry Andric } HWDivNames[] = {
1167d523365SDimitry Andric #define ARM_HW_DIV_NAME(NAME, ID) { NAME, sizeof(NAME) - 1, ID },
1177d523365SDimitry Andric #include "llvm/Support/ARMTargetParser.def"
1187d523365SDimitry Andric };
1197d523365SDimitry Andric 
120ff0cc061SDimitry Andric // List of CPU names and their arches.
121ff0cc061SDimitry Andric // The same CPU can have multiple arches and can be default on multiple arches.
122ff0cc061SDimitry Andric // When finding the Arch for a CPU, first-found prevails. Sort them accordingly.
12397bc6c73SDimitry Andric // When this becomes table-generated, we'd probably need two tables.
124ff0cc061SDimitry Andric // FIXME: TableGen this.
1257d523365SDimitry Andric static const struct {
1267d523365SDimitry Andric   const char *NameCStr;
1277d523365SDimitry Andric   size_t NameLength;
128ff0cc061SDimitry Andric   ARM::ArchKind ArchID;
1297d523365SDimitry Andric   bool Default; // is $Name the default CPU for $ArchID ?
1307d523365SDimitry Andric   unsigned DefaultExtensions;
1317d523365SDimitry Andric 
1327d523365SDimitry Andric   StringRef getName() const { return StringRef(NameCStr, NameLength); }
133ff0cc061SDimitry Andric } CPUNames[] = {
1347d523365SDimitry Andric #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
1357d523365SDimitry Andric   { NAME, sizeof(NAME) - 1, ID, IS_DEFAULT, DEFAULT_EXT },
1367d523365SDimitry Andric #include "llvm/Support/ARMTargetParser.def"
1373ca95b02SDimitry Andric },AArch64CPUNames[] = {
1383ca95b02SDimitry Andric #define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
1393ca95b02SDimitry Andric   { NAME, sizeof(NAME) - 1, ID, IS_DEFAULT, DEFAULT_EXT },
1403ca95b02SDimitry Andric #include "llvm/Support/AArch64TargetParser.def"
141ff0cc061SDimitry Andric };
142ff0cc061SDimitry Andric 
143ff0cc061SDimitry Andric } // namespace
144ff0cc061SDimitry Andric 
145ff0cc061SDimitry Andric // ======================================================= //
146ff0cc061SDimitry Andric // Information by ID
147ff0cc061SDimitry Andric // ======================================================= //
148ff0cc061SDimitry Andric 
1497d523365SDimitry Andric StringRef llvm::ARM::getFPUName(unsigned FPUKind) {
150ff0cc061SDimitry Andric   if (FPUKind >= ARM::FK_LAST)
1517d523365SDimitry Andric     return StringRef();
1527d523365SDimitry Andric   return FPUNames[FPUKind].getName();
153ff0cc061SDimitry Andric }
154ff0cc061SDimitry Andric 
1557d523365SDimitry Andric unsigned llvm::ARM::getFPUVersion(unsigned FPUKind) {
15697bc6c73SDimitry Andric   if (FPUKind >= ARM::FK_LAST)
15797bc6c73SDimitry Andric     return 0;
15897bc6c73SDimitry Andric   return FPUNames[FPUKind].FPUVersion;
15997bc6c73SDimitry Andric }
16097bc6c73SDimitry Andric 
1617d523365SDimitry Andric unsigned llvm::ARM::getFPUNeonSupportLevel(unsigned FPUKind) {
16297bc6c73SDimitry Andric   if (FPUKind >= ARM::FK_LAST)
16397bc6c73SDimitry Andric     return 0;
16497bc6c73SDimitry Andric   return FPUNames[FPUKind].NeonSupport;
16597bc6c73SDimitry Andric }
16697bc6c73SDimitry Andric 
1677d523365SDimitry Andric unsigned llvm::ARM::getFPURestriction(unsigned FPUKind) {
16897bc6c73SDimitry Andric   if (FPUKind >= ARM::FK_LAST)
16997bc6c73SDimitry Andric     return 0;
17097bc6c73SDimitry Andric   return FPUNames[FPUKind].Restriction;
17197bc6c73SDimitry Andric }
17297bc6c73SDimitry Andric 
1737d523365SDimitry Andric unsigned llvm::ARM::getDefaultFPU(StringRef CPU, unsigned ArchKind) {
1747d523365SDimitry Andric   if (CPU == "generic")
1757d523365SDimitry Andric     return ARCHNames[ArchKind].DefaultFPU;
1767d523365SDimitry Andric 
1777d523365SDimitry Andric   return StringSwitch<unsigned>(CPU)
1787d523365SDimitry Andric #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
1797d523365SDimitry Andric     .Case(NAME, DEFAULT_FPU)
1807d523365SDimitry Andric #include "llvm/Support/ARMTargetParser.def"
1817d523365SDimitry Andric     .Default(ARM::FK_INVALID);
1827d523365SDimitry Andric }
1837d523365SDimitry Andric 
1847d523365SDimitry Andric unsigned llvm::ARM::getDefaultExtensions(StringRef CPU, unsigned ArchKind) {
1857d523365SDimitry Andric   if (CPU == "generic")
1867d523365SDimitry Andric     return ARCHNames[ArchKind].ArchBaseExtensions;
1877d523365SDimitry Andric 
1887d523365SDimitry Andric   return StringSwitch<unsigned>(CPU)
1897d523365SDimitry Andric #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
1907d523365SDimitry Andric     .Case(NAME, ARCHNames[ID].ArchBaseExtensions | DEFAULT_EXT)
1917d523365SDimitry Andric #include "llvm/Support/ARMTargetParser.def"
1927d523365SDimitry Andric     .Default(ARM::AEK_INVALID);
1937d523365SDimitry Andric }
1947d523365SDimitry Andric 
1957d523365SDimitry Andric bool llvm::ARM::getHWDivFeatures(unsigned HWDivKind,
1967d523365SDimitry Andric                                  std::vector<const char *> &Features) {
1977d523365SDimitry Andric 
1987d523365SDimitry Andric   if (HWDivKind == ARM::AEK_INVALID)
1997d523365SDimitry Andric     return false;
2007d523365SDimitry Andric 
2017d523365SDimitry Andric   if (HWDivKind & ARM::AEK_HWDIVARM)
2027d523365SDimitry Andric     Features.push_back("+hwdiv-arm");
2037d523365SDimitry Andric   else
2047d523365SDimitry Andric     Features.push_back("-hwdiv-arm");
2057d523365SDimitry Andric 
2067d523365SDimitry Andric   if (HWDivKind & ARM::AEK_HWDIV)
2077d523365SDimitry Andric     Features.push_back("+hwdiv");
2087d523365SDimitry Andric   else
2097d523365SDimitry Andric     Features.push_back("-hwdiv");
2107d523365SDimitry Andric 
2117d523365SDimitry Andric   return true;
2127d523365SDimitry Andric }
2137d523365SDimitry Andric 
2147d523365SDimitry Andric bool llvm::ARM::getExtensionFeatures(unsigned Extensions,
2157d523365SDimitry Andric                                      std::vector<const char *> &Features) {
2167d523365SDimitry Andric 
2177d523365SDimitry Andric   if (Extensions == ARM::AEK_INVALID)
2187d523365SDimitry Andric     return false;
2197d523365SDimitry Andric 
2207d523365SDimitry Andric   if (Extensions & ARM::AEK_CRC)
2217d523365SDimitry Andric     Features.push_back("+crc");
2227d523365SDimitry Andric   else
2237d523365SDimitry Andric     Features.push_back("-crc");
2247d523365SDimitry Andric 
2257d523365SDimitry Andric   if (Extensions & ARM::AEK_DSP)
2267d523365SDimitry Andric     Features.push_back("+dsp");
2277d523365SDimitry Andric   else
2287d523365SDimitry Andric     Features.push_back("-dsp");
2297d523365SDimitry Andric 
2307d523365SDimitry Andric   return getHWDivFeatures(Extensions, Features);
2317d523365SDimitry Andric }
2327d523365SDimitry Andric 
2337d523365SDimitry Andric bool llvm::ARM::getFPUFeatures(unsigned FPUKind,
23497bc6c73SDimitry Andric                                std::vector<const char *> &Features) {
23597bc6c73SDimitry Andric 
23697bc6c73SDimitry Andric   if (FPUKind >= ARM::FK_LAST || FPUKind == ARM::FK_INVALID)
23797bc6c73SDimitry Andric     return false;
23897bc6c73SDimitry Andric 
23997bc6c73SDimitry Andric   // fp-only-sp and d16 subtarget features are independent of each other, so we
24097bc6c73SDimitry Andric   // must enable/disable both.
24197bc6c73SDimitry Andric   switch (FPUNames[FPUKind].Restriction) {
24297bc6c73SDimitry Andric   case ARM::FR_SP_D16:
24397bc6c73SDimitry Andric     Features.push_back("+fp-only-sp");
24497bc6c73SDimitry Andric     Features.push_back("+d16");
24597bc6c73SDimitry Andric     break;
24697bc6c73SDimitry Andric   case ARM::FR_D16:
24797bc6c73SDimitry Andric     Features.push_back("-fp-only-sp");
24897bc6c73SDimitry Andric     Features.push_back("+d16");
24997bc6c73SDimitry Andric     break;
25097bc6c73SDimitry Andric   case ARM::FR_None:
25197bc6c73SDimitry Andric     Features.push_back("-fp-only-sp");
25297bc6c73SDimitry Andric     Features.push_back("-d16");
25397bc6c73SDimitry Andric     break;
25497bc6c73SDimitry Andric   }
25597bc6c73SDimitry Andric 
25697bc6c73SDimitry Andric   // FPU version subtarget features are inclusive of lower-numbered ones, so
25797bc6c73SDimitry Andric   // enable the one corresponding to this version and disable all that are
2588f0fd8f6SDimitry Andric   // higher. We also have to make sure to disable fp16 when vfp4 is disabled,
2598f0fd8f6SDimitry Andric   // as +vfp4 implies +fp16 but -vfp4 does not imply -fp16.
26097bc6c73SDimitry Andric   switch (FPUNames[FPUKind].FPUVersion) {
2613dac3a9bSDimitry Andric   case ARM::FV_VFPV5:
26297bc6c73SDimitry Andric     Features.push_back("+fp-armv8");
26397bc6c73SDimitry Andric     break;
2643dac3a9bSDimitry Andric   case ARM::FV_VFPV4:
26597bc6c73SDimitry Andric     Features.push_back("+vfp4");
26697bc6c73SDimitry Andric     Features.push_back("-fp-armv8");
26797bc6c73SDimitry Andric     break;
2683dac3a9bSDimitry Andric   case ARM::FV_VFPV3_FP16:
2693dac3a9bSDimitry Andric     Features.push_back("+vfp3");
2703dac3a9bSDimitry Andric     Features.push_back("+fp16");
2713dac3a9bSDimitry Andric     Features.push_back("-vfp4");
2723dac3a9bSDimitry Andric     Features.push_back("-fp-armv8");
2733dac3a9bSDimitry Andric     break;
2743dac3a9bSDimitry Andric   case ARM::FV_VFPV3:
27597bc6c73SDimitry Andric     Features.push_back("+vfp3");
2768f0fd8f6SDimitry Andric     Features.push_back("-fp16");
27797bc6c73SDimitry Andric     Features.push_back("-vfp4");
27897bc6c73SDimitry Andric     Features.push_back("-fp-armv8");
27997bc6c73SDimitry Andric     break;
2803dac3a9bSDimitry Andric   case ARM::FV_VFPV2:
28197bc6c73SDimitry Andric     Features.push_back("+vfp2");
28297bc6c73SDimitry Andric     Features.push_back("-vfp3");
2838f0fd8f6SDimitry Andric     Features.push_back("-fp16");
28497bc6c73SDimitry Andric     Features.push_back("-vfp4");
28597bc6c73SDimitry Andric     Features.push_back("-fp-armv8");
28697bc6c73SDimitry Andric     break;
2873dac3a9bSDimitry Andric   case ARM::FV_NONE:
28897bc6c73SDimitry Andric     Features.push_back("-vfp2");
28997bc6c73SDimitry Andric     Features.push_back("-vfp3");
2908f0fd8f6SDimitry Andric     Features.push_back("-fp16");
29197bc6c73SDimitry Andric     Features.push_back("-vfp4");
29297bc6c73SDimitry Andric     Features.push_back("-fp-armv8");
29397bc6c73SDimitry Andric     break;
29497bc6c73SDimitry Andric   }
29597bc6c73SDimitry Andric 
29697bc6c73SDimitry Andric   // crypto includes neon, so we handle this similarly to FPU version.
29797bc6c73SDimitry Andric   switch (FPUNames[FPUKind].NeonSupport) {
29897bc6c73SDimitry Andric   case ARM::NS_Crypto:
2997d523365SDimitry Andric     Features.push_back("+neon");
30097bc6c73SDimitry Andric     Features.push_back("+crypto");
30197bc6c73SDimitry Andric     break;
30297bc6c73SDimitry Andric   case ARM::NS_Neon:
30397bc6c73SDimitry Andric     Features.push_back("+neon");
30497bc6c73SDimitry Andric     Features.push_back("-crypto");
30597bc6c73SDimitry Andric     break;
30697bc6c73SDimitry Andric   case ARM::NS_None:
30797bc6c73SDimitry Andric     Features.push_back("-neon");
30897bc6c73SDimitry Andric     Features.push_back("-crypto");
30997bc6c73SDimitry Andric     break;
31097bc6c73SDimitry Andric   }
31197bc6c73SDimitry Andric 
31297bc6c73SDimitry Andric   return true;
31397bc6c73SDimitry Andric }
31497bc6c73SDimitry Andric 
3157d523365SDimitry Andric StringRef llvm::ARM::getArchName(unsigned ArchKind) {
316ff0cc061SDimitry Andric   if (ArchKind >= ARM::AK_LAST)
3177d523365SDimitry Andric     return StringRef();
3187d523365SDimitry Andric   return ARCHNames[ArchKind].getName();
319ff0cc061SDimitry Andric }
320ff0cc061SDimitry Andric 
3217d523365SDimitry Andric StringRef llvm::ARM::getCPUAttr(unsigned ArchKind) {
3223ca95b02SDimitry Andric   if (ArchKind == ARM::AK_INVALID || ArchKind >= ARM::AK_LAST)
3237d523365SDimitry Andric     return StringRef();
3247d523365SDimitry Andric   return ARCHNames[ArchKind].getCPUAttr();
325ff0cc061SDimitry Andric }
326ff0cc061SDimitry Andric 
3277d523365SDimitry Andric StringRef llvm::ARM::getSubArch(unsigned ArchKind) {
3283ca95b02SDimitry Andric   if (ArchKind == ARM::AK_INVALID || ArchKind >= ARM::AK_LAST)
3297d523365SDimitry Andric     return StringRef();
3307d523365SDimitry Andric   return ARCHNames[ArchKind].getSubArch();
33197bc6c73SDimitry Andric }
33297bc6c73SDimitry Andric 
3337d523365SDimitry Andric unsigned llvm::ARM::getArchAttr(unsigned ArchKind) {
334ff0cc061SDimitry Andric   if (ArchKind >= ARM::AK_LAST)
335ff0cc061SDimitry Andric     return ARMBuildAttrs::CPUArch::Pre_v4;
33697bc6c73SDimitry Andric   return ARCHNames[ArchKind].ArchAttr;
337ff0cc061SDimitry Andric }
338ff0cc061SDimitry Andric 
3397d523365SDimitry Andric StringRef llvm::ARM::getArchExtName(unsigned ArchExtKind) {
3407d523365SDimitry Andric   for (const auto AE : ARCHExtNames) {
3417d523365SDimitry Andric     if (ArchExtKind == AE.ID)
3427d523365SDimitry Andric       return AE.getName();
3437d523365SDimitry Andric   }
3447d523365SDimitry Andric   return StringRef();
345ff0cc061SDimitry Andric }
346ff0cc061SDimitry Andric 
3477d523365SDimitry Andric const char *llvm::ARM::getArchExtFeature(StringRef ArchExt) {
3487d523365SDimitry Andric   if (ArchExt.startswith("no")) {
3497d523365SDimitry Andric     StringRef ArchExtBase(ArchExt.substr(2));
3507d523365SDimitry Andric     for (const auto AE : ARCHExtNames) {
3517d523365SDimitry Andric       if (AE.NegFeature && ArchExtBase == AE.getName())
3527d523365SDimitry Andric         return AE.NegFeature;
3537d523365SDimitry Andric     }
3547d523365SDimitry Andric   }
3557d523365SDimitry Andric   for (const auto AE : ARCHExtNames) {
3567d523365SDimitry Andric     if (AE.Feature && ArchExt == AE.getName())
3577d523365SDimitry Andric       return AE.Feature;
3587d523365SDimitry Andric   }
3597d523365SDimitry Andric 
3607d523365SDimitry Andric   return nullptr;
3617d523365SDimitry Andric }
3627d523365SDimitry Andric 
3637d523365SDimitry Andric StringRef llvm::ARM::getHWDivName(unsigned HWDivKind) {
3647d523365SDimitry Andric   for (const auto D : HWDivNames) {
3657d523365SDimitry Andric     if (HWDivKind == D.ID)
3667d523365SDimitry Andric       return D.getName();
3677d523365SDimitry Andric   }
3687d523365SDimitry Andric   return StringRef();
3697d523365SDimitry Andric }
3707d523365SDimitry Andric 
3717d523365SDimitry Andric StringRef llvm::ARM::getDefaultCPU(StringRef Arch) {
372ff0cc061SDimitry Andric   unsigned AK = parseArch(Arch);
373ff0cc061SDimitry Andric   if (AK == ARM::AK_INVALID)
3747d523365SDimitry Andric     return StringRef();
375ff0cc061SDimitry Andric 
376ff0cc061SDimitry Andric   // Look for multiple AKs to find the default for pair AK+Name.
377ff0cc061SDimitry Andric   for (const auto CPU : CPUNames) {
378ff0cc061SDimitry Andric     if (CPU.ArchID == AK && CPU.Default)
3797d523365SDimitry Andric       return CPU.getName();
380ff0cc061SDimitry Andric   }
3817d523365SDimitry Andric 
3827d523365SDimitry Andric   // If we can't find a default then target the architecture instead
3837d523365SDimitry Andric   return "generic";
384ff0cc061SDimitry Andric }
385ff0cc061SDimitry Andric 
3863ca95b02SDimitry Andric StringRef llvm::AArch64::getFPUName(unsigned FPUKind) {
3873ca95b02SDimitry Andric   return ARM::getFPUName(FPUKind);
3883ca95b02SDimitry Andric }
3893ca95b02SDimitry Andric 
3903ca95b02SDimitry Andric unsigned llvm::AArch64::getFPUVersion(unsigned FPUKind) {
3913ca95b02SDimitry Andric   return ARM::getFPUVersion(FPUKind);
3923ca95b02SDimitry Andric }
3933ca95b02SDimitry Andric 
3943ca95b02SDimitry Andric unsigned llvm::AArch64::getFPUNeonSupportLevel(unsigned FPUKind) {
3953ca95b02SDimitry Andric   return ARM::getFPUNeonSupportLevel( FPUKind);
3963ca95b02SDimitry Andric }
3973ca95b02SDimitry Andric 
3983ca95b02SDimitry Andric unsigned llvm::AArch64::getFPURestriction(unsigned FPUKind) {
3993ca95b02SDimitry Andric   return ARM::getFPURestriction(FPUKind);
4003ca95b02SDimitry Andric }
4013ca95b02SDimitry Andric 
4023ca95b02SDimitry Andric unsigned llvm::AArch64::getDefaultFPU(StringRef CPU, unsigned ArchKind) {
4033ca95b02SDimitry Andric   if (CPU == "generic")
4043ca95b02SDimitry Andric     return AArch64ARCHNames[ArchKind].DefaultFPU;
4053ca95b02SDimitry Andric 
4063ca95b02SDimitry Andric   return StringSwitch<unsigned>(CPU)
4073ca95b02SDimitry Andric #define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
4083ca95b02SDimitry Andric     .Case(NAME, DEFAULT_FPU)
4093ca95b02SDimitry Andric #include "llvm/Support/AArch64TargetParser.def"
4103ca95b02SDimitry Andric     .Default(ARM::FK_INVALID);
4113ca95b02SDimitry Andric }
4123ca95b02SDimitry Andric 
4133ca95b02SDimitry Andric unsigned llvm::AArch64::getDefaultExtensions(StringRef CPU, unsigned ArchKind) {
4143ca95b02SDimitry Andric   if (CPU == "generic")
4153ca95b02SDimitry Andric     return AArch64ARCHNames[ArchKind].ArchBaseExtensions;
4163ca95b02SDimitry Andric 
4173ca95b02SDimitry Andric   return StringSwitch<unsigned>(CPU)
4183ca95b02SDimitry Andric #define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
4193ca95b02SDimitry Andric     .Case(NAME, AArch64ARCHNames[ID].ArchBaseExtensions | DEFAULT_EXT)
4203ca95b02SDimitry Andric #include "llvm/Support/AArch64TargetParser.def"
4213ca95b02SDimitry Andric     .Default(AArch64::AEK_INVALID);
4223ca95b02SDimitry Andric }
4233ca95b02SDimitry Andric 
4243ca95b02SDimitry Andric bool llvm::AArch64::getExtensionFeatures(unsigned Extensions,
4253ca95b02SDimitry Andric                                      std::vector<const char *> &Features) {
4263ca95b02SDimitry Andric 
4273ca95b02SDimitry Andric   if (Extensions == AArch64::AEK_INVALID)
4283ca95b02SDimitry Andric     return false;
4293ca95b02SDimitry Andric 
4303ca95b02SDimitry Andric   if (Extensions & AArch64::AEK_FP)
4313ca95b02SDimitry Andric     Features.push_back("+fp-armv8");
4323ca95b02SDimitry Andric   if (Extensions & AArch64::AEK_SIMD)
4333ca95b02SDimitry Andric     Features.push_back("+neon");
4343ca95b02SDimitry Andric   if (Extensions & AArch64::AEK_CRC)
4353ca95b02SDimitry Andric     Features.push_back("+crc");
4363ca95b02SDimitry Andric   if (Extensions & AArch64::AEK_CRYPTO)
4373ca95b02SDimitry Andric     Features.push_back("+crypto");
4383ca95b02SDimitry Andric   if (Extensions & AArch64::AEK_FP16)
4393ca95b02SDimitry Andric     Features.push_back("+fullfp16");
4403ca95b02SDimitry Andric   if (Extensions & AArch64::AEK_PROFILE)
4413ca95b02SDimitry Andric     Features.push_back("+spe");
4423ca95b02SDimitry Andric   if (Extensions & AArch64::AEK_RAS)
4433ca95b02SDimitry Andric     Features.push_back("+ras");
4443ca95b02SDimitry Andric 
4453ca95b02SDimitry Andric   return true;
4463ca95b02SDimitry Andric }
4473ca95b02SDimitry Andric 
4483ca95b02SDimitry Andric bool llvm::AArch64::getFPUFeatures(unsigned FPUKind,
4493ca95b02SDimitry Andric                                std::vector<const char *> &Features) {
4503ca95b02SDimitry Andric   return ARM::getFPUFeatures(FPUKind, Features);
4513ca95b02SDimitry Andric }
4523ca95b02SDimitry Andric 
4533ca95b02SDimitry Andric bool llvm::AArch64::getArchFeatures(unsigned ArchKind,
4543ca95b02SDimitry Andric                                      std::vector<const char *> &Features) {
4553ca95b02SDimitry Andric   if (ArchKind == ARM::AK_INVALID || ArchKind >= ARM::AK_LAST)
4563ca95b02SDimitry Andric     return false;
4573ca95b02SDimitry Andric 
4583ca95b02SDimitry Andric   if (ArchKind == ARM::AK_ARMV8_1A)
4593ca95b02SDimitry Andric     Features.push_back("+v8.1a");
4603ca95b02SDimitry Andric   if (ArchKind == ARM::AK_ARMV8_2A)
4613ca95b02SDimitry Andric     Features.push_back("+v8.2a");
4623ca95b02SDimitry Andric 
4633ca95b02SDimitry Andric   return true;
4643ca95b02SDimitry Andric }
4653ca95b02SDimitry Andric 
4663ca95b02SDimitry Andric StringRef llvm::AArch64::getArchName(unsigned ArchKind) {
4673ca95b02SDimitry Andric   for (const auto &AI : AArch64ARCHNames)
4683ca95b02SDimitry Andric     if (AI.ID == ArchKind)
4693ca95b02SDimitry Andric       return AI.getName();
4703ca95b02SDimitry Andric   return StringRef();
4713ca95b02SDimitry Andric }
4723ca95b02SDimitry Andric 
4733ca95b02SDimitry Andric StringRef llvm::AArch64::getCPUAttr(unsigned ArchKind) {
4743ca95b02SDimitry Andric   for (const auto &AI : AArch64ARCHNames)
4753ca95b02SDimitry Andric     if (AI.ID == ArchKind)
4763ca95b02SDimitry Andric       return AI.getCPUAttr();
4773ca95b02SDimitry Andric   return StringRef();
4783ca95b02SDimitry Andric }
4793ca95b02SDimitry Andric 
4803ca95b02SDimitry Andric StringRef llvm::AArch64::getSubArch(unsigned ArchKind) {
4813ca95b02SDimitry Andric   for (const auto &AI : AArch64ARCHNames)
4823ca95b02SDimitry Andric     if (AI.ID == ArchKind)
4833ca95b02SDimitry Andric       return AI.getSubArch();
4843ca95b02SDimitry Andric   return StringRef();
4853ca95b02SDimitry Andric }
4863ca95b02SDimitry Andric 
4873ca95b02SDimitry Andric unsigned llvm::AArch64::getArchAttr(unsigned ArchKind) {
4883ca95b02SDimitry Andric   for (const auto &AI : AArch64ARCHNames)
4893ca95b02SDimitry Andric     if (AI.ID == ArchKind)
4903ca95b02SDimitry Andric       return AI.ArchAttr;
4913ca95b02SDimitry Andric   return ARMBuildAttrs::CPUArch::v8_A;
4923ca95b02SDimitry Andric }
4933ca95b02SDimitry Andric 
4943ca95b02SDimitry Andric StringRef llvm::AArch64::getArchExtName(unsigned AArchExtKind) {
4953ca95b02SDimitry Andric   for (const auto &AE : AArch64ARCHExtNames)
4963ca95b02SDimitry Andric     if (AArchExtKind == AE.ID)
4973ca95b02SDimitry Andric       return AE.getName();
4983ca95b02SDimitry Andric   return StringRef();
4993ca95b02SDimitry Andric }
5003ca95b02SDimitry Andric 
5013ca95b02SDimitry Andric const char *llvm::AArch64::getArchExtFeature(StringRef ArchExt) {
5023ca95b02SDimitry Andric   if (ArchExt.startswith("no")) {
5033ca95b02SDimitry Andric     StringRef ArchExtBase(ArchExt.substr(2));
5043ca95b02SDimitry Andric     for (const auto &AE : AArch64ARCHExtNames) {
5053ca95b02SDimitry Andric       if (AE.NegFeature && ArchExtBase == AE.getName())
5063ca95b02SDimitry Andric         return AE.NegFeature;
5073ca95b02SDimitry Andric     }
5083ca95b02SDimitry Andric   }
5093ca95b02SDimitry Andric 
5103ca95b02SDimitry Andric   for (const auto &AE : AArch64ARCHExtNames)
5113ca95b02SDimitry Andric     if (AE.Feature && ArchExt == AE.getName())
5123ca95b02SDimitry Andric       return AE.Feature;
5133ca95b02SDimitry Andric   return nullptr;
5143ca95b02SDimitry Andric }
5153ca95b02SDimitry Andric 
5163ca95b02SDimitry Andric StringRef llvm::AArch64::getDefaultCPU(StringRef Arch) {
5173ca95b02SDimitry Andric   unsigned AK = parseArch(Arch);
5183ca95b02SDimitry Andric   if (AK == ARM::AK_INVALID)
5193ca95b02SDimitry Andric     return StringRef();
5203ca95b02SDimitry Andric 
5213ca95b02SDimitry Andric   // Look for multiple AKs to find the default for pair AK+Name.
5223ca95b02SDimitry Andric   for (const auto &CPU : AArch64CPUNames)
5233ca95b02SDimitry Andric     if (CPU.ArchID == AK && CPU.Default)
5243ca95b02SDimitry Andric       return CPU.getName();
5253ca95b02SDimitry Andric 
5263ca95b02SDimitry Andric   // If we can't find a default then target the architecture instead
5273ca95b02SDimitry Andric   return "generic";
5283ca95b02SDimitry Andric }
5293ca95b02SDimitry Andric 
5303ca95b02SDimitry Andric unsigned llvm::AArch64::checkArchVersion(StringRef Arch) {
5313ca95b02SDimitry Andric   if (Arch[0] == 'v' && std::isdigit(Arch[1]))
5323ca95b02SDimitry Andric     return (Arch[1] - 48);
5333ca95b02SDimitry Andric   return 0;
5343ca95b02SDimitry Andric }
5353ca95b02SDimitry Andric 
536ff0cc061SDimitry Andric // ======================================================= //
537ff0cc061SDimitry Andric // Parsers
538ff0cc061SDimitry Andric // ======================================================= //
539ff0cc061SDimitry Andric 
5407d523365SDimitry Andric static StringRef getHWDivSynonym(StringRef HWDiv) {
5417d523365SDimitry Andric   return StringSwitch<StringRef>(HWDiv)
5427d523365SDimitry Andric       .Case("thumb,arm", "arm,thumb")
5437d523365SDimitry Andric       .Default(HWDiv);
5447d523365SDimitry Andric }
5457d523365SDimitry Andric 
5467d523365SDimitry Andric static StringRef getFPUSynonym(StringRef FPU) {
547ff0cc061SDimitry Andric   return StringSwitch<StringRef>(FPU)
548ff0cc061SDimitry Andric       .Cases("fpa", "fpe2", "fpe3", "maverick", "invalid") // Unsupported
549ff0cc061SDimitry Andric       .Case("vfp2", "vfpv2")
550ff0cc061SDimitry Andric       .Case("vfp3", "vfpv3")
551ff0cc061SDimitry Andric       .Case("vfp4", "vfpv4")
552ff0cc061SDimitry Andric       .Case("vfp3-d16", "vfpv3-d16")
553ff0cc061SDimitry Andric       .Case("vfp4-d16", "vfpv4-d16")
55497bc6c73SDimitry Andric       .Cases("fp4-sp-d16", "vfpv4-sp-d16", "fpv4-sp-d16")
555ff0cc061SDimitry Andric       .Cases("fp4-dp-d16", "fpv4-dp-d16", "vfpv4-d16")
55697bc6c73SDimitry Andric       .Case("fp5-sp-d16", "fpv5-sp-d16")
557ff0cc061SDimitry Andric       .Cases("fp5-dp-d16", "fpv5-dp-d16", "fpv5-d16")
558ff0cc061SDimitry Andric       // FIXME: Clang uses it, but it's bogus, since neon defaults to vfpv3.
559ff0cc061SDimitry Andric       .Case("neon-vfpv3", "neon")
560ff0cc061SDimitry Andric       .Default(FPU);
561ff0cc061SDimitry Andric }
562ff0cc061SDimitry Andric 
5637d523365SDimitry Andric static StringRef getArchSynonym(StringRef Arch) {
564ff0cc061SDimitry Andric   return StringSwitch<StringRef>(Arch)
5657d523365SDimitry Andric       .Case("v5", "v5t")
5667d523365SDimitry Andric       .Case("v5e", "v5te")
5677d523365SDimitry Andric       .Case("v6j", "v6")
5687d523365SDimitry Andric       .Case("v6hl", "v6k")
5697d523365SDimitry Andric       .Cases("v6m", "v6sm", "v6s-m", "v6-m")
5707d523365SDimitry Andric       .Cases("v6z", "v6zk", "v6kz")
5717d523365SDimitry Andric       .Cases("v7", "v7a", "v7hl", "v7l", "v7-a")
57297bc6c73SDimitry Andric       .Case("v7r", "v7-r")
57397bc6c73SDimitry Andric       .Case("v7m", "v7-m")
57497bc6c73SDimitry Andric       .Case("v7em", "v7e-m")
57597bc6c73SDimitry Andric       .Cases("v8", "v8a", "aarch64", "arm64", "v8-a")
57697bc6c73SDimitry Andric       .Case("v8.1a", "v8.1-a")
5777d523365SDimitry Andric       .Case("v8.2a", "v8.2-a")
5783ca95b02SDimitry Andric       .Case("v8m.base", "v8-m.base")
5793ca95b02SDimitry Andric       .Case("v8m.main", "v8-m.main")
580ff0cc061SDimitry Andric       .Default(Arch);
581ff0cc061SDimitry Andric }
582ff0cc061SDimitry Andric 
583ff0cc061SDimitry Andric // MArch is expected to be of the form (arm|thumb)?(eb)?(v.+)?(eb)?, but
584ff0cc061SDimitry Andric // (iwmmxt|xscale)(eb)? is also permitted. If the former, return
585ff0cc061SDimitry Andric // "v.+", if the latter, return unmodified string, minus 'eb'.
586ff0cc061SDimitry Andric // If invalid, return empty string.
5877d523365SDimitry Andric StringRef llvm::ARM::getCanonicalArchName(StringRef Arch) {
588ff0cc061SDimitry Andric   size_t offset = StringRef::npos;
589ff0cc061SDimitry Andric   StringRef A = Arch;
590ff0cc061SDimitry Andric   StringRef Error = "";
591ff0cc061SDimitry Andric 
592ff0cc061SDimitry Andric   // Begins with "arm" / "thumb", move past it.
593ff0cc061SDimitry Andric   if (A.startswith("arm64"))
594ff0cc061SDimitry Andric     offset = 5;
595ff0cc061SDimitry Andric   else if (A.startswith("arm"))
596ff0cc061SDimitry Andric     offset = 3;
597ff0cc061SDimitry Andric   else if (A.startswith("thumb"))
598ff0cc061SDimitry Andric     offset = 5;
599ff0cc061SDimitry Andric   else if (A.startswith("aarch64")) {
600ff0cc061SDimitry Andric     offset = 7;
601ff0cc061SDimitry Andric     // AArch64 uses "_be", not "eb" suffix.
602ff0cc061SDimitry Andric     if (A.find("eb") != StringRef::npos)
603ff0cc061SDimitry Andric       return Error;
604ff0cc061SDimitry Andric     if (A.substr(offset, 3) == "_be")
605ff0cc061SDimitry Andric       offset += 3;
606ff0cc061SDimitry Andric   }
607ff0cc061SDimitry Andric 
608ff0cc061SDimitry Andric   // Ex. "armebv7", move past the "eb".
609ff0cc061SDimitry Andric   if (offset != StringRef::npos && A.substr(offset, 2) == "eb")
610ff0cc061SDimitry Andric     offset += 2;
611ff0cc061SDimitry Andric   // Or, if it ends with eb ("armv7eb"), chop it off.
612ff0cc061SDimitry Andric   else if (A.endswith("eb"))
613ff0cc061SDimitry Andric     A = A.substr(0, A.size() - 2);
614ff0cc061SDimitry Andric   // Trim the head
615ff0cc061SDimitry Andric   if (offset != StringRef::npos)
616ff0cc061SDimitry Andric     A = A.substr(offset);
617ff0cc061SDimitry Andric 
618ff0cc061SDimitry Andric   // Empty string means offset reached the end, which means it's valid.
619ff0cc061SDimitry Andric   if (A.empty())
620ff0cc061SDimitry Andric     return Arch;
621ff0cc061SDimitry Andric 
622ff0cc061SDimitry Andric   // Only match non-marketing names
623ff0cc061SDimitry Andric   if (offset != StringRef::npos) {
624ff0cc061SDimitry Andric     // Must start with 'vN'.
625ff0cc061SDimitry Andric     if (A[0] != 'v' || !std::isdigit(A[1]))
626ff0cc061SDimitry Andric       return Error;
627ff0cc061SDimitry Andric     // Can't have an extra 'eb'.
628ff0cc061SDimitry Andric     if (A.find("eb") != StringRef::npos)
629ff0cc061SDimitry Andric       return Error;
630ff0cc061SDimitry Andric   }
631ff0cc061SDimitry Andric 
632ff0cc061SDimitry Andric   // Arch will either be a 'v' name (v7a) or a marketing name (xscale).
633ff0cc061SDimitry Andric   return A;
634ff0cc061SDimitry Andric }
635ff0cc061SDimitry Andric 
6367d523365SDimitry Andric unsigned llvm::ARM::parseHWDiv(StringRef HWDiv) {
6377d523365SDimitry Andric   StringRef Syn = getHWDivSynonym(HWDiv);
6387d523365SDimitry Andric   for (const auto D : HWDivNames) {
6397d523365SDimitry Andric     if (Syn == D.getName())
6407d523365SDimitry Andric       return D.ID;
6417d523365SDimitry Andric   }
6427d523365SDimitry Andric   return ARM::AEK_INVALID;
6437d523365SDimitry Andric }
6447d523365SDimitry Andric 
6457d523365SDimitry Andric unsigned llvm::ARM::parseFPU(StringRef FPU) {
646ff0cc061SDimitry Andric   StringRef Syn = getFPUSynonym(FPU);
647ff0cc061SDimitry Andric   for (const auto F : FPUNames) {
6487d523365SDimitry Andric     if (Syn == F.getName())
649ff0cc061SDimitry Andric       return F.ID;
650ff0cc061SDimitry Andric   }
651ff0cc061SDimitry Andric   return ARM::FK_INVALID;
652ff0cc061SDimitry Andric }
653ff0cc061SDimitry Andric 
654ff0cc061SDimitry Andric // Allows partial match, ex. "v7a" matches "armv7a".
6557d523365SDimitry Andric unsigned llvm::ARM::parseArch(StringRef Arch) {
65697bc6c73SDimitry Andric   Arch = getCanonicalArchName(Arch);
657ff0cc061SDimitry Andric   StringRef Syn = getArchSynonym(Arch);
658ff0cc061SDimitry Andric   for (const auto A : ARCHNames) {
6597d523365SDimitry Andric     if (A.getName().endswith(Syn))
660ff0cc061SDimitry Andric       return A.ID;
661ff0cc061SDimitry Andric   }
662ff0cc061SDimitry Andric   return ARM::AK_INVALID;
663ff0cc061SDimitry Andric }
664ff0cc061SDimitry Andric 
6657d523365SDimitry Andric unsigned llvm::ARM::parseArchExt(StringRef ArchExt) {
666ff0cc061SDimitry Andric   for (const auto A : ARCHExtNames) {
6677d523365SDimitry Andric     if (ArchExt == A.getName())
668ff0cc061SDimitry Andric       return A.ID;
669ff0cc061SDimitry Andric   }
670ff0cc061SDimitry Andric   return ARM::AEK_INVALID;
671ff0cc061SDimitry Andric }
672ff0cc061SDimitry Andric 
6737d523365SDimitry Andric unsigned llvm::ARM::parseCPUArch(StringRef CPU) {
674ff0cc061SDimitry Andric   for (const auto C : CPUNames) {
6757d523365SDimitry Andric     if (CPU == C.getName())
676ff0cc061SDimitry Andric       return C.ArchID;
677ff0cc061SDimitry Andric   }
678ff0cc061SDimitry Andric   return ARM::AK_INVALID;
679ff0cc061SDimitry Andric }
680ff0cc061SDimitry Andric 
681ff0cc061SDimitry Andric // ARM, Thumb, AArch64
6827d523365SDimitry Andric unsigned llvm::ARM::parseArchISA(StringRef Arch) {
683ff0cc061SDimitry Andric   return StringSwitch<unsigned>(Arch)
684ff0cc061SDimitry Andric       .StartsWith("aarch64", ARM::IK_AARCH64)
685ff0cc061SDimitry Andric       .StartsWith("arm64", ARM::IK_AARCH64)
686ff0cc061SDimitry Andric       .StartsWith("thumb", ARM::IK_THUMB)
687ff0cc061SDimitry Andric       .StartsWith("arm", ARM::IK_ARM)
688ff0cc061SDimitry Andric       .Default(ARM::EK_INVALID);
689ff0cc061SDimitry Andric }
690ff0cc061SDimitry Andric 
691ff0cc061SDimitry Andric // Little/Big endian
6927d523365SDimitry Andric unsigned llvm::ARM::parseArchEndian(StringRef Arch) {
6937d523365SDimitry Andric   if (Arch.startswith("armeb") || Arch.startswith("thumbeb") ||
694ff0cc061SDimitry Andric       Arch.startswith("aarch64_be"))
695ff0cc061SDimitry Andric     return ARM::EK_BIG;
696ff0cc061SDimitry Andric 
697ff0cc061SDimitry Andric   if (Arch.startswith("arm") || Arch.startswith("thumb")) {
698ff0cc061SDimitry Andric     if (Arch.endswith("eb"))
699ff0cc061SDimitry Andric       return ARM::EK_BIG;
700ff0cc061SDimitry Andric     else
701ff0cc061SDimitry Andric       return ARM::EK_LITTLE;
702ff0cc061SDimitry Andric   }
703ff0cc061SDimitry Andric 
704ff0cc061SDimitry Andric   if (Arch.startswith("aarch64"))
705ff0cc061SDimitry Andric     return ARM::EK_LITTLE;
706ff0cc061SDimitry Andric 
707ff0cc061SDimitry Andric   return ARM::EK_INVALID;
708ff0cc061SDimitry Andric }
709ff0cc061SDimitry Andric 
710ff0cc061SDimitry Andric // Profile A/R/M
7117d523365SDimitry Andric unsigned llvm::ARM::parseArchProfile(StringRef Arch) {
712ff0cc061SDimitry Andric   Arch = getCanonicalArchName(Arch);
713ff0cc061SDimitry Andric   switch (parseArch(Arch)) {
714ff0cc061SDimitry Andric   case ARM::AK_ARMV6M:
715ff0cc061SDimitry Andric   case ARM::AK_ARMV7M:
716ff0cc061SDimitry Andric   case ARM::AK_ARMV7EM:
7173ca95b02SDimitry Andric   case ARM::AK_ARMV8MMainline:
7183ca95b02SDimitry Andric   case ARM::AK_ARMV8MBaseline:
719ff0cc061SDimitry Andric     return ARM::PK_M;
720ff0cc061SDimitry Andric   case ARM::AK_ARMV7R:
721ff0cc061SDimitry Andric     return ARM::PK_R;
722ff0cc061SDimitry Andric   case ARM::AK_ARMV7A:
7237d523365SDimitry Andric   case ARM::AK_ARMV7K:
724ff0cc061SDimitry Andric   case ARM::AK_ARMV8A:
725ff0cc061SDimitry Andric   case ARM::AK_ARMV8_1A:
7267d523365SDimitry Andric   case ARM::AK_ARMV8_2A:
727ff0cc061SDimitry Andric     return ARM::PK_A;
728ff0cc061SDimitry Andric   }
729ff0cc061SDimitry Andric   return ARM::PK_INVALID;
730ff0cc061SDimitry Andric }
731ff0cc061SDimitry Andric 
732ff0cc061SDimitry Andric // Version number (ex. v7 = 7).
7337d523365SDimitry Andric unsigned llvm::ARM::parseArchVersion(StringRef Arch) {
734ff0cc061SDimitry Andric   Arch = getCanonicalArchName(Arch);
735ff0cc061SDimitry Andric   switch (parseArch(Arch)) {
736ff0cc061SDimitry Andric   case ARM::AK_ARMV2:
737ff0cc061SDimitry Andric   case ARM::AK_ARMV2A:
738ff0cc061SDimitry Andric     return 2;
739ff0cc061SDimitry Andric   case ARM::AK_ARMV3:
740ff0cc061SDimitry Andric   case ARM::AK_ARMV3M:
741ff0cc061SDimitry Andric     return 3;
742ff0cc061SDimitry Andric   case ARM::AK_ARMV4:
743ff0cc061SDimitry Andric   case ARM::AK_ARMV4T:
744ff0cc061SDimitry Andric     return 4;
745ff0cc061SDimitry Andric   case ARM::AK_ARMV5T:
746ff0cc061SDimitry Andric   case ARM::AK_ARMV5TE:
747ff0cc061SDimitry Andric   case ARM::AK_IWMMXT:
748ff0cc061SDimitry Andric   case ARM::AK_IWMMXT2:
749ff0cc061SDimitry Andric   case ARM::AK_XSCALE:
750ff0cc061SDimitry Andric   case ARM::AK_ARMV5TEJ:
751ff0cc061SDimitry Andric     return 5;
752ff0cc061SDimitry Andric   case ARM::AK_ARMV6:
753ff0cc061SDimitry Andric   case ARM::AK_ARMV6K:
754ff0cc061SDimitry Andric   case ARM::AK_ARMV6T2:
7557d523365SDimitry Andric   case ARM::AK_ARMV6KZ:
756ff0cc061SDimitry Andric   case ARM::AK_ARMV6M:
757ff0cc061SDimitry Andric     return 6;
758ff0cc061SDimitry Andric   case ARM::AK_ARMV7A:
759ff0cc061SDimitry Andric   case ARM::AK_ARMV7R:
760ff0cc061SDimitry Andric   case ARM::AK_ARMV7M:
761ff0cc061SDimitry Andric   case ARM::AK_ARMV7S:
762ff0cc061SDimitry Andric   case ARM::AK_ARMV7EM:
7637d523365SDimitry Andric   case ARM::AK_ARMV7K:
764ff0cc061SDimitry Andric     return 7;
765ff0cc061SDimitry Andric   case ARM::AK_ARMV8A:
766ff0cc061SDimitry Andric   case ARM::AK_ARMV8_1A:
7677d523365SDimitry Andric   case ARM::AK_ARMV8_2A:
7683ca95b02SDimitry Andric   case ARM::AK_ARMV8MBaseline:
7693ca95b02SDimitry Andric   case ARM::AK_ARMV8MMainline:
770ff0cc061SDimitry Andric     return 8;
771ff0cc061SDimitry Andric   }
772ff0cc061SDimitry Andric   return 0;
773ff0cc061SDimitry Andric }
7743ca95b02SDimitry Andric 
7753ca95b02SDimitry Andric StringRef llvm::AArch64::getCanonicalArchName(StringRef Arch) {
7763ca95b02SDimitry Andric   return ARM::getCanonicalArchName(Arch);
7773ca95b02SDimitry Andric }
7783ca95b02SDimitry Andric 
7793ca95b02SDimitry Andric unsigned llvm::AArch64::parseFPU(StringRef FPU) {
7803ca95b02SDimitry Andric   return ARM::parseFPU(FPU);
7813ca95b02SDimitry Andric }
7823ca95b02SDimitry Andric 
7833ca95b02SDimitry Andric // Allows partial match, ex. "v8a" matches "armv8a".
7843ca95b02SDimitry Andric unsigned llvm::AArch64::parseArch(StringRef Arch) {
7853ca95b02SDimitry Andric   Arch = getCanonicalArchName(Arch);
7863ca95b02SDimitry Andric   if (checkArchVersion(Arch) < 8)
7873ca95b02SDimitry Andric     return ARM::AK_INVALID;
7883ca95b02SDimitry Andric 
7893ca95b02SDimitry Andric   StringRef Syn = getArchSynonym(Arch);
7903ca95b02SDimitry Andric   for (const auto A : AArch64ARCHNames) {
7913ca95b02SDimitry Andric     if (A.getName().endswith(Syn))
7923ca95b02SDimitry Andric       return A.ID;
7933ca95b02SDimitry Andric   }
7943ca95b02SDimitry Andric   return ARM::AK_INVALID;
7953ca95b02SDimitry Andric }
7963ca95b02SDimitry Andric 
7973ca95b02SDimitry Andric unsigned llvm::AArch64::parseArchExt(StringRef ArchExt) {
7983ca95b02SDimitry Andric   for (const auto A : AArch64ARCHExtNames) {
7993ca95b02SDimitry Andric     if (ArchExt == A.getName())
8003ca95b02SDimitry Andric       return A.ID;
8013ca95b02SDimitry Andric   }
8023ca95b02SDimitry Andric   return AArch64::AEK_INVALID;
8033ca95b02SDimitry Andric }
8043ca95b02SDimitry Andric 
8053ca95b02SDimitry Andric unsigned llvm::AArch64::parseCPUArch(StringRef CPU) {
8063ca95b02SDimitry Andric   for (const auto C : AArch64CPUNames) {
8073ca95b02SDimitry Andric     if (CPU == C.getName())
8083ca95b02SDimitry Andric       return C.ArchID;
8093ca95b02SDimitry Andric   }
8103ca95b02SDimitry Andric   return ARM::AK_INVALID;
8113ca95b02SDimitry Andric }
8123ca95b02SDimitry Andric 
8133ca95b02SDimitry Andric // ARM, Thumb, AArch64
8143ca95b02SDimitry Andric unsigned llvm::AArch64::parseArchISA(StringRef Arch) {
8153ca95b02SDimitry Andric   return ARM::parseArchISA(Arch);
8163ca95b02SDimitry Andric }
8173ca95b02SDimitry Andric 
8183ca95b02SDimitry Andric // Little/Big endian
8193ca95b02SDimitry Andric unsigned llvm::AArch64::parseArchEndian(StringRef Arch) {
8203ca95b02SDimitry Andric   return ARM::parseArchEndian(Arch);
8213ca95b02SDimitry Andric }
8223ca95b02SDimitry Andric 
8233ca95b02SDimitry Andric // Profile A/R/M
8243ca95b02SDimitry Andric unsigned llvm::AArch64::parseArchProfile(StringRef Arch) {
8253ca95b02SDimitry Andric   return ARM::parseArchProfile(Arch);
8263ca95b02SDimitry Andric }
8273ca95b02SDimitry Andric 
8283ca95b02SDimitry Andric // Version number (ex. v8 = 8).
8293ca95b02SDimitry Andric unsigned llvm::AArch64::parseArchVersion(StringRef Arch) {
8303ca95b02SDimitry Andric   return ARM::parseArchVersion(Arch);
8313ca95b02SDimitry Andric }
832