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.
55d88c1a5aSDimitry Andric template <typename T> struct ArchNames {
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;
64d88c1a5aSDimitry Andric   T 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); }
74d88c1a5aSDimitry Andric };
75d88c1a5aSDimitry Andric ArchNames<ARM::ArchKind> ARCHNames[] = {
767d523365SDimitry Andric #define ARM_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT)       \
777d523365SDimitry Andric   {NAME, sizeof(NAME) - 1, CPU_ATTR, sizeof(CPU_ATTR) - 1, SUB_ARCH,       \
787d523365SDimitry Andric    sizeof(SUB_ARCH) - 1, ARCH_FPU, ARCH_BASE_EXT, ID, ARCH_ATTR},
797d523365SDimitry Andric #include "llvm/Support/ARMTargetParser.def"
80d88c1a5aSDimitry Andric };
81d88c1a5aSDimitry Andric 
82d88c1a5aSDimitry Andric ArchNames<AArch64::ArchKind> AArch64ARCHNames[] = {
833ca95b02SDimitry Andric  #define AARCH64_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT)       \
843ca95b02SDimitry Andric    {NAME, sizeof(NAME) - 1, CPU_ATTR, sizeof(CPU_ATTR) - 1, SUB_ARCH,       \
85d88c1a5aSDimitry Andric     sizeof(SUB_ARCH) - 1, ARCH_FPU, ARCH_BASE_EXT, AArch64::ArchKind::ID, ARCH_ATTR},
863ca95b02SDimitry Andric  #include "llvm/Support/AArch64TargetParser.def"
87ff0cc061SDimitry Andric  };
887d523365SDimitry Andric 
89d88c1a5aSDimitry Andric 
9097bc6c73SDimitry Andric // List of Arch Extension names.
91ff0cc061SDimitry Andric // FIXME: TableGen this.
927d523365SDimitry Andric static const struct {
937d523365SDimitry Andric   const char *NameCStr;
947d523365SDimitry Andric   size_t NameLength;
957d523365SDimitry Andric   unsigned ID;
967d523365SDimitry Andric   const char *Feature;
977d523365SDimitry Andric   const char *NegFeature;
987d523365SDimitry Andric 
997d523365SDimitry Andric   StringRef getName() const { return StringRef(NameCStr, NameLength); }
100ff0cc061SDimitry Andric } ARCHExtNames[] = {
1017d523365SDimitry Andric #define ARM_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE) \
1027d523365SDimitry Andric   { NAME, sizeof(NAME) - 1, ID, FEATURE, NEGFEATURE },
1037d523365SDimitry Andric #include "llvm/Support/ARMTargetParser.def"
1043ca95b02SDimitry Andric },AArch64ARCHExtNames[] = {
1053ca95b02SDimitry Andric #define AARCH64_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE) \
1063ca95b02SDimitry Andric   { NAME, sizeof(NAME) - 1, ID, FEATURE, NEGFEATURE },
1073ca95b02SDimitry Andric #include "llvm/Support/AArch64TargetParser.def"
108ff0cc061SDimitry Andric };
1097d523365SDimitry Andric 
1107d523365SDimitry Andric // List of HWDiv names (use getHWDivSynonym) and which architectural
1117d523365SDimitry Andric // features they correspond to (use getHWDivFeatures).
1127d523365SDimitry Andric // FIXME: TableGen this.
1137d523365SDimitry Andric static const struct {
1147d523365SDimitry Andric   const char *NameCStr;
1157d523365SDimitry Andric   size_t NameLength;
1167d523365SDimitry Andric   unsigned ID;
1177d523365SDimitry Andric 
1187d523365SDimitry Andric   StringRef getName() const { return StringRef(NameCStr, NameLength); }
1197d523365SDimitry Andric } HWDivNames[] = {
1207d523365SDimitry Andric #define ARM_HW_DIV_NAME(NAME, ID) { NAME, sizeof(NAME) - 1, ID },
1217d523365SDimitry Andric #include "llvm/Support/ARMTargetParser.def"
1227d523365SDimitry Andric };
1237d523365SDimitry Andric 
124ff0cc061SDimitry Andric // List of CPU names and their arches.
125ff0cc061SDimitry Andric // The same CPU can have multiple arches and can be default on multiple arches.
126ff0cc061SDimitry Andric // When finding the Arch for a CPU, first-found prevails. Sort them accordingly.
12797bc6c73SDimitry Andric // When this becomes table-generated, we'd probably need two tables.
128ff0cc061SDimitry Andric // FIXME: TableGen this.
129d88c1a5aSDimitry Andric template <typename T> struct CpuNames {
1307d523365SDimitry Andric   const char *NameCStr;
1317d523365SDimitry Andric   size_t NameLength;
132d88c1a5aSDimitry Andric   T ArchID;
1337d523365SDimitry Andric   bool Default; // is $Name the default CPU for $ArchID ?
1347d523365SDimitry Andric   unsigned DefaultExtensions;
1357d523365SDimitry Andric 
1367d523365SDimitry Andric   StringRef getName() const { return StringRef(NameCStr, NameLength); }
137d88c1a5aSDimitry Andric };
138d88c1a5aSDimitry Andric CpuNames<ARM::ArchKind> CPUNames[] = {
1397d523365SDimitry Andric #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
1407d523365SDimitry Andric   { NAME, sizeof(NAME) - 1, ID, IS_DEFAULT, DEFAULT_EXT },
1417d523365SDimitry Andric #include "llvm/Support/ARMTargetParser.def"
142d88c1a5aSDimitry Andric };
143d88c1a5aSDimitry Andric 
144d88c1a5aSDimitry Andric CpuNames<AArch64::ArchKind> AArch64CPUNames[] = {
1453ca95b02SDimitry Andric  #define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
146d88c1a5aSDimitry Andric    { NAME, sizeof(NAME) - 1, AArch64::ArchKind::ID, IS_DEFAULT, DEFAULT_EXT },
1473ca95b02SDimitry Andric  #include "llvm/Support/AArch64TargetParser.def"
148ff0cc061SDimitry Andric  };
149ff0cc061SDimitry Andric 
150ff0cc061SDimitry Andric } // namespace
151ff0cc061SDimitry Andric 
152ff0cc061SDimitry Andric // ======================================================= //
153ff0cc061SDimitry Andric // Information by ID
154ff0cc061SDimitry Andric // ======================================================= //
155ff0cc061SDimitry Andric 
1567d523365SDimitry Andric StringRef llvm::ARM::getFPUName(unsigned FPUKind) {
157ff0cc061SDimitry Andric   if (FPUKind >= ARM::FK_LAST)
1587d523365SDimitry Andric     return StringRef();
1597d523365SDimitry Andric   return FPUNames[FPUKind].getName();
160ff0cc061SDimitry Andric }
161ff0cc061SDimitry Andric 
1627d523365SDimitry Andric unsigned llvm::ARM::getFPUVersion(unsigned FPUKind) {
16397bc6c73SDimitry Andric   if (FPUKind >= ARM::FK_LAST)
16497bc6c73SDimitry Andric     return 0;
16597bc6c73SDimitry Andric   return FPUNames[FPUKind].FPUVersion;
16697bc6c73SDimitry Andric }
16797bc6c73SDimitry Andric 
1687d523365SDimitry Andric unsigned llvm::ARM::getFPUNeonSupportLevel(unsigned FPUKind) {
16997bc6c73SDimitry Andric   if (FPUKind >= ARM::FK_LAST)
17097bc6c73SDimitry Andric     return 0;
17197bc6c73SDimitry Andric   return FPUNames[FPUKind].NeonSupport;
17297bc6c73SDimitry Andric }
17397bc6c73SDimitry Andric 
1747d523365SDimitry Andric unsigned llvm::ARM::getFPURestriction(unsigned FPUKind) {
17597bc6c73SDimitry Andric   if (FPUKind >= ARM::FK_LAST)
17697bc6c73SDimitry Andric     return 0;
17797bc6c73SDimitry Andric   return FPUNames[FPUKind].Restriction;
17897bc6c73SDimitry Andric }
17997bc6c73SDimitry Andric 
1807d523365SDimitry Andric unsigned llvm::ARM::getDefaultFPU(StringRef CPU, unsigned ArchKind) {
1817d523365SDimitry Andric   if (CPU == "generic")
1827d523365SDimitry Andric     return ARCHNames[ArchKind].DefaultFPU;
1837d523365SDimitry Andric 
1847d523365SDimitry Andric   return StringSwitch<unsigned>(CPU)
1857d523365SDimitry Andric #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
1867d523365SDimitry Andric     .Case(NAME, DEFAULT_FPU)
1877d523365SDimitry Andric #include "llvm/Support/ARMTargetParser.def"
1887d523365SDimitry Andric     .Default(ARM::FK_INVALID);
1897d523365SDimitry Andric }
1907d523365SDimitry Andric 
1917d523365SDimitry Andric unsigned llvm::ARM::getDefaultExtensions(StringRef CPU, unsigned ArchKind) {
1927d523365SDimitry Andric   if (CPU == "generic")
1937d523365SDimitry Andric     return ARCHNames[ArchKind].ArchBaseExtensions;
1947d523365SDimitry Andric 
1957d523365SDimitry Andric   return StringSwitch<unsigned>(CPU)
1967d523365SDimitry Andric #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
1977d523365SDimitry Andric     .Case(NAME, ARCHNames[ID].ArchBaseExtensions | DEFAULT_EXT)
1987d523365SDimitry Andric #include "llvm/Support/ARMTargetParser.def"
1997d523365SDimitry Andric     .Default(ARM::AEK_INVALID);
2007d523365SDimitry Andric }
2017d523365SDimitry Andric 
2027d523365SDimitry Andric bool llvm::ARM::getHWDivFeatures(unsigned HWDivKind,
203d88c1a5aSDimitry Andric                                  std::vector<StringRef> &Features) {
2047d523365SDimitry Andric 
2057d523365SDimitry Andric   if (HWDivKind == ARM::AEK_INVALID)
2067d523365SDimitry Andric     return false;
2077d523365SDimitry Andric 
2087d523365SDimitry Andric   if (HWDivKind & ARM::AEK_HWDIVARM)
2097d523365SDimitry Andric     Features.push_back("+hwdiv-arm");
2107d523365SDimitry Andric   else
2117d523365SDimitry Andric     Features.push_back("-hwdiv-arm");
2127d523365SDimitry Andric 
2137d523365SDimitry Andric   if (HWDivKind & ARM::AEK_HWDIV)
2147d523365SDimitry Andric     Features.push_back("+hwdiv");
2157d523365SDimitry Andric   else
2167d523365SDimitry Andric     Features.push_back("-hwdiv");
2177d523365SDimitry Andric 
2187d523365SDimitry Andric   return true;
2197d523365SDimitry Andric }
2207d523365SDimitry Andric 
2217d523365SDimitry Andric bool llvm::ARM::getExtensionFeatures(unsigned Extensions,
222d88c1a5aSDimitry Andric                                      std::vector<StringRef> &Features) {
2237d523365SDimitry Andric 
2247d523365SDimitry Andric   if (Extensions == ARM::AEK_INVALID)
2257d523365SDimitry Andric     return false;
2267d523365SDimitry Andric 
2277d523365SDimitry Andric   if (Extensions & ARM::AEK_CRC)
2287d523365SDimitry Andric     Features.push_back("+crc");
2297d523365SDimitry Andric   else
2307d523365SDimitry Andric     Features.push_back("-crc");
2317d523365SDimitry Andric 
2327d523365SDimitry Andric   if (Extensions & ARM::AEK_DSP)
2337d523365SDimitry Andric     Features.push_back("+dsp");
2347d523365SDimitry Andric   else
2357d523365SDimitry Andric     Features.push_back("-dsp");
2367d523365SDimitry Andric 
2377d523365SDimitry Andric   return getHWDivFeatures(Extensions, Features);
2387d523365SDimitry Andric }
2397d523365SDimitry Andric 
2407d523365SDimitry Andric bool llvm::ARM::getFPUFeatures(unsigned FPUKind,
241d88c1a5aSDimitry Andric                                std::vector<StringRef> &Features) {
24297bc6c73SDimitry Andric 
24397bc6c73SDimitry Andric   if (FPUKind >= ARM::FK_LAST || FPUKind == ARM::FK_INVALID)
24497bc6c73SDimitry Andric     return false;
24597bc6c73SDimitry Andric 
24697bc6c73SDimitry Andric   // fp-only-sp and d16 subtarget features are independent of each other, so we
24797bc6c73SDimitry Andric   // must enable/disable both.
24897bc6c73SDimitry Andric   switch (FPUNames[FPUKind].Restriction) {
24997bc6c73SDimitry Andric   case ARM::FR_SP_D16:
25097bc6c73SDimitry Andric     Features.push_back("+fp-only-sp");
25197bc6c73SDimitry Andric     Features.push_back("+d16");
25297bc6c73SDimitry Andric     break;
25397bc6c73SDimitry Andric   case ARM::FR_D16:
25497bc6c73SDimitry Andric     Features.push_back("-fp-only-sp");
25597bc6c73SDimitry Andric     Features.push_back("+d16");
25697bc6c73SDimitry Andric     break;
25797bc6c73SDimitry Andric   case ARM::FR_None:
25897bc6c73SDimitry Andric     Features.push_back("-fp-only-sp");
25997bc6c73SDimitry Andric     Features.push_back("-d16");
26097bc6c73SDimitry Andric     break;
26197bc6c73SDimitry Andric   }
26297bc6c73SDimitry Andric 
26397bc6c73SDimitry Andric   // FPU version subtarget features are inclusive of lower-numbered ones, so
26497bc6c73SDimitry Andric   // enable the one corresponding to this version and disable all that are
2658f0fd8f6SDimitry Andric   // higher. We also have to make sure to disable fp16 when vfp4 is disabled,
2668f0fd8f6SDimitry Andric   // as +vfp4 implies +fp16 but -vfp4 does not imply -fp16.
26797bc6c73SDimitry Andric   switch (FPUNames[FPUKind].FPUVersion) {
2683dac3a9bSDimitry Andric   case ARM::FV_VFPV5:
26997bc6c73SDimitry Andric     Features.push_back("+fp-armv8");
27097bc6c73SDimitry Andric     break;
2713dac3a9bSDimitry Andric   case ARM::FV_VFPV4:
27297bc6c73SDimitry Andric     Features.push_back("+vfp4");
27397bc6c73SDimitry Andric     Features.push_back("-fp-armv8");
27497bc6c73SDimitry Andric     break;
2753dac3a9bSDimitry Andric   case ARM::FV_VFPV3_FP16:
2763dac3a9bSDimitry Andric     Features.push_back("+vfp3");
2773dac3a9bSDimitry Andric     Features.push_back("+fp16");
2783dac3a9bSDimitry Andric     Features.push_back("-vfp4");
2793dac3a9bSDimitry Andric     Features.push_back("-fp-armv8");
2803dac3a9bSDimitry Andric     break;
2813dac3a9bSDimitry Andric   case ARM::FV_VFPV3:
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_VFPV2:
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;
2943dac3a9bSDimitry Andric   case ARM::FV_NONE:
29597bc6c73SDimitry Andric     Features.push_back("-vfp2");
29697bc6c73SDimitry Andric     Features.push_back("-vfp3");
2978f0fd8f6SDimitry Andric     Features.push_back("-fp16");
29897bc6c73SDimitry Andric     Features.push_back("-vfp4");
29997bc6c73SDimitry Andric     Features.push_back("-fp-armv8");
30097bc6c73SDimitry Andric     break;
30197bc6c73SDimitry Andric   }
30297bc6c73SDimitry Andric 
30397bc6c73SDimitry Andric   // crypto includes neon, so we handle this similarly to FPU version.
30497bc6c73SDimitry Andric   switch (FPUNames[FPUKind].NeonSupport) {
30597bc6c73SDimitry Andric   case ARM::NS_Crypto:
3067d523365SDimitry Andric     Features.push_back("+neon");
30797bc6c73SDimitry Andric     Features.push_back("+crypto");
30897bc6c73SDimitry Andric     break;
30997bc6c73SDimitry Andric   case ARM::NS_Neon:
31097bc6c73SDimitry Andric     Features.push_back("+neon");
31197bc6c73SDimitry Andric     Features.push_back("-crypto");
31297bc6c73SDimitry Andric     break;
31397bc6c73SDimitry Andric   case ARM::NS_None:
31497bc6c73SDimitry Andric     Features.push_back("-neon");
31597bc6c73SDimitry Andric     Features.push_back("-crypto");
31697bc6c73SDimitry Andric     break;
31797bc6c73SDimitry Andric   }
31897bc6c73SDimitry Andric 
31997bc6c73SDimitry Andric   return true;
32097bc6c73SDimitry Andric }
32197bc6c73SDimitry Andric 
3227d523365SDimitry Andric StringRef llvm::ARM::getArchName(unsigned ArchKind) {
323ff0cc061SDimitry Andric   if (ArchKind >= ARM::AK_LAST)
3247d523365SDimitry Andric     return StringRef();
3257d523365SDimitry Andric   return ARCHNames[ArchKind].getName();
326ff0cc061SDimitry Andric }
327ff0cc061SDimitry Andric 
3287d523365SDimitry Andric StringRef llvm::ARM::getCPUAttr(unsigned ArchKind) {
3293ca95b02SDimitry Andric   if (ArchKind == ARM::AK_INVALID || ArchKind >= ARM::AK_LAST)
3307d523365SDimitry Andric     return StringRef();
3317d523365SDimitry Andric   return ARCHNames[ArchKind].getCPUAttr();
332ff0cc061SDimitry Andric }
333ff0cc061SDimitry Andric 
3347d523365SDimitry Andric StringRef llvm::ARM::getSubArch(unsigned ArchKind) {
3353ca95b02SDimitry Andric   if (ArchKind == ARM::AK_INVALID || ArchKind >= ARM::AK_LAST)
3367d523365SDimitry Andric     return StringRef();
3377d523365SDimitry Andric   return ARCHNames[ArchKind].getSubArch();
33897bc6c73SDimitry Andric }
33997bc6c73SDimitry Andric 
3407d523365SDimitry Andric unsigned llvm::ARM::getArchAttr(unsigned ArchKind) {
341ff0cc061SDimitry Andric   if (ArchKind >= ARM::AK_LAST)
342ff0cc061SDimitry Andric     return ARMBuildAttrs::CPUArch::Pre_v4;
34397bc6c73SDimitry Andric   return ARCHNames[ArchKind].ArchAttr;
344ff0cc061SDimitry Andric }
345ff0cc061SDimitry Andric 
3467d523365SDimitry Andric StringRef llvm::ARM::getArchExtName(unsigned ArchExtKind) {
3477d523365SDimitry Andric   for (const auto AE : ARCHExtNames) {
3487d523365SDimitry Andric     if (ArchExtKind == AE.ID)
3497d523365SDimitry Andric       return AE.getName();
3507d523365SDimitry Andric   }
3517d523365SDimitry Andric   return StringRef();
352ff0cc061SDimitry Andric }
353ff0cc061SDimitry Andric 
354d88c1a5aSDimitry Andric StringRef llvm::ARM::getArchExtFeature(StringRef ArchExt) {
3557d523365SDimitry Andric   if (ArchExt.startswith("no")) {
3567d523365SDimitry Andric     StringRef ArchExtBase(ArchExt.substr(2));
3577d523365SDimitry Andric     for (const auto AE : ARCHExtNames) {
3587d523365SDimitry Andric       if (AE.NegFeature && ArchExtBase == AE.getName())
359d88c1a5aSDimitry Andric         return StringRef(AE.NegFeature);
3607d523365SDimitry Andric     }
3617d523365SDimitry Andric   }
3627d523365SDimitry Andric   for (const auto AE : ARCHExtNames) {
3637d523365SDimitry Andric     if (AE.Feature && ArchExt == AE.getName())
364d88c1a5aSDimitry Andric       return StringRef(AE.Feature);
3657d523365SDimitry Andric   }
3667d523365SDimitry Andric 
367d88c1a5aSDimitry Andric   return StringRef();
3687d523365SDimitry Andric }
3697d523365SDimitry Andric 
3707d523365SDimitry Andric StringRef llvm::ARM::getHWDivName(unsigned HWDivKind) {
3717d523365SDimitry Andric   for (const auto D : HWDivNames) {
3727d523365SDimitry Andric     if (HWDivKind == D.ID)
3737d523365SDimitry Andric       return D.getName();
3747d523365SDimitry Andric   }
3757d523365SDimitry Andric   return StringRef();
3767d523365SDimitry Andric }
3777d523365SDimitry Andric 
3787d523365SDimitry Andric StringRef llvm::ARM::getDefaultCPU(StringRef Arch) {
379ff0cc061SDimitry Andric   unsigned AK = parseArch(Arch);
380ff0cc061SDimitry Andric   if (AK == ARM::AK_INVALID)
3817d523365SDimitry Andric     return StringRef();
382ff0cc061SDimitry Andric 
383ff0cc061SDimitry Andric   // Look for multiple AKs to find the default for pair AK+Name.
384ff0cc061SDimitry Andric   for (const auto CPU : CPUNames) {
385ff0cc061SDimitry Andric     if (CPU.ArchID == AK && CPU.Default)
3867d523365SDimitry Andric       return CPU.getName();
387ff0cc061SDimitry Andric   }
3887d523365SDimitry Andric 
3897d523365SDimitry Andric   // If we can't find a default then target the architecture instead
3907d523365SDimitry Andric   return "generic";
391ff0cc061SDimitry Andric }
392ff0cc061SDimitry Andric 
3933ca95b02SDimitry Andric StringRef llvm::AArch64::getFPUName(unsigned FPUKind) {
3943ca95b02SDimitry Andric   return ARM::getFPUName(FPUKind);
3953ca95b02SDimitry Andric }
3963ca95b02SDimitry Andric 
3973ca95b02SDimitry Andric unsigned llvm::AArch64::getFPUVersion(unsigned FPUKind) {
3983ca95b02SDimitry Andric   return ARM::getFPUVersion(FPUKind);
3993ca95b02SDimitry Andric }
4003ca95b02SDimitry Andric 
4013ca95b02SDimitry Andric unsigned llvm::AArch64::getFPUNeonSupportLevel(unsigned FPUKind) {
4023ca95b02SDimitry Andric   return ARM::getFPUNeonSupportLevel( FPUKind);
4033ca95b02SDimitry Andric }
4043ca95b02SDimitry Andric 
4053ca95b02SDimitry Andric unsigned llvm::AArch64::getFPURestriction(unsigned FPUKind) {
4063ca95b02SDimitry Andric   return ARM::getFPURestriction(FPUKind);
4073ca95b02SDimitry Andric }
4083ca95b02SDimitry Andric 
4093ca95b02SDimitry Andric unsigned llvm::AArch64::getDefaultFPU(StringRef CPU, unsigned ArchKind) {
4103ca95b02SDimitry Andric   if (CPU == "generic")
4113ca95b02SDimitry Andric     return AArch64ARCHNames[ArchKind].DefaultFPU;
4123ca95b02SDimitry Andric 
4133ca95b02SDimitry Andric   return StringSwitch<unsigned>(CPU)
4143ca95b02SDimitry Andric #define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
4153ca95b02SDimitry Andric     .Case(NAME, DEFAULT_FPU)
4163ca95b02SDimitry Andric #include "llvm/Support/AArch64TargetParser.def"
4173ca95b02SDimitry Andric     .Default(ARM::FK_INVALID);
4183ca95b02SDimitry Andric }
4193ca95b02SDimitry Andric 
4203ca95b02SDimitry Andric unsigned llvm::AArch64::getDefaultExtensions(StringRef CPU, unsigned ArchKind) {
4213ca95b02SDimitry Andric   if (CPU == "generic")
4223ca95b02SDimitry Andric     return AArch64ARCHNames[ArchKind].ArchBaseExtensions;
4233ca95b02SDimitry Andric 
4243ca95b02SDimitry Andric   return StringSwitch<unsigned>(CPU)
4253ca95b02SDimitry Andric #define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
426d88c1a5aSDimitry Andric     .Case(NAME, DEFAULT_EXT)
4273ca95b02SDimitry Andric #include "llvm/Support/AArch64TargetParser.def"
4283ca95b02SDimitry Andric     .Default(AArch64::AEK_INVALID);
4293ca95b02SDimitry Andric }
4303ca95b02SDimitry Andric 
4313ca95b02SDimitry Andric bool llvm::AArch64::getExtensionFeatures(unsigned Extensions,
432d88c1a5aSDimitry Andric                                      std::vector<StringRef> &Features) {
4333ca95b02SDimitry Andric 
4343ca95b02SDimitry Andric   if (Extensions == AArch64::AEK_INVALID)
4353ca95b02SDimitry Andric     return false;
4363ca95b02SDimitry Andric 
4373ca95b02SDimitry Andric   if (Extensions & AArch64::AEK_FP)
4383ca95b02SDimitry Andric     Features.push_back("+fp-armv8");
4393ca95b02SDimitry Andric   if (Extensions & AArch64::AEK_SIMD)
4403ca95b02SDimitry Andric     Features.push_back("+neon");
4413ca95b02SDimitry Andric   if (Extensions & AArch64::AEK_CRC)
4423ca95b02SDimitry Andric     Features.push_back("+crc");
4433ca95b02SDimitry Andric   if (Extensions & AArch64::AEK_CRYPTO)
4443ca95b02SDimitry Andric     Features.push_back("+crypto");
4453ca95b02SDimitry Andric   if (Extensions & AArch64::AEK_FP16)
4463ca95b02SDimitry Andric     Features.push_back("+fullfp16");
4473ca95b02SDimitry Andric   if (Extensions & AArch64::AEK_PROFILE)
4483ca95b02SDimitry Andric     Features.push_back("+spe");
4493ca95b02SDimitry Andric   if (Extensions & AArch64::AEK_RAS)
4503ca95b02SDimitry Andric     Features.push_back("+ras");
4513ca95b02SDimitry Andric 
4523ca95b02SDimitry Andric   return true;
4533ca95b02SDimitry Andric }
4543ca95b02SDimitry Andric 
4553ca95b02SDimitry Andric bool llvm::AArch64::getFPUFeatures(unsigned FPUKind,
456d88c1a5aSDimitry Andric                                std::vector<StringRef> &Features) {
4573ca95b02SDimitry Andric   return ARM::getFPUFeatures(FPUKind, Features);
4583ca95b02SDimitry Andric }
4593ca95b02SDimitry Andric 
4603ca95b02SDimitry Andric bool llvm::AArch64::getArchFeatures(unsigned ArchKind,
461d88c1a5aSDimitry Andric                                      std::vector<StringRef> &Features) {
462d88c1a5aSDimitry Andric   if (ArchKind == static_cast<unsigned>(AArch64::ArchKind::AK_ARMV8_1A))
4633ca95b02SDimitry Andric     Features.push_back("+v8.1a");
464d88c1a5aSDimitry Andric   if (ArchKind == static_cast<unsigned>(AArch64::ArchKind::AK_ARMV8_2A))
4653ca95b02SDimitry Andric     Features.push_back("+v8.2a");
4663ca95b02SDimitry Andric 
467d88c1a5aSDimitry Andric   return ArchKind > static_cast<unsigned>(AArch64::ArchKind::AK_INVALID) &&
468d88c1a5aSDimitry Andric          ArchKind < static_cast<unsigned>(AArch64::ArchKind::AK_LAST);
4693ca95b02SDimitry Andric }
4703ca95b02SDimitry Andric 
4713ca95b02SDimitry Andric StringRef llvm::AArch64::getArchName(unsigned ArchKind) {
472d88c1a5aSDimitry Andric   if (ArchKind >= static_cast<unsigned>(AArch64::ArchKind::AK_LAST))
4733ca95b02SDimitry Andric     return StringRef();
474d88c1a5aSDimitry Andric   return AArch64ARCHNames[ArchKind].getName();
4753ca95b02SDimitry Andric }
4763ca95b02SDimitry Andric 
4773ca95b02SDimitry Andric StringRef llvm::AArch64::getCPUAttr(unsigned ArchKind) {
478d88c1a5aSDimitry Andric   if (ArchKind == static_cast<unsigned>(AArch64::ArchKind::AK_INVALID) ||
479d88c1a5aSDimitry Andric       ArchKind >= static_cast<unsigned>(AArch64::ArchKind::AK_LAST))
4803ca95b02SDimitry Andric     return StringRef();
481d88c1a5aSDimitry Andric   return AArch64ARCHNames[ArchKind].getCPUAttr();
4823ca95b02SDimitry Andric }
4833ca95b02SDimitry Andric 
4843ca95b02SDimitry Andric StringRef llvm::AArch64::getSubArch(unsigned ArchKind) {
485d88c1a5aSDimitry Andric   if (ArchKind == static_cast<unsigned>(AArch64::ArchKind::AK_INVALID) ||
486d88c1a5aSDimitry Andric       ArchKind >= static_cast<unsigned>(AArch64::ArchKind::AK_LAST))
4873ca95b02SDimitry Andric     return StringRef();
488d88c1a5aSDimitry Andric   return AArch64ARCHNames[ArchKind].getSubArch();
4893ca95b02SDimitry Andric }
4903ca95b02SDimitry Andric 
4913ca95b02SDimitry Andric unsigned llvm::AArch64::getArchAttr(unsigned ArchKind) {
492d88c1a5aSDimitry Andric   if (ArchKind >= static_cast<unsigned>(AArch64::ArchKind::AK_LAST))
4933ca95b02SDimitry Andric     return ARMBuildAttrs::CPUArch::v8_A;
494d88c1a5aSDimitry Andric   return AArch64ARCHNames[ArchKind].ArchAttr;
4953ca95b02SDimitry Andric }
4963ca95b02SDimitry Andric 
497d88c1a5aSDimitry Andric StringRef llvm::AArch64::getArchExtName(unsigned ArchExtKind) {
4983ca95b02SDimitry Andric   for (const auto &AE : AArch64ARCHExtNames)
499d88c1a5aSDimitry Andric     if (ArchExtKind == AE.ID)
5003ca95b02SDimitry Andric       return AE.getName();
5013ca95b02SDimitry Andric   return StringRef();
5023ca95b02SDimitry Andric }
5033ca95b02SDimitry Andric 
504d88c1a5aSDimitry Andric StringRef llvm::AArch64::getArchExtFeature(StringRef ArchExt) {
5053ca95b02SDimitry Andric   if (ArchExt.startswith("no")) {
5063ca95b02SDimitry Andric     StringRef ArchExtBase(ArchExt.substr(2));
5073ca95b02SDimitry Andric     for (const auto &AE : AArch64ARCHExtNames) {
5083ca95b02SDimitry Andric       if (AE.NegFeature && ArchExtBase == AE.getName())
509d88c1a5aSDimitry Andric         return StringRef(AE.NegFeature);
5103ca95b02SDimitry Andric     }
5113ca95b02SDimitry Andric   }
5123ca95b02SDimitry Andric 
5133ca95b02SDimitry Andric   for (const auto &AE : AArch64ARCHExtNames)
5143ca95b02SDimitry Andric     if (AE.Feature && ArchExt == AE.getName())
515d88c1a5aSDimitry Andric       return StringRef(AE.Feature);
516d88c1a5aSDimitry Andric   return StringRef();
5173ca95b02SDimitry Andric }
5183ca95b02SDimitry Andric 
5193ca95b02SDimitry Andric StringRef llvm::AArch64::getDefaultCPU(StringRef Arch) {
5203ca95b02SDimitry Andric   unsigned AK = parseArch(Arch);
521d88c1a5aSDimitry Andric   if (AK == static_cast<unsigned>(AArch64::ArchKind::AK_INVALID))
5223ca95b02SDimitry Andric     return StringRef();
5233ca95b02SDimitry Andric 
5243ca95b02SDimitry Andric   // Look for multiple AKs to find the default for pair AK+Name.
5253ca95b02SDimitry Andric   for (const auto &CPU : AArch64CPUNames)
526d88c1a5aSDimitry Andric     if (static_cast<unsigned>(CPU.ArchID) == AK && CPU.Default)
5273ca95b02SDimitry Andric       return CPU.getName();
5283ca95b02SDimitry Andric 
5293ca95b02SDimitry Andric   // If we can't find a default then target the architecture instead
5303ca95b02SDimitry Andric   return "generic";
5313ca95b02SDimitry Andric }
5323ca95b02SDimitry Andric 
5333ca95b02SDimitry Andric unsigned llvm::AArch64::checkArchVersion(StringRef Arch) {
5343ca95b02SDimitry Andric   if (Arch[0] == 'v' && std::isdigit(Arch[1]))
5353ca95b02SDimitry Andric     return (Arch[1] - 48);
5363ca95b02SDimitry Andric   return 0;
5373ca95b02SDimitry Andric }
5383ca95b02SDimitry Andric 
539ff0cc061SDimitry Andric // ======================================================= //
540ff0cc061SDimitry Andric // Parsers
541ff0cc061SDimitry Andric // ======================================================= //
542ff0cc061SDimitry Andric 
5437d523365SDimitry Andric static StringRef getHWDivSynonym(StringRef HWDiv) {
5447d523365SDimitry Andric   return StringSwitch<StringRef>(HWDiv)
5457d523365SDimitry Andric       .Case("thumb,arm", "arm,thumb")
5467d523365SDimitry Andric       .Default(HWDiv);
5477d523365SDimitry Andric }
5487d523365SDimitry Andric 
5497d523365SDimitry Andric static StringRef getFPUSynonym(StringRef FPU) {
550ff0cc061SDimitry Andric   return StringSwitch<StringRef>(FPU)
551ff0cc061SDimitry Andric       .Cases("fpa", "fpe2", "fpe3", "maverick", "invalid") // Unsupported
552ff0cc061SDimitry Andric       .Case("vfp2", "vfpv2")
553ff0cc061SDimitry Andric       .Case("vfp3", "vfpv3")
554ff0cc061SDimitry Andric       .Case("vfp4", "vfpv4")
555ff0cc061SDimitry Andric       .Case("vfp3-d16", "vfpv3-d16")
556ff0cc061SDimitry Andric       .Case("vfp4-d16", "vfpv4-d16")
55797bc6c73SDimitry Andric       .Cases("fp4-sp-d16", "vfpv4-sp-d16", "fpv4-sp-d16")
558ff0cc061SDimitry Andric       .Cases("fp4-dp-d16", "fpv4-dp-d16", "vfpv4-d16")
55997bc6c73SDimitry Andric       .Case("fp5-sp-d16", "fpv5-sp-d16")
560ff0cc061SDimitry Andric       .Cases("fp5-dp-d16", "fpv5-dp-d16", "fpv5-d16")
561ff0cc061SDimitry Andric       // FIXME: Clang uses it, but it's bogus, since neon defaults to vfpv3.
562ff0cc061SDimitry Andric       .Case("neon-vfpv3", "neon")
563ff0cc061SDimitry Andric       .Default(FPU);
564ff0cc061SDimitry Andric }
565ff0cc061SDimitry Andric 
5667d523365SDimitry Andric static StringRef getArchSynonym(StringRef Arch) {
567ff0cc061SDimitry Andric   return StringSwitch<StringRef>(Arch)
5687d523365SDimitry Andric       .Case("v5", "v5t")
5697d523365SDimitry Andric       .Case("v5e", "v5te")
5707d523365SDimitry Andric       .Case("v6j", "v6")
5717d523365SDimitry Andric       .Case("v6hl", "v6k")
5727d523365SDimitry Andric       .Cases("v6m", "v6sm", "v6s-m", "v6-m")
5737d523365SDimitry Andric       .Cases("v6z", "v6zk", "v6kz")
5747d523365SDimitry Andric       .Cases("v7", "v7a", "v7hl", "v7l", "v7-a")
57597bc6c73SDimitry Andric       .Case("v7r", "v7-r")
57697bc6c73SDimitry Andric       .Case("v7m", "v7-m")
57797bc6c73SDimitry Andric       .Case("v7em", "v7e-m")
57897bc6c73SDimitry Andric       .Cases("v8", "v8a", "aarch64", "arm64", "v8-a")
57997bc6c73SDimitry Andric       .Case("v8.1a", "v8.1-a")
5807d523365SDimitry Andric       .Case("v8.2a", "v8.2-a")
581d88c1a5aSDimitry Andric       .Case("v8r", "v8-r")
5823ca95b02SDimitry Andric       .Case("v8m.base", "v8-m.base")
5833ca95b02SDimitry Andric       .Case("v8m.main", "v8-m.main")
584ff0cc061SDimitry Andric       .Default(Arch);
585ff0cc061SDimitry Andric }
586ff0cc061SDimitry Andric 
587ff0cc061SDimitry Andric // MArch is expected to be of the form (arm|thumb)?(eb)?(v.+)?(eb)?, but
588ff0cc061SDimitry Andric // (iwmmxt|xscale)(eb)? is also permitted. If the former, return
589ff0cc061SDimitry Andric // "v.+", if the latter, return unmodified string, minus 'eb'.
590ff0cc061SDimitry Andric // If invalid, return empty string.
5917d523365SDimitry Andric StringRef llvm::ARM::getCanonicalArchName(StringRef Arch) {
592ff0cc061SDimitry Andric   size_t offset = StringRef::npos;
593ff0cc061SDimitry Andric   StringRef A = Arch;
594ff0cc061SDimitry Andric   StringRef Error = "";
595ff0cc061SDimitry Andric 
596ff0cc061SDimitry Andric   // Begins with "arm" / "thumb", move past it.
597ff0cc061SDimitry Andric   if (A.startswith("arm64"))
598ff0cc061SDimitry Andric     offset = 5;
599ff0cc061SDimitry Andric   else if (A.startswith("arm"))
600ff0cc061SDimitry Andric     offset = 3;
601ff0cc061SDimitry Andric   else if (A.startswith("thumb"))
602ff0cc061SDimitry Andric     offset = 5;
603ff0cc061SDimitry Andric   else if (A.startswith("aarch64")) {
604ff0cc061SDimitry Andric     offset = 7;
605ff0cc061SDimitry Andric     // AArch64 uses "_be", not "eb" suffix.
606ff0cc061SDimitry Andric     if (A.find("eb") != StringRef::npos)
607ff0cc061SDimitry Andric       return Error;
608ff0cc061SDimitry Andric     if (A.substr(offset, 3) == "_be")
609ff0cc061SDimitry Andric       offset += 3;
610ff0cc061SDimitry Andric   }
611ff0cc061SDimitry Andric 
612ff0cc061SDimitry Andric   // Ex. "armebv7", move past the "eb".
613ff0cc061SDimitry Andric   if (offset != StringRef::npos && A.substr(offset, 2) == "eb")
614ff0cc061SDimitry Andric     offset += 2;
615ff0cc061SDimitry Andric   // Or, if it ends with eb ("armv7eb"), chop it off.
616ff0cc061SDimitry Andric   else if (A.endswith("eb"))
617ff0cc061SDimitry Andric     A = A.substr(0, A.size() - 2);
618ff0cc061SDimitry Andric   // Trim the head
619ff0cc061SDimitry Andric   if (offset != StringRef::npos)
620ff0cc061SDimitry Andric     A = A.substr(offset);
621ff0cc061SDimitry Andric 
622ff0cc061SDimitry Andric   // Empty string means offset reached the end, which means it's valid.
623ff0cc061SDimitry Andric   if (A.empty())
624ff0cc061SDimitry Andric     return Arch;
625ff0cc061SDimitry Andric 
626ff0cc061SDimitry Andric   // Only match non-marketing names
627ff0cc061SDimitry Andric   if (offset != StringRef::npos) {
628ff0cc061SDimitry Andric     // Must start with 'vN'.
629ff0cc061SDimitry Andric     if (A[0] != 'v' || !std::isdigit(A[1]))
630ff0cc061SDimitry Andric       return Error;
631ff0cc061SDimitry Andric     // Can't have an extra 'eb'.
632ff0cc061SDimitry Andric     if (A.find("eb") != StringRef::npos)
633ff0cc061SDimitry Andric       return Error;
634ff0cc061SDimitry Andric   }
635ff0cc061SDimitry Andric 
636ff0cc061SDimitry Andric   // Arch will either be a 'v' name (v7a) or a marketing name (xscale).
637ff0cc061SDimitry Andric   return A;
638ff0cc061SDimitry Andric }
639ff0cc061SDimitry Andric 
6407d523365SDimitry Andric unsigned llvm::ARM::parseHWDiv(StringRef HWDiv) {
6417d523365SDimitry Andric   StringRef Syn = getHWDivSynonym(HWDiv);
6427d523365SDimitry Andric   for (const auto D : HWDivNames) {
6437d523365SDimitry Andric     if (Syn == D.getName())
6447d523365SDimitry Andric       return D.ID;
6457d523365SDimitry Andric   }
6467d523365SDimitry Andric   return ARM::AEK_INVALID;
6477d523365SDimitry Andric }
6487d523365SDimitry Andric 
6497d523365SDimitry Andric unsigned llvm::ARM::parseFPU(StringRef FPU) {
650ff0cc061SDimitry Andric   StringRef Syn = getFPUSynonym(FPU);
651ff0cc061SDimitry Andric   for (const auto F : FPUNames) {
6527d523365SDimitry Andric     if (Syn == F.getName())
653ff0cc061SDimitry Andric       return F.ID;
654ff0cc061SDimitry Andric   }
655ff0cc061SDimitry Andric   return ARM::FK_INVALID;
656ff0cc061SDimitry Andric }
657ff0cc061SDimitry Andric 
658ff0cc061SDimitry Andric // Allows partial match, ex. "v7a" matches "armv7a".
6597d523365SDimitry Andric unsigned llvm::ARM::parseArch(StringRef Arch) {
66097bc6c73SDimitry Andric   Arch = getCanonicalArchName(Arch);
661ff0cc061SDimitry Andric   StringRef Syn = getArchSynonym(Arch);
662ff0cc061SDimitry Andric   for (const auto A : ARCHNames) {
6637d523365SDimitry Andric     if (A.getName().endswith(Syn))
664ff0cc061SDimitry Andric       return A.ID;
665ff0cc061SDimitry Andric   }
666ff0cc061SDimitry Andric   return ARM::AK_INVALID;
667ff0cc061SDimitry Andric }
668ff0cc061SDimitry Andric 
6697d523365SDimitry Andric unsigned llvm::ARM::parseArchExt(StringRef ArchExt) {
670ff0cc061SDimitry Andric   for (const auto A : ARCHExtNames) {
6717d523365SDimitry Andric     if (ArchExt == A.getName())
672ff0cc061SDimitry Andric       return A.ID;
673ff0cc061SDimitry Andric   }
674ff0cc061SDimitry Andric   return ARM::AEK_INVALID;
675ff0cc061SDimitry Andric }
676ff0cc061SDimitry Andric 
6777d523365SDimitry Andric unsigned llvm::ARM::parseCPUArch(StringRef CPU) {
678ff0cc061SDimitry Andric   for (const auto C : CPUNames) {
6797d523365SDimitry Andric     if (CPU == C.getName())
680ff0cc061SDimitry Andric       return C.ArchID;
681ff0cc061SDimitry Andric   }
682ff0cc061SDimitry Andric   return ARM::AK_INVALID;
683ff0cc061SDimitry Andric }
684ff0cc061SDimitry Andric 
685ff0cc061SDimitry Andric // ARM, Thumb, AArch64
6867d523365SDimitry Andric unsigned llvm::ARM::parseArchISA(StringRef Arch) {
687ff0cc061SDimitry Andric   return StringSwitch<unsigned>(Arch)
688ff0cc061SDimitry Andric       .StartsWith("aarch64", ARM::IK_AARCH64)
689ff0cc061SDimitry Andric       .StartsWith("arm64", ARM::IK_AARCH64)
690ff0cc061SDimitry Andric       .StartsWith("thumb", ARM::IK_THUMB)
691ff0cc061SDimitry Andric       .StartsWith("arm", ARM::IK_ARM)
692d88c1a5aSDimitry Andric       .Default(ARM::IK_INVALID);
693ff0cc061SDimitry Andric }
694ff0cc061SDimitry Andric 
695ff0cc061SDimitry Andric // Little/Big endian
6967d523365SDimitry Andric unsigned llvm::ARM::parseArchEndian(StringRef Arch) {
6977d523365SDimitry Andric   if (Arch.startswith("armeb") || Arch.startswith("thumbeb") ||
698ff0cc061SDimitry Andric       Arch.startswith("aarch64_be"))
699ff0cc061SDimitry Andric     return ARM::EK_BIG;
700ff0cc061SDimitry Andric 
701ff0cc061SDimitry Andric   if (Arch.startswith("arm") || Arch.startswith("thumb")) {
702ff0cc061SDimitry Andric     if (Arch.endswith("eb"))
703ff0cc061SDimitry Andric       return ARM::EK_BIG;
704ff0cc061SDimitry Andric     else
705ff0cc061SDimitry Andric       return ARM::EK_LITTLE;
706ff0cc061SDimitry Andric   }
707ff0cc061SDimitry Andric 
708ff0cc061SDimitry Andric   if (Arch.startswith("aarch64"))
709ff0cc061SDimitry Andric     return ARM::EK_LITTLE;
710ff0cc061SDimitry Andric 
711ff0cc061SDimitry Andric   return ARM::EK_INVALID;
712ff0cc061SDimitry Andric }
713ff0cc061SDimitry Andric 
714ff0cc061SDimitry Andric // Profile A/R/M
7157d523365SDimitry Andric unsigned llvm::ARM::parseArchProfile(StringRef Arch) {
716ff0cc061SDimitry Andric   Arch = getCanonicalArchName(Arch);
717ff0cc061SDimitry Andric   switch (parseArch(Arch)) {
718ff0cc061SDimitry Andric   case ARM::AK_ARMV6M:
719ff0cc061SDimitry Andric   case ARM::AK_ARMV7M:
720ff0cc061SDimitry Andric   case ARM::AK_ARMV7EM:
7213ca95b02SDimitry Andric   case ARM::AK_ARMV8MMainline:
7223ca95b02SDimitry Andric   case ARM::AK_ARMV8MBaseline:
723ff0cc061SDimitry Andric     return ARM::PK_M;
724ff0cc061SDimitry Andric   case ARM::AK_ARMV7R:
725d88c1a5aSDimitry Andric   case ARM::AK_ARMV8R:
726ff0cc061SDimitry Andric     return ARM::PK_R;
727ff0cc061SDimitry Andric   case ARM::AK_ARMV7A:
7287d523365SDimitry Andric   case ARM::AK_ARMV7K:
729ff0cc061SDimitry Andric   case ARM::AK_ARMV8A:
730ff0cc061SDimitry Andric   case ARM::AK_ARMV8_1A:
7317d523365SDimitry Andric   case ARM::AK_ARMV8_2A:
732ff0cc061SDimitry Andric     return ARM::PK_A;
733ff0cc061SDimitry Andric   }
734ff0cc061SDimitry Andric   return ARM::PK_INVALID;
735ff0cc061SDimitry Andric }
736ff0cc061SDimitry Andric 
737ff0cc061SDimitry Andric // Version number (ex. v7 = 7).
7387d523365SDimitry Andric unsigned llvm::ARM::parseArchVersion(StringRef Arch) {
739ff0cc061SDimitry Andric   Arch = getCanonicalArchName(Arch);
740ff0cc061SDimitry Andric   switch (parseArch(Arch)) {
741ff0cc061SDimitry Andric   case ARM::AK_ARMV2:
742ff0cc061SDimitry Andric   case ARM::AK_ARMV2A:
743ff0cc061SDimitry Andric     return 2;
744ff0cc061SDimitry Andric   case ARM::AK_ARMV3:
745ff0cc061SDimitry Andric   case ARM::AK_ARMV3M:
746ff0cc061SDimitry Andric     return 3;
747ff0cc061SDimitry Andric   case ARM::AK_ARMV4:
748ff0cc061SDimitry Andric   case ARM::AK_ARMV4T:
749ff0cc061SDimitry Andric     return 4;
750ff0cc061SDimitry Andric   case ARM::AK_ARMV5T:
751ff0cc061SDimitry Andric   case ARM::AK_ARMV5TE:
752ff0cc061SDimitry Andric   case ARM::AK_IWMMXT:
753ff0cc061SDimitry Andric   case ARM::AK_IWMMXT2:
754ff0cc061SDimitry Andric   case ARM::AK_XSCALE:
755ff0cc061SDimitry Andric   case ARM::AK_ARMV5TEJ:
756ff0cc061SDimitry Andric     return 5;
757ff0cc061SDimitry Andric   case ARM::AK_ARMV6:
758ff0cc061SDimitry Andric   case ARM::AK_ARMV6K:
759ff0cc061SDimitry Andric   case ARM::AK_ARMV6T2:
7607d523365SDimitry Andric   case ARM::AK_ARMV6KZ:
761ff0cc061SDimitry Andric   case ARM::AK_ARMV6M:
762ff0cc061SDimitry Andric     return 6;
763ff0cc061SDimitry Andric   case ARM::AK_ARMV7A:
764ff0cc061SDimitry Andric   case ARM::AK_ARMV7R:
765ff0cc061SDimitry Andric   case ARM::AK_ARMV7M:
766ff0cc061SDimitry Andric   case ARM::AK_ARMV7S:
767ff0cc061SDimitry Andric   case ARM::AK_ARMV7EM:
7687d523365SDimitry Andric   case ARM::AK_ARMV7K:
769ff0cc061SDimitry Andric     return 7;
770ff0cc061SDimitry Andric   case ARM::AK_ARMV8A:
771ff0cc061SDimitry Andric   case ARM::AK_ARMV8_1A:
7727d523365SDimitry Andric   case ARM::AK_ARMV8_2A:
773d88c1a5aSDimitry Andric   case ARM::AK_ARMV8R:
7743ca95b02SDimitry Andric   case ARM::AK_ARMV8MBaseline:
7753ca95b02SDimitry Andric   case ARM::AK_ARMV8MMainline:
776ff0cc061SDimitry Andric     return 8;
777ff0cc061SDimitry Andric   }
778ff0cc061SDimitry Andric   return 0;
779ff0cc061SDimitry Andric }
7803ca95b02SDimitry Andric 
7813ca95b02SDimitry Andric StringRef llvm::AArch64::getCanonicalArchName(StringRef Arch) {
7823ca95b02SDimitry Andric   return ARM::getCanonicalArchName(Arch);
7833ca95b02SDimitry Andric }
7843ca95b02SDimitry Andric 
7853ca95b02SDimitry Andric unsigned llvm::AArch64::parseFPU(StringRef FPU) {
7863ca95b02SDimitry Andric   return ARM::parseFPU(FPU);
7873ca95b02SDimitry Andric }
7883ca95b02SDimitry Andric 
7893ca95b02SDimitry Andric // Allows partial match, ex. "v8a" matches "armv8a".
7903ca95b02SDimitry Andric unsigned llvm::AArch64::parseArch(StringRef Arch) {
7913ca95b02SDimitry Andric   Arch = getCanonicalArchName(Arch);
7923ca95b02SDimitry Andric   if (checkArchVersion(Arch) < 8)
793d88c1a5aSDimitry Andric     return static_cast<unsigned>(AArch64::ArchKind::AK_INVALID);
7943ca95b02SDimitry Andric 
7953ca95b02SDimitry Andric   StringRef Syn = getArchSynonym(Arch);
7963ca95b02SDimitry Andric   for (const auto A : AArch64ARCHNames) {
7973ca95b02SDimitry Andric     if (A.getName().endswith(Syn))
798d88c1a5aSDimitry Andric       return static_cast<unsigned>(A.ID);
7993ca95b02SDimitry Andric   }
800d88c1a5aSDimitry Andric   return static_cast<unsigned>(AArch64::ArchKind::AK_INVALID);
8013ca95b02SDimitry Andric }
8023ca95b02SDimitry Andric 
8033ca95b02SDimitry Andric unsigned llvm::AArch64::parseArchExt(StringRef ArchExt) {
8043ca95b02SDimitry Andric   for (const auto A : AArch64ARCHExtNames) {
8053ca95b02SDimitry Andric     if (ArchExt == A.getName())
8063ca95b02SDimitry Andric       return A.ID;
8073ca95b02SDimitry Andric   }
8083ca95b02SDimitry Andric   return AArch64::AEK_INVALID;
8093ca95b02SDimitry Andric }
8103ca95b02SDimitry Andric 
8113ca95b02SDimitry Andric unsigned llvm::AArch64::parseCPUArch(StringRef CPU) {
8123ca95b02SDimitry Andric   for (const auto C : AArch64CPUNames) {
8133ca95b02SDimitry Andric     if (CPU == C.getName())
814d88c1a5aSDimitry Andric       return static_cast<unsigned>(C.ArchID);
8153ca95b02SDimitry Andric   }
816d88c1a5aSDimitry Andric   return static_cast<unsigned>(AArch64::ArchKind::AK_INVALID);
8173ca95b02SDimitry Andric }
8183ca95b02SDimitry Andric 
8193ca95b02SDimitry Andric // ARM, Thumb, AArch64
8203ca95b02SDimitry Andric unsigned llvm::AArch64::parseArchISA(StringRef Arch) {
8213ca95b02SDimitry Andric   return ARM::parseArchISA(Arch);
8223ca95b02SDimitry Andric }
8233ca95b02SDimitry Andric 
8243ca95b02SDimitry Andric // Little/Big endian
8253ca95b02SDimitry Andric unsigned llvm::AArch64::parseArchEndian(StringRef Arch) {
8263ca95b02SDimitry Andric   return ARM::parseArchEndian(Arch);
8273ca95b02SDimitry Andric }
8283ca95b02SDimitry Andric 
8293ca95b02SDimitry Andric // Profile A/R/M
8303ca95b02SDimitry Andric unsigned llvm::AArch64::parseArchProfile(StringRef Arch) {
8313ca95b02SDimitry Andric   return ARM::parseArchProfile(Arch);
8323ca95b02SDimitry Andric }
8333ca95b02SDimitry Andric 
8343ca95b02SDimitry Andric // Version number (ex. v8 = 8).
8353ca95b02SDimitry Andric unsigned llvm::AArch64::parseArchVersion(StringRef Arch) {
8363ca95b02SDimitry Andric   return ARM::parseArchVersion(Arch);
8373ca95b02SDimitry Andric }
838