1f5f373fcSRenato Golin //===-- TargetParser - Parser for target features ---------------*- C++ -*-===//
2f5f373fcSRenato Golin //
3f5f373fcSRenato Golin //                     The LLVM Compiler Infrastructure
4f5f373fcSRenato Golin //
5f5f373fcSRenato Golin // This file is distributed under the University of Illinois Open Source
6f5f373fcSRenato Golin // License. See LICENSE.TXT for details.
7f5f373fcSRenato Golin //
8f5f373fcSRenato Golin //===----------------------------------------------------------------------===//
9f5f373fcSRenato Golin //
10f5f373fcSRenato Golin // This file implements a target parser to recognise hardware features such as
11f5f373fcSRenato Golin // FPU/CPU/ARCH names as well as specific support such as HDIV, etc.
12f5f373fcSRenato Golin //
13f5f373fcSRenato Golin //===----------------------------------------------------------------------===//
14f5f373fcSRenato Golin 
15f5f373fcSRenato Golin #include "llvm/Support/ARMBuildAttributes.h"
16f5f373fcSRenato Golin #include "llvm/Support/TargetParser.h"
17f5f373fcSRenato Golin #include "llvm/ADT/StringExtras.h"
18f5f373fcSRenato Golin #include "llvm/ADT/StringSwitch.h"
19ebdd12cbSRenato Golin #include <cctype>
20f5f373fcSRenato Golin 
21f5f373fcSRenato Golin using namespace llvm;
22*799e880eSChandler Carruth using namespace ARM;
23f5f373fcSRenato Golin 
24f5f373fcSRenato Golin namespace {
25f5f373fcSRenato Golin 
26d03d2292SJohn Brawn // List of canonical FPU names (use getFPUSynonym) and which architectural
27d03d2292SJohn Brawn // features they correspond to (use getFPUFeatures).
28f5f373fcSRenato Golin // FIXME: TableGen this.
29d5526303SJaved Absar // The entries must appear in the order listed in ARM::FPUKind for correct indexing
30f5f373fcSRenato Golin struct {
31f5f373fcSRenato Golin   const char * Name;
32f5f373fcSRenato Golin   ARM::FPUKind ID;
33d5526303SJaved Absar   ARM::FPUVersion FPUVersion;
34d03d2292SJohn Brawn   ARM::NeonSupportLevel NeonSupport;
35d03d2292SJohn Brawn   ARM::FPURestriction Restriction;
36f5f373fcSRenato Golin } FPUNames[] = {
37*799e880eSChandler Carruth #define ARM_FPU(NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION) \
38*799e880eSChandler Carruth   { NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION },
39*799e880eSChandler Carruth #include "llvm/Support/ARMTargetParser.def"
40f5f373fcSRenato Golin };
41d03d2292SJohn Brawn 
42f7c0d5f2SRenato Golin // List of canonical arch names (use getArchSynonym).
43f7c0d5f2SRenato Golin // This table also provides the build attribute fields for CPU arch
44f7c0d5f2SRenato Golin // and Arch ID, according to the Addenda to the ARM ABI, chapters
45f7c0d5f2SRenato Golin // 2.4 and 2.3.5.2 respectively.
4642dad647SRenato Golin // FIXME: SubArch values were simplified to fit into the expectations
4742dad647SRenato Golin // of the triples and are not conforming with their official names.
4842dad647SRenato Golin // Check to see if the expectation should be changed.
49f5f373fcSRenato Golin // FIXME: TableGen this.
50f5f373fcSRenato Golin struct {
51f5f373fcSRenato Golin   const char *Name;
52f5f373fcSRenato Golin   ARM::ArchKind ID;
53f7c0d5f2SRenato Golin   const char *CPUAttr; // CPU class in build attributes.
5442dad647SRenato Golin   const char *SubArch; // Sub-Arch name.
55f7c0d5f2SRenato Golin   ARMBuildAttrs::CPUArch ArchAttr; // Arch ID in build attributes.
56f5f373fcSRenato Golin } ARCHNames[] = {
57*799e880eSChandler Carruth #define ARM_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR) \
58*799e880eSChandler Carruth   { NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR },
59*799e880eSChandler Carruth #include "llvm/Support/ARMTargetParser.def"
60f5f373fcSRenato Golin };
61e1326cadSRenato Golin // List of Arch Extension names.
62f5f373fcSRenato Golin // FIXME: TableGen this.
63f5f373fcSRenato Golin struct {
64f5f373fcSRenato Golin   const char *Name;
654ea70755SAlexandros Lamprineas   unsigned ID;
66f5f373fcSRenato Golin } ARCHExtNames[] = {
67*799e880eSChandler Carruth #define ARM_ARCH_EXT_NAME(NAME, ID) { NAME, ID },
68*799e880eSChandler Carruth #include "llvm/Support/ARMTargetParser.def"
69f5f373fcSRenato Golin };
704ea70755SAlexandros Lamprineas // List of HWDiv names (use getHWDivSynonym) and which architectural
714ea70755SAlexandros Lamprineas // features they correspond to (use getHWDivFeatures).
724ea70755SAlexandros Lamprineas // FIXME: TableGen this.
734ea70755SAlexandros Lamprineas struct {
744ea70755SAlexandros Lamprineas   const char *Name;
754ea70755SAlexandros Lamprineas   unsigned ID;
764ea70755SAlexandros Lamprineas } HWDivNames[] = {
77*799e880eSChandler Carruth #define ARM_HW_DIV_NAME(NAME, ID) { NAME, ID },
78*799e880eSChandler Carruth #include "llvm/Support/ARMTargetParser.def"
794ea70755SAlexandros Lamprineas };
80e8048f0dSRenato Golin // List of CPU names and their arches.
81e8048f0dSRenato Golin // The same CPU can have multiple arches and can be default on multiple arches.
82e8048f0dSRenato Golin // When finding the Arch for a CPU, first-found prevails. Sort them accordingly.
837374fcdbSRenato Golin // When this becomes table-generated, we'd probably need two tables.
84e8048f0dSRenato Golin // FIXME: TableGen this.
85e8048f0dSRenato Golin struct {
86e8048f0dSRenato Golin   const char *Name;
87e8048f0dSRenato Golin   ARM::ArchKind ArchID;
88fcd93d53SAlexandros Lamprineas   ARM::FPUKind DefaultFPU;
89fcd93d53SAlexandros Lamprineas   bool Default; // is $Name the default CPU for $ArchID ?
90e8048f0dSRenato Golin } CPUNames[] = {
91*799e880eSChandler Carruth #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT) \
92*799e880eSChandler Carruth   { NAME, ID, DEFAULT_FPU, IS_DEFAULT },
93*799e880eSChandler Carruth #include "llvm/Support/ARMTargetParser.def"
94e8048f0dSRenato Golin };
95f5f373fcSRenato Golin 
96f5f373fcSRenato Golin } // namespace
97f5f373fcSRenato Golin 
98f5f373fcSRenato Golin // ======================================================= //
99f5f373fcSRenato Golin // Information by ID
100f5f373fcSRenato Golin // ======================================================= //
101f5f373fcSRenato Golin 
102bb47b9a3SChandler Carruth const char *llvm::ARM::getFPUName(unsigned FPUKind) {
103e8048f0dSRenato Golin   if (FPUKind >= ARM::FK_LAST)
104f5f373fcSRenato Golin     return nullptr;
105e8048f0dSRenato Golin   return FPUNames[FPUKind].Name;
106f5f373fcSRenato Golin }
107f5f373fcSRenato Golin 
108bb47b9a3SChandler Carruth unsigned llvm::ARM::getFPUVersion(unsigned FPUKind) {
109d03d2292SJohn Brawn   if (FPUKind >= ARM::FK_LAST)
110d03d2292SJohn Brawn     return 0;
111d03d2292SJohn Brawn   return FPUNames[FPUKind].FPUVersion;
112d03d2292SJohn Brawn }
113d03d2292SJohn Brawn 
114bb47b9a3SChandler Carruth unsigned llvm::ARM::getFPUNeonSupportLevel(unsigned FPUKind) {
115d03d2292SJohn Brawn   if (FPUKind >= ARM::FK_LAST)
116d03d2292SJohn Brawn     return 0;
117d03d2292SJohn Brawn   return FPUNames[FPUKind].NeonSupport;
118d03d2292SJohn Brawn }
119d03d2292SJohn Brawn 
120bb47b9a3SChandler Carruth unsigned llvm::ARM::getFPURestriction(unsigned FPUKind) {
121d03d2292SJohn Brawn   if (FPUKind >= ARM::FK_LAST)
122d03d2292SJohn Brawn     return 0;
123d03d2292SJohn Brawn   return FPUNames[FPUKind].Restriction;
124d03d2292SJohn Brawn }
125d03d2292SJohn Brawn 
126bb47b9a3SChandler Carruth unsigned llvm::ARM::getDefaultFPU(StringRef CPU) {
127fcd93d53SAlexandros Lamprineas   for (const auto C : CPUNames) {
128fcd93d53SAlexandros Lamprineas     if (CPU == C.Name)
129fcd93d53SAlexandros Lamprineas       return C.DefaultFPU;
130fcd93d53SAlexandros Lamprineas   }
131fcd93d53SAlexandros Lamprineas   return ARM::FK_INVALID;
132fcd93d53SAlexandros Lamprineas }
133fcd93d53SAlexandros Lamprineas 
134bb47b9a3SChandler Carruth bool llvm::ARM::getHWDivFeatures(unsigned HWDivKind,
1354ea70755SAlexandros Lamprineas                                  std::vector<const char *> &Features) {
1364ea70755SAlexandros Lamprineas 
1374ea70755SAlexandros Lamprineas   if (HWDivKind == ARM::AEK_INVALID)
1384ea70755SAlexandros Lamprineas     return false;
1394ea70755SAlexandros Lamprineas 
1404ea70755SAlexandros Lamprineas   if (HWDivKind & ARM::AEK_HWDIVARM)
1414ea70755SAlexandros Lamprineas     Features.push_back("+hwdiv-arm");
1424ea70755SAlexandros Lamprineas   else
1434ea70755SAlexandros Lamprineas     Features.push_back("-hwdiv-arm");
1444ea70755SAlexandros Lamprineas 
1454ea70755SAlexandros Lamprineas   if (HWDivKind & ARM::AEK_HWDIV)
1464ea70755SAlexandros Lamprineas     Features.push_back("+hwdiv");
1474ea70755SAlexandros Lamprineas   else
1484ea70755SAlexandros Lamprineas     Features.push_back("-hwdiv");
1494ea70755SAlexandros Lamprineas 
1504ea70755SAlexandros Lamprineas   return true;
1514ea70755SAlexandros Lamprineas }
1524ea70755SAlexandros Lamprineas 
153bb47b9a3SChandler Carruth bool llvm::ARM::getFPUFeatures(unsigned FPUKind,
154d03d2292SJohn Brawn                                std::vector<const char *> &Features) {
155d03d2292SJohn Brawn 
156d03d2292SJohn Brawn   if (FPUKind >= ARM::FK_LAST || FPUKind == ARM::FK_INVALID)
157d03d2292SJohn Brawn     return false;
158d03d2292SJohn Brawn 
159d03d2292SJohn Brawn   // fp-only-sp and d16 subtarget features are independent of each other, so we
160d03d2292SJohn Brawn   // must enable/disable both.
161d03d2292SJohn Brawn   switch (FPUNames[FPUKind].Restriction) {
162d03d2292SJohn Brawn   case ARM::FR_SP_D16:
163d03d2292SJohn Brawn     Features.push_back("+fp-only-sp");
164d03d2292SJohn Brawn     Features.push_back("+d16");
165d03d2292SJohn Brawn     break;
166d03d2292SJohn Brawn   case ARM::FR_D16:
167d03d2292SJohn Brawn     Features.push_back("-fp-only-sp");
168d03d2292SJohn Brawn     Features.push_back("+d16");
169d03d2292SJohn Brawn     break;
170d03d2292SJohn Brawn   case ARM::FR_None:
171d03d2292SJohn Brawn     Features.push_back("-fp-only-sp");
172d03d2292SJohn Brawn     Features.push_back("-d16");
173d03d2292SJohn Brawn     break;
174d03d2292SJohn Brawn   }
175d03d2292SJohn Brawn 
176d03d2292SJohn Brawn   // FPU version subtarget features are inclusive of lower-numbered ones, so
177d03d2292SJohn Brawn   // enable the one corresponding to this version and disable all that are
178d9e39d53SJohn Brawn   // higher. We also have to make sure to disable fp16 when vfp4 is disabled,
179d9e39d53SJohn Brawn   // as +vfp4 implies +fp16 but -vfp4 does not imply -fp16.
180d03d2292SJohn Brawn   switch (FPUNames[FPUKind].FPUVersion) {
181d5526303SJaved Absar   case ARM::FV_VFPV5:
182d03d2292SJohn Brawn     Features.push_back("+fp-armv8");
183d03d2292SJohn Brawn     break;
184d5526303SJaved Absar   case ARM::FV_VFPV4:
185d03d2292SJohn Brawn     Features.push_back("+vfp4");
186d03d2292SJohn Brawn     Features.push_back("-fp-armv8");
187d03d2292SJohn Brawn     break;
188d5526303SJaved Absar   case ARM::FV_VFPV3_FP16:
189d5526303SJaved Absar     Features.push_back("+vfp3");
190d5526303SJaved Absar     Features.push_back("+fp16");
191d5526303SJaved Absar     Features.push_back("-vfp4");
192d5526303SJaved Absar     Features.push_back("-fp-armv8");
193d5526303SJaved Absar     break;
194d5526303SJaved Absar   case ARM::FV_VFPV3:
195d03d2292SJohn Brawn     Features.push_back("+vfp3");
196d9e39d53SJohn Brawn     Features.push_back("-fp16");
197d03d2292SJohn Brawn     Features.push_back("-vfp4");
198d03d2292SJohn Brawn     Features.push_back("-fp-armv8");
199d03d2292SJohn Brawn     break;
200d5526303SJaved Absar   case ARM::FV_VFPV2:
201d03d2292SJohn Brawn     Features.push_back("+vfp2");
202d03d2292SJohn Brawn     Features.push_back("-vfp3");
203d9e39d53SJohn Brawn     Features.push_back("-fp16");
204d03d2292SJohn Brawn     Features.push_back("-vfp4");
205d03d2292SJohn Brawn     Features.push_back("-fp-armv8");
206d03d2292SJohn Brawn     break;
207d5526303SJaved Absar   case ARM::FV_NONE:
208d03d2292SJohn Brawn     Features.push_back("-vfp2");
209d03d2292SJohn Brawn     Features.push_back("-vfp3");
210d9e39d53SJohn Brawn     Features.push_back("-fp16");
211d03d2292SJohn Brawn     Features.push_back("-vfp4");
212d03d2292SJohn Brawn     Features.push_back("-fp-armv8");
213d03d2292SJohn Brawn     break;
214d03d2292SJohn Brawn   }
215d03d2292SJohn Brawn 
216d03d2292SJohn Brawn   // crypto includes neon, so we handle this similarly to FPU version.
217d03d2292SJohn Brawn   switch (FPUNames[FPUKind].NeonSupport) {
218d03d2292SJohn Brawn   case ARM::NS_Crypto:
219d03d2292SJohn Brawn     Features.push_back("+crypto");
220d03d2292SJohn Brawn     break;
221d03d2292SJohn Brawn   case ARM::NS_Neon:
222d03d2292SJohn Brawn     Features.push_back("+neon");
223d03d2292SJohn Brawn     Features.push_back("-crypto");
224d03d2292SJohn Brawn     break;
225d03d2292SJohn Brawn   case ARM::NS_None:
226d03d2292SJohn Brawn     Features.push_back("-neon");
227d03d2292SJohn Brawn     Features.push_back("-crypto");
228d03d2292SJohn Brawn     break;
229d03d2292SJohn Brawn   }
230d03d2292SJohn Brawn 
231d03d2292SJohn Brawn   return true;
232d03d2292SJohn Brawn }
233d03d2292SJohn Brawn 
234bb47b9a3SChandler Carruth const char *llvm::ARM::getArchName(unsigned ArchKind) {
235e8048f0dSRenato Golin   if (ArchKind >= ARM::AK_LAST)
236f5f373fcSRenato Golin     return nullptr;
237e8048f0dSRenato Golin   return ARCHNames[ArchKind].Name;
238f5f373fcSRenato Golin }
239f5f373fcSRenato Golin 
240bb47b9a3SChandler Carruth const char *llvm::ARM::getCPUAttr(unsigned ArchKind) {
241e8048f0dSRenato Golin   if (ArchKind >= ARM::AK_LAST)
242f5f373fcSRenato Golin     return nullptr;
243f7c0d5f2SRenato Golin   return ARCHNames[ArchKind].CPUAttr;
244f5f373fcSRenato Golin }
245f5f373fcSRenato Golin 
246bb47b9a3SChandler Carruth const char *llvm::ARM::getSubArch(unsigned ArchKind) {
24742dad647SRenato Golin   if (ArchKind >= ARM::AK_LAST)
24842dad647SRenato Golin     return nullptr;
24942dad647SRenato Golin   return ARCHNames[ArchKind].SubArch;
25042dad647SRenato Golin }
25142dad647SRenato Golin 
252bb47b9a3SChandler Carruth unsigned llvm::ARM::getArchAttr(unsigned ArchKind) {
253e8048f0dSRenato Golin   if (ArchKind >= ARM::AK_LAST)
254e8048f0dSRenato Golin     return ARMBuildAttrs::CPUArch::Pre_v4;
255f7c0d5f2SRenato Golin   return ARCHNames[ArchKind].ArchAttr;
256f5f373fcSRenato Golin }
257f5f373fcSRenato Golin 
258bb47b9a3SChandler Carruth const char *llvm::ARM::getArchExtName(unsigned ArchExtKind) {
2594ea70755SAlexandros Lamprineas   for (const auto AE : ARCHExtNames) {
2604ea70755SAlexandros Lamprineas     if (ArchExtKind == AE.ID)
2614ea70755SAlexandros Lamprineas       return AE.Name;
2624ea70755SAlexandros Lamprineas   }
263f5f373fcSRenato Golin   return nullptr;
2644ea70755SAlexandros Lamprineas }
2654ea70755SAlexandros Lamprineas 
266bb47b9a3SChandler Carruth const char *llvm::ARM::getHWDivName(unsigned HWDivKind) {
2674ea70755SAlexandros Lamprineas   for (const auto D : HWDivNames) {
2684ea70755SAlexandros Lamprineas     if (HWDivKind == D.ID)
2694ea70755SAlexandros Lamprineas       return D.Name;
2704ea70755SAlexandros Lamprineas   }
2714ea70755SAlexandros Lamprineas   return nullptr;
272e8048f0dSRenato Golin }
273e8048f0dSRenato Golin 
274bb47b9a3SChandler Carruth const char *llvm::ARM::getDefaultCPU(StringRef Arch) {
275e8048f0dSRenato Golin   unsigned AK = parseArch(Arch);
276e8048f0dSRenato Golin   if (AK == ARM::AK_INVALID)
277e8048f0dSRenato Golin     return nullptr;
278e8048f0dSRenato Golin 
279e8048f0dSRenato Golin   // Look for multiple AKs to find the default for pair AK+Name.
280e8048f0dSRenato Golin   for (const auto CPU : CPUNames) {
281e8048f0dSRenato Golin     if (CPU.ArchID == AK && CPU.Default)
282e8048f0dSRenato Golin       return CPU.Name;
283e8048f0dSRenato Golin   }
284e8048f0dSRenato Golin   return nullptr;
285f5f373fcSRenato Golin }
286f5f373fcSRenato Golin 
287f5f373fcSRenato Golin // ======================================================= //
288f5f373fcSRenato Golin // Parsers
289f5f373fcSRenato Golin // ======================================================= //
290f5f373fcSRenato Golin 
291bb47b9a3SChandler Carruth static StringRef getHWDivSynonym(StringRef HWDiv) {
2924ea70755SAlexandros Lamprineas   return StringSwitch<StringRef>(HWDiv)
2934ea70755SAlexandros Lamprineas       .Case("thumb,arm", "arm,thumb")
2944ea70755SAlexandros Lamprineas       .Default(HWDiv);
2954ea70755SAlexandros Lamprineas }
2964ea70755SAlexandros Lamprineas 
297bb47b9a3SChandler Carruth static StringRef getFPUSynonym(StringRef FPU) {
298f5f373fcSRenato Golin   return StringSwitch<StringRef>(FPU)
299f5f373fcSRenato Golin       .Cases("fpa", "fpe2", "fpe3", "maverick", "invalid") // Unsupported
300f5f373fcSRenato Golin       .Case("vfp2", "vfpv2")
301f5f373fcSRenato Golin       .Case("vfp3", "vfpv3")
302f5f373fcSRenato Golin       .Case("vfp4", "vfpv4")
303f5f373fcSRenato Golin       .Case("vfp3-d16", "vfpv3-d16")
304f5f373fcSRenato Golin       .Case("vfp4-d16", "vfpv4-d16")
305985c04e8SJohn Brawn       .Cases("fp4-sp-d16", "vfpv4-sp-d16", "fpv4-sp-d16")
306f5f373fcSRenato Golin       .Cases("fp4-dp-d16", "fpv4-dp-d16", "vfpv4-d16")
307985c04e8SJohn Brawn       .Case("fp5-sp-d16", "fpv5-sp-d16")
308f5f373fcSRenato Golin       .Cases("fp5-dp-d16", "fpv5-dp-d16", "fpv5-d16")
309f5f373fcSRenato Golin       // FIXME: Clang uses it, but it's bogus, since neon defaults to vfpv3.
310f5f373fcSRenato Golin       .Case("neon-vfpv3", "neon")
311f5f373fcSRenato Golin       .Default(FPU);
312f5f373fcSRenato Golin }
313f5f373fcSRenato Golin 
314bb47b9a3SChandler Carruth static StringRef getArchSynonym(StringRef Arch) {
315f5f373fcSRenato Golin   return StringSwitch<StringRef>(Arch)
31685aebc8cSArtyom Skrobov       .Case("v6sm", "v6s-m")
31785aebc8cSArtyom Skrobov       .Case("v6m", "v6-m")
31885aebc8cSArtyom Skrobov       .Case("v7a", "v7-a")
31985aebc8cSArtyom Skrobov       .Case("v7r", "v7-r")
32085aebc8cSArtyom Skrobov       .Case("v7m", "v7-m")
32185aebc8cSArtyom Skrobov       .Case("v7em", "v7e-m")
322acd1cd66SArtyom Skrobov       .Cases("v8", "v8a", "aarch64", "arm64", "v8-a")
32385aebc8cSArtyom Skrobov       .Case("v8.1a", "v8.1-a")
324f5f373fcSRenato Golin       .Default(Arch);
325f5f373fcSRenato Golin }
326f5f373fcSRenato Golin 
327e8048f0dSRenato Golin // MArch is expected to be of the form (arm|thumb)?(eb)?(v.+)?(eb)?, but
328e8048f0dSRenato Golin // (iwmmxt|xscale)(eb)? is also permitted. If the former, return
329ebdd12cbSRenato Golin // "v.+", if the latter, return unmodified string, minus 'eb'.
330ebdd12cbSRenato Golin // If invalid, return empty string.
331bb47b9a3SChandler Carruth StringRef llvm::ARM::getCanonicalArchName(StringRef Arch) {
332e8048f0dSRenato Golin   size_t offset = StringRef::npos;
333e8048f0dSRenato Golin   StringRef A = Arch;
334b6b9e056SRenato Golin   StringRef Error = "";
335e8048f0dSRenato Golin 
336e8048f0dSRenato Golin   // Begins with "arm" / "thumb", move past it.
337ebdd12cbSRenato Golin   if (A.startswith("arm64"))
338ebdd12cbSRenato Golin     offset = 5;
339ebdd12cbSRenato Golin   else if (A.startswith("arm"))
340e8048f0dSRenato Golin     offset = 3;
341e8048f0dSRenato Golin   else if (A.startswith("thumb"))
342e8048f0dSRenato Golin     offset = 5;
343b6b9e056SRenato Golin   else if (A.startswith("aarch64")) {
344b6b9e056SRenato Golin     offset = 7;
345b6b9e056SRenato Golin     // AArch64 uses "_be", not "eb" suffix.
346b6b9e056SRenato Golin     if (A.find("eb") != StringRef::npos)
347b6b9e056SRenato Golin       return Error;
348b6b9e056SRenato Golin     if (A.substr(offset, 3) == "_be")
349b6b9e056SRenato Golin       offset += 3;
350b6b9e056SRenato Golin   }
351b6b9e056SRenato Golin 
352e8048f0dSRenato Golin   // Ex. "armebv7", move past the "eb".
353e8048f0dSRenato Golin   if (offset != StringRef::npos && A.substr(offset, 2) == "eb")
354e8048f0dSRenato Golin     offset += 2;
355e8048f0dSRenato Golin   // Or, if it ends with eb ("armv7eb"), chop it off.
356e8048f0dSRenato Golin   else if (A.endswith("eb"))
357e8048f0dSRenato Golin     A = A.substr(0, A.size() - 2);
358ebdd12cbSRenato Golin   // Trim the head
359ebdd12cbSRenato Golin   if (offset != StringRef::npos)
360e8048f0dSRenato Golin     A = A.substr(offset);
361e8048f0dSRenato Golin 
362ebdd12cbSRenato Golin   // Empty string means offset reached the end, which means it's valid.
363e8048f0dSRenato Golin   if (A.empty())
364e8048f0dSRenato Golin     return Arch;
365e8048f0dSRenato Golin 
366ebdd12cbSRenato Golin   // Only match non-marketing names
367ebdd12cbSRenato Golin   if (offset != StringRef::npos) {
368ebdd12cbSRenato Golin     // Must start with 'vN'.
369ebdd12cbSRenato Golin     if (A[0] != 'v' || !std::isdigit(A[1]))
370b6b9e056SRenato Golin       return Error;
371ebdd12cbSRenato Golin     // Can't have an extra 'eb'.
372ebdd12cbSRenato Golin     if (A.find("eb") != StringRef::npos)
373ebdd12cbSRenato Golin       return Error;
374ebdd12cbSRenato Golin   }
375e8048f0dSRenato Golin 
376ebdd12cbSRenato Golin   // Arch will either be a 'v' name (v7a) or a marketing name (xscale).
377e8048f0dSRenato Golin   return A;
378e8048f0dSRenato Golin }
379e8048f0dSRenato Golin 
380bb47b9a3SChandler Carruth unsigned llvm::ARM::parseHWDiv(StringRef HWDiv) {
3814ea70755SAlexandros Lamprineas   StringRef Syn = getHWDivSynonym(HWDiv);
3824ea70755SAlexandros Lamprineas   for (const auto D : HWDivNames) {
3834ea70755SAlexandros Lamprineas     if (Syn == D.Name)
3844ea70755SAlexandros Lamprineas       return D.ID;
3854ea70755SAlexandros Lamprineas   }
3864ea70755SAlexandros Lamprineas   return ARM::AEK_INVALID;
3874ea70755SAlexandros Lamprineas }
3884ea70755SAlexandros Lamprineas 
389bb47b9a3SChandler Carruth unsigned llvm::ARM::parseFPU(StringRef FPU) {
390f5f373fcSRenato Golin   StringRef Syn = getFPUSynonym(FPU);
391f5f373fcSRenato Golin   for (const auto F : FPUNames) {
392f5f373fcSRenato Golin     if (Syn == F.Name)
393f5f373fcSRenato Golin       return F.ID;
394f5f373fcSRenato Golin   }
39535de35d0SRenato Golin   return ARM::FK_INVALID;
396f5f373fcSRenato Golin }
397f5f373fcSRenato Golin 
398e8048f0dSRenato Golin // Allows partial match, ex. "v7a" matches "armv7a".
399bb47b9a3SChandler Carruth unsigned llvm::ARM::parseArch(StringRef Arch) {
40085aebc8cSArtyom Skrobov   Arch = getCanonicalArchName(Arch);
401f5f373fcSRenato Golin   StringRef Syn = getArchSynonym(Arch);
402f5f373fcSRenato Golin   for (const auto A : ARCHNames) {
403e8048f0dSRenato Golin     if (StringRef(A.Name).endswith(Syn))
404f5f373fcSRenato Golin       return A.ID;
405f5f373fcSRenato Golin   }
40635de35d0SRenato Golin   return ARM::AK_INVALID;
407f5f373fcSRenato Golin }
408f5f373fcSRenato Golin 
409bb47b9a3SChandler Carruth unsigned llvm::ARM::parseArchExt(StringRef ArchExt) {
410f5f373fcSRenato Golin   for (const auto A : ARCHExtNames) {
411f5f373fcSRenato Golin     if (ArchExt == A.Name)
412f5f373fcSRenato Golin       return A.ID;
413f5f373fcSRenato Golin   }
41435de35d0SRenato Golin   return ARM::AEK_INVALID;
415f5f373fcSRenato Golin }
416f5f373fcSRenato Golin 
417bb47b9a3SChandler Carruth unsigned llvm::ARM::parseCPUArch(StringRef CPU) {
418e8048f0dSRenato Golin   for (const auto C : CPUNames) {
419e8048f0dSRenato Golin     if (CPU == C.Name)
420e8048f0dSRenato Golin       return C.ArchID;
421e8048f0dSRenato Golin   }
422e8048f0dSRenato Golin   return ARM::AK_INVALID;
423e8048f0dSRenato Golin }
424e8048f0dSRenato Golin 
425b6b9e056SRenato Golin // ARM, Thumb, AArch64
426bb47b9a3SChandler Carruth unsigned llvm::ARM::parseArchISA(StringRef Arch) {
427b6b9e056SRenato Golin   return StringSwitch<unsigned>(Arch)
428b6b9e056SRenato Golin       .StartsWith("aarch64", ARM::IK_AARCH64)
429b6b9e056SRenato Golin       .StartsWith("arm64", ARM::IK_AARCH64)
430b6b9e056SRenato Golin       .StartsWith("thumb", ARM::IK_THUMB)
431b6b9e056SRenato Golin       .StartsWith("arm", ARM::IK_ARM)
432b6b9e056SRenato Golin       .Default(ARM::EK_INVALID);
433b6b9e056SRenato Golin }
434b6b9e056SRenato Golin 
435b6b9e056SRenato Golin // Little/Big endian
436bb47b9a3SChandler Carruth unsigned llvm::ARM::parseArchEndian(StringRef Arch) {
4374fc3a986SChandler Carruth   if (Arch.startswith("armeb") || Arch.startswith("thumbeb") ||
438b6b9e056SRenato Golin       Arch.startswith("aarch64_be"))
439b6b9e056SRenato Golin     return ARM::EK_BIG;
440b6b9e056SRenato Golin 
441b6b9e056SRenato Golin   if (Arch.startswith("arm") || Arch.startswith("thumb")) {
442b6b9e056SRenato Golin     if (Arch.endswith("eb"))
443b6b9e056SRenato Golin       return ARM::EK_BIG;
444b6b9e056SRenato Golin     else
445b6b9e056SRenato Golin       return ARM::EK_LITTLE;
446b6b9e056SRenato Golin   }
447b6b9e056SRenato Golin 
448b6b9e056SRenato Golin   if (Arch.startswith("aarch64"))
449b6b9e056SRenato Golin     return ARM::EK_LITTLE;
450b6b9e056SRenato Golin 
451b6b9e056SRenato Golin   return ARM::EK_INVALID;
452b6b9e056SRenato Golin }
453b6b9e056SRenato Golin 
454fadc2108SRenato Golin // Profile A/R/M
455bb47b9a3SChandler Carruth unsigned llvm::ARM::parseArchProfile(StringRef Arch) {
456fadc2108SRenato Golin   Arch = getCanonicalArchName(Arch);
457fadc2108SRenato Golin   switch (parseArch(Arch)) {
458fadc2108SRenato Golin   case ARM::AK_ARMV6M:
459fadc2108SRenato Golin   case ARM::AK_ARMV7M:
460fadc2108SRenato Golin   case ARM::AK_ARMV6SM:
461fadc2108SRenato Golin   case ARM::AK_ARMV7EM:
462fadc2108SRenato Golin     return ARM::PK_M;
463fadc2108SRenato Golin   case ARM::AK_ARMV7R:
464fadc2108SRenato Golin     return ARM::PK_R;
465fadc2108SRenato Golin   case ARM::AK_ARMV7:
466fadc2108SRenato Golin   case ARM::AK_ARMV7A:
4670e20b8dcSAlexandros Lamprineas   case ARM::AK_ARMV7L:
468fadc2108SRenato Golin   case ARM::AK_ARMV8A:
469fadc2108SRenato Golin   case ARM::AK_ARMV8_1A:
470fadc2108SRenato Golin     return ARM::PK_A;
471fadc2108SRenato Golin   }
472fadc2108SRenato Golin   return ARM::PK_INVALID;
473fadc2108SRenato Golin }
474fadc2108SRenato Golin 
475ebdd12cbSRenato Golin // Version number (ex. v7 = 7).
476bb47b9a3SChandler Carruth unsigned llvm::ARM::parseArchVersion(StringRef Arch) {
477fadc2108SRenato Golin   Arch = getCanonicalArchName(Arch);
478fadc2108SRenato Golin   switch (parseArch(Arch)) {
479fadc2108SRenato Golin   case ARM::AK_ARMV2:
480fadc2108SRenato Golin   case ARM::AK_ARMV2A:
481fadc2108SRenato Golin     return 2;
482fadc2108SRenato Golin   case ARM::AK_ARMV3:
483fadc2108SRenato Golin   case ARM::AK_ARMV3M:
484fadc2108SRenato Golin     return 3;
485fadc2108SRenato Golin   case ARM::AK_ARMV4:
486fadc2108SRenato Golin   case ARM::AK_ARMV4T:
487fadc2108SRenato Golin     return 4;
488fadc2108SRenato Golin   case ARM::AK_ARMV5:
489fadc2108SRenato Golin   case ARM::AK_ARMV5T:
490fadc2108SRenato Golin   case ARM::AK_ARMV5TE:
491fadc2108SRenato Golin   case ARM::AK_IWMMXT:
492fadc2108SRenato Golin   case ARM::AK_IWMMXT2:
493fadc2108SRenato Golin   case ARM::AK_XSCALE:
494fadc2108SRenato Golin   case ARM::AK_ARMV5E:
495fadc2108SRenato Golin   case ARM::AK_ARMV5TEJ:
496fadc2108SRenato Golin     return 5;
497fadc2108SRenato Golin   case ARM::AK_ARMV6:
498fadc2108SRenato Golin   case ARM::AK_ARMV6J:
499fadc2108SRenato Golin   case ARM::AK_ARMV6K:
500fadc2108SRenato Golin   case ARM::AK_ARMV6T2:
501fadc2108SRenato Golin   case ARM::AK_ARMV6Z:
502fadc2108SRenato Golin   case ARM::AK_ARMV6ZK:
503fadc2108SRenato Golin   case ARM::AK_ARMV6M:
504fadc2108SRenato Golin   case ARM::AK_ARMV6SM:
505fadc2108SRenato Golin   case ARM::AK_ARMV6HL:
506fadc2108SRenato Golin     return 6;
507fadc2108SRenato Golin   case ARM::AK_ARMV7:
508fadc2108SRenato Golin   case ARM::AK_ARMV7A:
509fadc2108SRenato Golin   case ARM::AK_ARMV7R:
510fadc2108SRenato Golin   case ARM::AK_ARMV7M:
511fadc2108SRenato Golin   case ARM::AK_ARMV7L:
512fadc2108SRenato Golin   case ARM::AK_ARMV7HL:
513fadc2108SRenato Golin   case ARM::AK_ARMV7S:
514fadc2108SRenato Golin   case ARM::AK_ARMV7EM:
515366dd9fdSVedant Kumar   case ARM::AK_ARMV7K:
516fadc2108SRenato Golin     return 7;
517fadc2108SRenato Golin   case ARM::AK_ARMV8A:
518fadc2108SRenato Golin   case ARM::AK_ARMV8_1A:
519fadc2108SRenato Golin     return 8;
520fadc2108SRenato Golin   }
521fadc2108SRenato Golin   return 0;
522fadc2108SRenato Golin }
523