TargetParser.cpp revision 296417
1283625Sdim//===-- TargetParser - Parser for target features ---------------*- C++ -*-===//
2283625Sdim//
3283625Sdim//                     The LLVM Compiler Infrastructure
4283625Sdim//
5283625Sdim// This file is distributed under the University of Illinois Open Source
6283625Sdim// License. See LICENSE.TXT for details.
7283625Sdim//
8283625Sdim//===----------------------------------------------------------------------===//
9283625Sdim//
10283625Sdim// This file implements a target parser to recognise hardware features such as
11283625Sdim// FPU/CPU/ARCH names as well as specific support such as HDIV, etc.
12283625Sdim//
13283625Sdim//===----------------------------------------------------------------------===//
14283625Sdim
15283625Sdim#include "llvm/Support/ARMBuildAttributes.h"
16283625Sdim#include "llvm/Support/TargetParser.h"
17283625Sdim#include "llvm/ADT/StringExtras.h"
18283625Sdim#include "llvm/ADT/StringSwitch.h"
19296417Sdim#include "llvm/ADT/Twine.h"
20283625Sdim#include <cctype>
21283625Sdim
22283625Sdimusing namespace llvm;
23296417Sdimusing namespace ARM;
24283625Sdim
25283625Sdimnamespace {
26283625Sdim
27284236Sdim// List of canonical FPU names (use getFPUSynonym) and which architectural
28284236Sdim// features they correspond to (use getFPUFeatures).
29283625Sdim// FIXME: TableGen this.
30285181Sdim// The entries must appear in the order listed in ARM::FPUKind for correct indexing
31296417Sdimstatic const struct {
32296417Sdim  const char *NameCStr;
33296417Sdim  size_t NameLength;
34283625Sdim  ARM::FPUKind ID;
35285181Sdim  ARM::FPUVersion FPUVersion;
36284236Sdim  ARM::NeonSupportLevel NeonSupport;
37284236Sdim  ARM::FPURestriction Restriction;
38296417Sdim
39296417Sdim  StringRef getName() const { return StringRef(NameCStr, NameLength); }
40283625Sdim} FPUNames[] = {
41296417Sdim#define ARM_FPU(NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION) \
42296417Sdim  { NAME, sizeof(NAME) - 1, KIND, VERSION, NEON_SUPPORT, RESTRICTION },
43296417Sdim#include "llvm/Support/ARMTargetParser.def"
44283625Sdim};
45284236Sdim
46284236Sdim// List of canonical arch names (use getArchSynonym).
47284236Sdim// This table also provides the build attribute fields for CPU arch
48284236Sdim// and Arch ID, according to the Addenda to the ARM ABI, chapters
49284236Sdim// 2.4 and 2.3.5.2 respectively.
50284236Sdim// FIXME: SubArch values were simplified to fit into the expectations
51284236Sdim// of the triples and are not conforming with their official names.
52284236Sdim// Check to see if the expectation should be changed.
53283625Sdim// FIXME: TableGen this.
54296417Sdimstatic const struct {
55296417Sdim  const char *NameCStr;
56296417Sdim  size_t NameLength;
57296417Sdim  const char *CPUAttrCStr;
58296417Sdim  size_t CPUAttrLength;
59296417Sdim  const char *SubArchCStr;
60296417Sdim  size_t SubArchLength;
61296417Sdim  unsigned DefaultFPU;
62296417Sdim  unsigned ArchBaseExtensions;
63283625Sdim  ARM::ArchKind ID;
64284236Sdim  ARMBuildAttrs::CPUArch ArchAttr; // Arch ID in build attributes.
65296417Sdim
66296417Sdim  StringRef getName() const { return StringRef(NameCStr, NameLength); }
67296417Sdim
68296417Sdim  // CPU class in build attributes.
69296417Sdim  StringRef getCPUAttr() const { return StringRef(CPUAttrCStr, CPUAttrLength); }
70296417Sdim
71296417Sdim  // Sub-Arch name.
72296417Sdim  StringRef getSubArch() const { return StringRef(SubArchCStr, SubArchLength); }
73283625Sdim} ARCHNames[] = {
74296417Sdim#define ARM_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT)       \
75296417Sdim  {NAME, sizeof(NAME) - 1, CPU_ATTR, sizeof(CPU_ATTR) - 1, SUB_ARCH,       \
76296417Sdim   sizeof(SUB_ARCH) - 1, ARCH_FPU, ARCH_BASE_EXT, ID, ARCH_ATTR},
77296417Sdim#include "llvm/Support/ARMTargetParser.def"
78283625Sdim};
79296417Sdim
80284236Sdim// List of Arch Extension names.
81283625Sdim// FIXME: TableGen this.
82296417Sdimstatic const struct {
83296417Sdim  const char *NameCStr;
84296417Sdim  size_t NameLength;
85296417Sdim  unsigned ID;
86296417Sdim  const char *Feature;
87296417Sdim  const char *NegFeature;
88296417Sdim
89296417Sdim  StringRef getName() const { return StringRef(NameCStr, NameLength); }
90283625Sdim} ARCHExtNames[] = {
91296417Sdim#define ARM_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE) \
92296417Sdim  { NAME, sizeof(NAME) - 1, ID, FEATURE, NEGFEATURE },
93296417Sdim#include "llvm/Support/ARMTargetParser.def"
94283625Sdim};
95296417Sdim
96296417Sdim// List of HWDiv names (use getHWDivSynonym) and which architectural
97296417Sdim// features they correspond to (use getHWDivFeatures).
98296417Sdim// FIXME: TableGen this.
99296417Sdimstatic const struct {
100296417Sdim  const char *NameCStr;
101296417Sdim  size_t NameLength;
102296417Sdim  unsigned ID;
103296417Sdim
104296417Sdim  StringRef getName() const { return StringRef(NameCStr, NameLength); }
105296417Sdim} HWDivNames[] = {
106296417Sdim#define ARM_HW_DIV_NAME(NAME, ID) { NAME, sizeof(NAME) - 1, ID },
107296417Sdim#include "llvm/Support/ARMTargetParser.def"
108296417Sdim};
109296417Sdim
110283625Sdim// List of CPU names and their arches.
111283625Sdim// The same CPU can have multiple arches and can be default on multiple arches.
112283625Sdim// When finding the Arch for a CPU, first-found prevails. Sort them accordingly.
113284236Sdim// When this becomes table-generated, we'd probably need two tables.
114283625Sdim// FIXME: TableGen this.
115296417Sdimstatic const struct {
116296417Sdim  const char *NameCStr;
117296417Sdim  size_t NameLength;
118283625Sdim  ARM::ArchKind ArchID;
119296417Sdim  bool Default; // is $Name the default CPU for $ArchID ?
120296417Sdim  unsigned DefaultExtensions;
121296417Sdim
122296417Sdim  StringRef getName() const { return StringRef(NameCStr, NameLength); }
123283625Sdim} CPUNames[] = {
124296417Sdim#define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
125296417Sdim  { NAME, sizeof(NAME) - 1, ID, IS_DEFAULT, DEFAULT_EXT },
126296417Sdim#include "llvm/Support/ARMTargetParser.def"
127283625Sdim};
128283625Sdim
129283625Sdim} // namespace
130283625Sdim
131283625Sdim// ======================================================= //
132283625Sdim// Information by ID
133283625Sdim// ======================================================= //
134283625Sdim
135296417SdimStringRef llvm::ARM::getFPUName(unsigned FPUKind) {
136283625Sdim  if (FPUKind >= ARM::FK_LAST)
137296417Sdim    return StringRef();
138296417Sdim  return FPUNames[FPUKind].getName();
139283625Sdim}
140283625Sdim
141296417Sdimunsigned llvm::ARM::getFPUVersion(unsigned FPUKind) {
142284236Sdim  if (FPUKind >= ARM::FK_LAST)
143284236Sdim    return 0;
144284236Sdim  return FPUNames[FPUKind].FPUVersion;
145284236Sdim}
146284236Sdim
147296417Sdimunsigned llvm::ARM::getFPUNeonSupportLevel(unsigned FPUKind) {
148284236Sdim  if (FPUKind >= ARM::FK_LAST)
149284236Sdim    return 0;
150284236Sdim  return FPUNames[FPUKind].NeonSupport;
151284236Sdim}
152284236Sdim
153296417Sdimunsigned llvm::ARM::getFPURestriction(unsigned FPUKind) {
154284236Sdim  if (FPUKind >= ARM::FK_LAST)
155284236Sdim    return 0;
156284236Sdim  return FPUNames[FPUKind].Restriction;
157284236Sdim}
158284236Sdim
159296417Sdimunsigned llvm::ARM::getDefaultFPU(StringRef CPU, unsigned ArchKind) {
160296417Sdim  if (CPU == "generic")
161296417Sdim    return ARCHNames[ArchKind].DefaultFPU;
162296417Sdim
163296417Sdim  return StringSwitch<unsigned>(CPU)
164296417Sdim#define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
165296417Sdim    .Case(NAME, DEFAULT_FPU)
166296417Sdim#include "llvm/Support/ARMTargetParser.def"
167296417Sdim    .Default(ARM::FK_INVALID);
168296417Sdim}
169296417Sdim
170296417Sdimunsigned llvm::ARM::getDefaultExtensions(StringRef CPU, unsigned ArchKind) {
171296417Sdim  if (CPU == "generic")
172296417Sdim    return ARCHNames[ArchKind].ArchBaseExtensions;
173296417Sdim
174296417Sdim  return StringSwitch<unsigned>(CPU)
175296417Sdim#define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
176296417Sdim    .Case(NAME, ARCHNames[ID].ArchBaseExtensions | DEFAULT_EXT)
177296417Sdim#include "llvm/Support/ARMTargetParser.def"
178296417Sdim    .Default(ARM::AEK_INVALID);
179296417Sdim}
180296417Sdim
181296417Sdimbool llvm::ARM::getHWDivFeatures(unsigned HWDivKind,
182296417Sdim                                 std::vector<const char *> &Features) {
183296417Sdim
184296417Sdim  if (HWDivKind == ARM::AEK_INVALID)
185296417Sdim    return false;
186296417Sdim
187296417Sdim  if (HWDivKind & ARM::AEK_HWDIVARM)
188296417Sdim    Features.push_back("+hwdiv-arm");
189296417Sdim  else
190296417Sdim    Features.push_back("-hwdiv-arm");
191296417Sdim
192296417Sdim  if (HWDivKind & ARM::AEK_HWDIV)
193296417Sdim    Features.push_back("+hwdiv");
194296417Sdim  else
195296417Sdim    Features.push_back("-hwdiv");
196296417Sdim
197296417Sdim  return true;
198296417Sdim}
199296417Sdim
200296417Sdimbool llvm::ARM::getExtensionFeatures(unsigned Extensions,
201284236Sdim                                     std::vector<const char *> &Features) {
202284236Sdim
203296417Sdim  if (Extensions == ARM::AEK_INVALID)
204296417Sdim    return false;
205296417Sdim
206296417Sdim  if (Extensions & ARM::AEK_CRC)
207296417Sdim    Features.push_back("+crc");
208296417Sdim  else
209296417Sdim    Features.push_back("-crc");
210296417Sdim
211296417Sdim  if (Extensions & ARM::AEK_DSP)
212296417Sdim    Features.push_back("+dsp");
213296417Sdim  else
214296417Sdim    Features.push_back("-dsp");
215296417Sdim
216296417Sdim  return getHWDivFeatures(Extensions, Features);
217296417Sdim}
218296417Sdim
219296417Sdimbool llvm::ARM::getFPUFeatures(unsigned FPUKind,
220296417Sdim                               std::vector<const char *> &Features) {
221296417Sdim
222284236Sdim  if (FPUKind >= ARM::FK_LAST || FPUKind == ARM::FK_INVALID)
223284236Sdim    return false;
224284236Sdim
225284236Sdim  // fp-only-sp and d16 subtarget features are independent of each other, so we
226284236Sdim  // must enable/disable both.
227284236Sdim  switch (FPUNames[FPUKind].Restriction) {
228284236Sdim  case ARM::FR_SP_D16:
229284236Sdim    Features.push_back("+fp-only-sp");
230284236Sdim    Features.push_back("+d16");
231284236Sdim    break;
232284236Sdim  case ARM::FR_D16:
233284236Sdim    Features.push_back("-fp-only-sp");
234284236Sdim    Features.push_back("+d16");
235284236Sdim    break;
236284236Sdim  case ARM::FR_None:
237284236Sdim    Features.push_back("-fp-only-sp");
238284236Sdim    Features.push_back("-d16");
239284236Sdim    break;
240284236Sdim  }
241284236Sdim
242284236Sdim  // FPU version subtarget features are inclusive of lower-numbered ones, so
243284236Sdim  // enable the one corresponding to this version and disable all that are
244284734Sdim  // higher. We also have to make sure to disable fp16 when vfp4 is disabled,
245284734Sdim  // as +vfp4 implies +fp16 but -vfp4 does not imply -fp16.
246284236Sdim  switch (FPUNames[FPUKind].FPUVersion) {
247285181Sdim  case ARM::FV_VFPV5:
248284236Sdim    Features.push_back("+fp-armv8");
249284236Sdim    break;
250285181Sdim  case ARM::FV_VFPV4:
251284236Sdim    Features.push_back("+vfp4");
252284236Sdim    Features.push_back("-fp-armv8");
253284236Sdim    break;
254285181Sdim  case ARM::FV_VFPV3_FP16:
255284236Sdim    Features.push_back("+vfp3");
256285181Sdim    Features.push_back("+fp16");
257285181Sdim    Features.push_back("-vfp4");
258285181Sdim    Features.push_back("-fp-armv8");
259285181Sdim    break;
260285181Sdim  case ARM::FV_VFPV3:
261285181Sdim    Features.push_back("+vfp3");
262284734Sdim    Features.push_back("-fp16");
263284236Sdim    Features.push_back("-vfp4");
264284236Sdim    Features.push_back("-fp-armv8");
265284236Sdim    break;
266285181Sdim  case ARM::FV_VFPV2:
267284236Sdim    Features.push_back("+vfp2");
268284236Sdim    Features.push_back("-vfp3");
269284734Sdim    Features.push_back("-fp16");
270284236Sdim    Features.push_back("-vfp4");
271284236Sdim    Features.push_back("-fp-armv8");
272284236Sdim    break;
273285181Sdim  case ARM::FV_NONE:
274284236Sdim    Features.push_back("-vfp2");
275284236Sdim    Features.push_back("-vfp3");
276284734Sdim    Features.push_back("-fp16");
277284236Sdim    Features.push_back("-vfp4");
278284236Sdim    Features.push_back("-fp-armv8");
279284236Sdim    break;
280284236Sdim  }
281284236Sdim
282284236Sdim  // crypto includes neon, so we handle this similarly to FPU version.
283284236Sdim  switch (FPUNames[FPUKind].NeonSupport) {
284284236Sdim  case ARM::NS_Crypto:
285296417Sdim    Features.push_back("+neon");
286284236Sdim    Features.push_back("+crypto");
287284236Sdim    break;
288284236Sdim  case ARM::NS_Neon:
289284236Sdim    Features.push_back("+neon");
290284236Sdim    Features.push_back("-crypto");
291284236Sdim    break;
292284236Sdim  case ARM::NS_None:
293284236Sdim    Features.push_back("-neon");
294284236Sdim    Features.push_back("-crypto");
295284236Sdim    break;
296284236Sdim  }
297284236Sdim
298284236Sdim  return true;
299284236Sdim}
300284236Sdim
301296417SdimStringRef llvm::ARM::getArchName(unsigned ArchKind) {
302283625Sdim  if (ArchKind >= ARM::AK_LAST)
303296417Sdim    return StringRef();
304296417Sdim  return ARCHNames[ArchKind].getName();
305283625Sdim}
306283625Sdim
307296417SdimStringRef llvm::ARM::getCPUAttr(unsigned ArchKind) {
308283625Sdim  if (ArchKind >= ARM::AK_LAST)
309296417Sdim    return StringRef();
310296417Sdim  return ARCHNames[ArchKind].getCPUAttr();
311283625Sdim}
312283625Sdim
313296417SdimStringRef llvm::ARM::getSubArch(unsigned ArchKind) {
314283625Sdim  if (ArchKind >= ARM::AK_LAST)
315296417Sdim    return StringRef();
316296417Sdim  return ARCHNames[ArchKind].getSubArch();
317284236Sdim}
318284236Sdim
319296417Sdimunsigned llvm::ARM::getArchAttr(unsigned ArchKind) {
320284236Sdim  if (ArchKind >= ARM::AK_LAST)
321283625Sdim    return ARMBuildAttrs::CPUArch::Pre_v4;
322284236Sdim  return ARCHNames[ArchKind].ArchAttr;
323283625Sdim}
324283625Sdim
325296417SdimStringRef llvm::ARM::getArchExtName(unsigned ArchExtKind) {
326296417Sdim  for (const auto AE : ARCHExtNames) {
327296417Sdim    if (ArchExtKind == AE.ID)
328296417Sdim      return AE.getName();
329296417Sdim  }
330296417Sdim  return StringRef();
331283625Sdim}
332283625Sdim
333296417Sdimconst char *llvm::ARM::getArchExtFeature(StringRef ArchExt) {
334296417Sdim  if (ArchExt.startswith("no")) {
335296417Sdim    StringRef ArchExtBase(ArchExt.substr(2));
336296417Sdim    for (const auto AE : ARCHExtNames) {
337296417Sdim      if (AE.NegFeature && ArchExtBase == AE.getName())
338296417Sdim        return AE.NegFeature;
339296417Sdim    }
340296417Sdim  }
341296417Sdim  for (const auto AE : ARCHExtNames) {
342296417Sdim    if (AE.Feature && ArchExt == AE.getName())
343296417Sdim      return AE.Feature;
344296417Sdim  }
345296417Sdim
346296417Sdim  return nullptr;
347296417Sdim}
348296417Sdim
349296417SdimStringRef llvm::ARM::getHWDivName(unsigned HWDivKind) {
350296417Sdim  for (const auto D : HWDivNames) {
351296417Sdim    if (HWDivKind == D.ID)
352296417Sdim      return D.getName();
353296417Sdim  }
354296417Sdim  return StringRef();
355296417Sdim}
356296417Sdim
357296417SdimStringRef llvm::ARM::getDefaultCPU(StringRef Arch) {
358283625Sdim  unsigned AK = parseArch(Arch);
359283625Sdim  if (AK == ARM::AK_INVALID)
360296417Sdim    return StringRef();
361283625Sdim
362283625Sdim  // Look for multiple AKs to find the default for pair AK+Name.
363283625Sdim  for (const auto CPU : CPUNames) {
364283625Sdim    if (CPU.ArchID == AK && CPU.Default)
365296417Sdim      return CPU.getName();
366283625Sdim  }
367296417Sdim
368296417Sdim  // If we can't find a default then target the architecture instead
369296417Sdim  return "generic";
370283625Sdim}
371283625Sdim
372283625Sdim// ======================================================= //
373283625Sdim// Parsers
374283625Sdim// ======================================================= //
375283625Sdim
376296417Sdimstatic StringRef getHWDivSynonym(StringRef HWDiv) {
377296417Sdim  return StringSwitch<StringRef>(HWDiv)
378296417Sdim      .Case("thumb,arm", "arm,thumb")
379296417Sdim      .Default(HWDiv);
380296417Sdim}
381296417Sdim
382296417Sdimstatic StringRef getFPUSynonym(StringRef FPU) {
383283625Sdim  return StringSwitch<StringRef>(FPU)
384296417Sdim      .Cases("fpa", "fpe2", "fpe3", "maverick", "invalid") // Unsupported
385296417Sdim      .Case("vfp2", "vfpv2")
386296417Sdim      .Case("vfp3", "vfpv3")
387296417Sdim      .Case("vfp4", "vfpv4")
388296417Sdim      .Case("vfp3-d16", "vfpv3-d16")
389296417Sdim      .Case("vfp4-d16", "vfpv4-d16")
390296417Sdim      .Cases("fp4-sp-d16", "vfpv4-sp-d16", "fpv4-sp-d16")
391296417Sdim      .Cases("fp4-dp-d16", "fpv4-dp-d16", "vfpv4-d16")
392296417Sdim      .Case("fp5-sp-d16", "fpv5-sp-d16")
393296417Sdim      .Cases("fp5-dp-d16", "fpv5-dp-d16", "fpv5-d16")
394296417Sdim      // FIXME: Clang uses it, but it's bogus, since neon defaults to vfpv3.
395296417Sdim      .Case("neon-vfpv3", "neon")
396296417Sdim      .Default(FPU);
397283625Sdim}
398283625Sdim
399296417Sdimstatic StringRef getArchSynonym(StringRef Arch) {
400283625Sdim  return StringSwitch<StringRef>(Arch)
401296417Sdim      .Case("v5", "v5t")
402296417Sdim      .Case("v5e", "v5te")
403296417Sdim      .Case("v6j", "v6")
404296417Sdim      .Case("v6hl", "v6k")
405296417Sdim      .Cases("v6m", "v6sm", "v6s-m", "v6-m")
406296417Sdim      .Cases("v6z", "v6zk", "v6kz")
407296417Sdim      .Cases("v7", "v7a", "v7hl", "v7l", "v7-a")
408296417Sdim      .Case("v7r", "v7-r")
409296417Sdim      .Case("v7m", "v7-m")
410296417Sdim      .Case("v7em", "v7e-m")
411296417Sdim      .Cases("v8", "v8a", "aarch64", "arm64", "v8-a")
412296417Sdim      .Case("v8.1a", "v8.1-a")
413296417Sdim      .Case("v8.2a", "v8.2-a")
414296417Sdim      .Default(Arch);
415283625Sdim}
416283625Sdim
417283625Sdim// MArch is expected to be of the form (arm|thumb)?(eb)?(v.+)?(eb)?, but
418283625Sdim// (iwmmxt|xscale)(eb)? is also permitted. If the former, return
419283625Sdim// "v.+", if the latter, return unmodified string, minus 'eb'.
420283625Sdim// If invalid, return empty string.
421296417SdimStringRef llvm::ARM::getCanonicalArchName(StringRef Arch) {
422283625Sdim  size_t offset = StringRef::npos;
423283625Sdim  StringRef A = Arch;
424283625Sdim  StringRef Error = "";
425283625Sdim
426283625Sdim  // Begins with "arm" / "thumb", move past it.
427283625Sdim  if (A.startswith("arm64"))
428283625Sdim    offset = 5;
429283625Sdim  else if (A.startswith("arm"))
430283625Sdim    offset = 3;
431283625Sdim  else if (A.startswith("thumb"))
432283625Sdim    offset = 5;
433283625Sdim  else if (A.startswith("aarch64")) {
434283625Sdim    offset = 7;
435283625Sdim    // AArch64 uses "_be", not "eb" suffix.
436283625Sdim    if (A.find("eb") != StringRef::npos)
437283625Sdim      return Error;
438296417Sdim    if (A.substr(offset, 3) == "_be")
439283625Sdim      offset += 3;
440283625Sdim  }
441283625Sdim
442283625Sdim  // Ex. "armebv7", move past the "eb".
443283625Sdim  if (offset != StringRef::npos && A.substr(offset, 2) == "eb")
444283625Sdim    offset += 2;
445283625Sdim  // Or, if it ends with eb ("armv7eb"), chop it off.
446283625Sdim  else if (A.endswith("eb"))
447283625Sdim    A = A.substr(0, A.size() - 2);
448283625Sdim  // Trim the head
449283625Sdim  if (offset != StringRef::npos)
450283625Sdim    A = A.substr(offset);
451283625Sdim
452283625Sdim  // Empty string means offset reached the end, which means it's valid.
453283625Sdim  if (A.empty())
454283625Sdim    return Arch;
455283625Sdim
456283625Sdim  // Only match non-marketing names
457283625Sdim  if (offset != StringRef::npos) {
458296417Sdim    // Must start with 'vN'.
459283625Sdim    if (A[0] != 'v' || !std::isdigit(A[1]))
460283625Sdim      return Error;
461283625Sdim    // Can't have an extra 'eb'.
462283625Sdim    if (A.find("eb") != StringRef::npos)
463283625Sdim      return Error;
464283625Sdim  }
465283625Sdim
466283625Sdim  // Arch will either be a 'v' name (v7a) or a marketing name (xscale).
467283625Sdim  return A;
468283625Sdim}
469283625Sdim
470296417Sdimunsigned llvm::ARM::parseHWDiv(StringRef HWDiv) {
471296417Sdim  StringRef Syn = getHWDivSynonym(HWDiv);
472296417Sdim  for (const auto D : HWDivNames) {
473296417Sdim    if (Syn == D.getName())
474296417Sdim      return D.ID;
475296417Sdim  }
476296417Sdim  return ARM::AEK_INVALID;
477296417Sdim}
478296417Sdim
479296417Sdimunsigned llvm::ARM::parseFPU(StringRef FPU) {
480283625Sdim  StringRef Syn = getFPUSynonym(FPU);
481283625Sdim  for (const auto F : FPUNames) {
482296417Sdim    if (Syn == F.getName())
483283625Sdim      return F.ID;
484283625Sdim  }
485283625Sdim  return ARM::FK_INVALID;
486283625Sdim}
487283625Sdim
488283625Sdim// Allows partial match, ex. "v7a" matches "armv7a".
489296417Sdimunsigned llvm::ARM::parseArch(StringRef Arch) {
490284236Sdim  Arch = getCanonicalArchName(Arch);
491283625Sdim  StringRef Syn = getArchSynonym(Arch);
492283625Sdim  for (const auto A : ARCHNames) {
493296417Sdim    if (A.getName().endswith(Syn))
494283625Sdim      return A.ID;
495283625Sdim  }
496283625Sdim  return ARM::AK_INVALID;
497283625Sdim}
498283625Sdim
499296417Sdimunsigned llvm::ARM::parseArchExt(StringRef ArchExt) {
500283625Sdim  for (const auto A : ARCHExtNames) {
501296417Sdim    if (ArchExt == A.getName())
502283625Sdim      return A.ID;
503283625Sdim  }
504283625Sdim  return ARM::AEK_INVALID;
505283625Sdim}
506283625Sdim
507296417Sdimunsigned llvm::ARM::parseCPUArch(StringRef CPU) {
508283625Sdim  for (const auto C : CPUNames) {
509296417Sdim    if (CPU == C.getName())
510283625Sdim      return C.ArchID;
511283625Sdim  }
512283625Sdim  return ARM::AK_INVALID;
513283625Sdim}
514283625Sdim
515283625Sdim// ARM, Thumb, AArch64
516296417Sdimunsigned llvm::ARM::parseArchISA(StringRef Arch) {
517283625Sdim  return StringSwitch<unsigned>(Arch)
518283625Sdim      .StartsWith("aarch64", ARM::IK_AARCH64)
519296417Sdim      .StartsWith("arm64", ARM::IK_AARCH64)
520296417Sdim      .StartsWith("thumb", ARM::IK_THUMB)
521296417Sdim      .StartsWith("arm", ARM::IK_ARM)
522283625Sdim      .Default(ARM::EK_INVALID);
523283625Sdim}
524283625Sdim
525283625Sdim// Little/Big endian
526296417Sdimunsigned llvm::ARM::parseArchEndian(StringRef Arch) {
527296417Sdim  if (Arch.startswith("armeb") || Arch.startswith("thumbeb") ||
528283625Sdim      Arch.startswith("aarch64_be"))
529283625Sdim    return ARM::EK_BIG;
530283625Sdim
531283625Sdim  if (Arch.startswith("arm") || Arch.startswith("thumb")) {
532283625Sdim    if (Arch.endswith("eb"))
533283625Sdim      return ARM::EK_BIG;
534283625Sdim    else
535283625Sdim      return ARM::EK_LITTLE;
536283625Sdim  }
537283625Sdim
538283625Sdim  if (Arch.startswith("aarch64"))
539283625Sdim    return ARM::EK_LITTLE;
540283625Sdim
541283625Sdim  return ARM::EK_INVALID;
542283625Sdim}
543283625Sdim
544283625Sdim// Profile A/R/M
545296417Sdimunsigned llvm::ARM::parseArchProfile(StringRef Arch) {
546283625Sdim  Arch = getCanonicalArchName(Arch);
547296417Sdim  switch (parseArch(Arch)) {
548283625Sdim  case ARM::AK_ARMV6M:
549283625Sdim  case ARM::AK_ARMV7M:
550283625Sdim  case ARM::AK_ARMV7EM:
551283625Sdim    return ARM::PK_M;
552283625Sdim  case ARM::AK_ARMV7R:
553283625Sdim    return ARM::PK_R;
554283625Sdim  case ARM::AK_ARMV7A:
555296417Sdim  case ARM::AK_ARMV7K:
556283625Sdim  case ARM::AK_ARMV8A:
557283625Sdim  case ARM::AK_ARMV8_1A:
558296417Sdim  case ARM::AK_ARMV8_2A:
559283625Sdim    return ARM::PK_A;
560283625Sdim  }
561283625Sdim  return ARM::PK_INVALID;
562283625Sdim}
563283625Sdim
564283625Sdim// Version number (ex. v7 = 7).
565296417Sdimunsigned llvm::ARM::parseArchVersion(StringRef Arch) {
566283625Sdim  Arch = getCanonicalArchName(Arch);
567296417Sdim  switch (parseArch(Arch)) {
568283625Sdim  case ARM::AK_ARMV2:
569283625Sdim  case ARM::AK_ARMV2A:
570283625Sdim    return 2;
571283625Sdim  case ARM::AK_ARMV3:
572283625Sdim  case ARM::AK_ARMV3M:
573283625Sdim    return 3;
574283625Sdim  case ARM::AK_ARMV4:
575283625Sdim  case ARM::AK_ARMV4T:
576283625Sdim    return 4;
577283625Sdim  case ARM::AK_ARMV5T:
578283625Sdim  case ARM::AK_ARMV5TE:
579283625Sdim  case ARM::AK_IWMMXT:
580283625Sdim  case ARM::AK_IWMMXT2:
581283625Sdim  case ARM::AK_XSCALE:
582283625Sdim  case ARM::AK_ARMV5TEJ:
583283625Sdim    return 5;
584283625Sdim  case ARM::AK_ARMV6:
585283625Sdim  case ARM::AK_ARMV6K:
586283625Sdim  case ARM::AK_ARMV6T2:
587296417Sdim  case ARM::AK_ARMV6KZ:
588283625Sdim  case ARM::AK_ARMV6M:
589283625Sdim    return 6;
590283625Sdim  case ARM::AK_ARMV7A:
591283625Sdim  case ARM::AK_ARMV7R:
592283625Sdim  case ARM::AK_ARMV7M:
593283625Sdim  case ARM::AK_ARMV7S:
594283625Sdim  case ARM::AK_ARMV7EM:
595296417Sdim  case ARM::AK_ARMV7K:
596283625Sdim    return 7;
597283625Sdim  case ARM::AK_ARMV8A:
598283625Sdim  case ARM::AK_ARMV8_1A:
599296417Sdim  case ARM::AK_ARMV8_2A:
600283625Sdim    return 8;
601283625Sdim  }
602283625Sdim  return 0;
603283625Sdim}
604