1 //===-- TargetParser - Parser for target features ---------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements a target parser to recognise hardware features such as
11 // FPU/CPU/ARCH names as well as specific support such as HDIV, etc.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "llvm/Support/ARMBuildAttributes.h"
16 #include "llvm/Support/TargetParser.h"
17 #include "llvm/ADT/StringExtras.h"
18 #include "llvm/ADT/StringSwitch.h"
19 #include "llvm/ADT/Twine.h"
20 #include <cctype>
21 
22 using namespace llvm;
23 using namespace ARM;
24 using namespace AArch64;
25 
26 namespace {
27 
28 // List of canonical FPU names (use getFPUSynonym) and which architectural
29 // features they correspond to (use getFPUFeatures).
30 // FIXME: TableGen this.
31 // The entries must appear in the order listed in ARM::FPUKind for correct indexing
32 static const struct {
33   const char *NameCStr;
34   size_t NameLength;
35   ARM::FPUKind ID;
36   ARM::FPUVersion FPUVersion;
37   ARM::NeonSupportLevel NeonSupport;
38   ARM::FPURestriction Restriction;
39 
40   StringRef getName() const { return StringRef(NameCStr, NameLength); }
41 } FPUNames[] = {
42 #define ARM_FPU(NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION) \
43   { NAME, sizeof(NAME) - 1, KIND, VERSION, NEON_SUPPORT, RESTRICTION },
44 #include "llvm/Support/ARMTargetParser.def"
45 };
46 
47 // List of canonical arch names (use getArchSynonym).
48 // This table also provides the build attribute fields for CPU arch
49 // and Arch ID, according to the Addenda to the ARM ABI, chapters
50 // 2.4 and 2.3.5.2 respectively.
51 // FIXME: SubArch values were simplified to fit into the expectations
52 // of the triples and are not conforming with their official names.
53 // Check to see if the expectation should be changed.
54 // FIXME: TableGen this.
55 template <typename T> struct ArchNames {
56   const char *NameCStr;
57   size_t NameLength;
58   const char *CPUAttrCStr;
59   size_t CPUAttrLength;
60   const char *SubArchCStr;
61   size_t SubArchLength;
62   unsigned DefaultFPU;
63   unsigned ArchBaseExtensions;
64   T ID;
65   ARMBuildAttrs::CPUArch ArchAttr; // Arch ID in build attributes.
66 
67   StringRef getName() const { return StringRef(NameCStr, NameLength); }
68 
69   // CPU class in build attributes.
70   StringRef getCPUAttr() const { return StringRef(CPUAttrCStr, CPUAttrLength); }
71 
72   // Sub-Arch name.
73   StringRef getSubArch() const { return StringRef(SubArchCStr, SubArchLength); }
74 };
75 ArchNames<ARM::ArchKind> ARCHNames[] = {
76 #define ARM_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT)       \
77   {NAME, sizeof(NAME) - 1, CPU_ATTR, sizeof(CPU_ATTR) - 1, SUB_ARCH,       \
78    sizeof(SUB_ARCH) - 1, ARCH_FPU, ARCH_BASE_EXT, ARM::ArchKind::ID, ARCH_ATTR},
79 #include "llvm/Support/ARMTargetParser.def"
80 };
81 
82 ArchNames<AArch64::ArchKind> AArch64ARCHNames[] = {
83  #define AARCH64_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT)       \
84    {NAME, sizeof(NAME) - 1, CPU_ATTR, sizeof(CPU_ATTR) - 1, SUB_ARCH,       \
85     sizeof(SUB_ARCH) - 1, ARCH_FPU, ARCH_BASE_EXT, AArch64::ArchKind::ID, ARCH_ATTR},
86  #include "llvm/Support/AArch64TargetParser.def"
87  };
88 
89 
90 // List of Arch Extension names.
91 // FIXME: TableGen this.
92 static const struct {
93   const char *NameCStr;
94   size_t NameLength;
95   unsigned ID;
96   const char *Feature;
97   const char *NegFeature;
98 
99   StringRef getName() const { return StringRef(NameCStr, NameLength); }
100 } ARCHExtNames[] = {
101 #define ARM_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE) \
102   { NAME, sizeof(NAME) - 1, ID, FEATURE, NEGFEATURE },
103 #include "llvm/Support/ARMTargetParser.def"
104 },AArch64ARCHExtNames[] = {
105 #define AARCH64_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE) \
106   { NAME, sizeof(NAME) - 1, ID, FEATURE, NEGFEATURE },
107 #include "llvm/Support/AArch64TargetParser.def"
108 };
109 
110 // List of HWDiv names (use getHWDivSynonym) and which architectural
111 // features they correspond to (use getHWDivFeatures).
112 // FIXME: TableGen this.
113 static const struct {
114   const char *NameCStr;
115   size_t NameLength;
116   unsigned ID;
117 
118   StringRef getName() const { return StringRef(NameCStr, NameLength); }
119 } HWDivNames[] = {
120 #define ARM_HW_DIV_NAME(NAME, ID) { NAME, sizeof(NAME) - 1, ID },
121 #include "llvm/Support/ARMTargetParser.def"
122 };
123 
124 // List of CPU names and their arches.
125 // The same CPU can have multiple arches and can be default on multiple arches.
126 // When finding the Arch for a CPU, first-found prevails. Sort them accordingly.
127 // When this becomes table-generated, we'd probably need two tables.
128 // FIXME: TableGen this.
129 template <typename T> struct CpuNames {
130   const char *NameCStr;
131   size_t NameLength;
132   T ArchID;
133   bool Default; // is $Name the default CPU for $ArchID ?
134   unsigned DefaultExtensions;
135 
136   StringRef getName() const { return StringRef(NameCStr, NameLength); }
137 };
138 CpuNames<ARM::ArchKind> CPUNames[] = {
139 #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
140   { NAME, sizeof(NAME) - 1, ARM::ArchKind::ID, IS_DEFAULT, DEFAULT_EXT },
141 #include "llvm/Support/ARMTargetParser.def"
142 };
143 
144 CpuNames<AArch64::ArchKind> AArch64CPUNames[] = {
145  #define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
146    { NAME, sizeof(NAME) - 1, AArch64::ArchKind::ID, IS_DEFAULT, DEFAULT_EXT },
147  #include "llvm/Support/AArch64TargetParser.def"
148  };
149 
150 } // namespace
151 
152 // ======================================================= //
153 // Information by ID
154 // ======================================================= //
155 
156 StringRef ARM::getFPUName(unsigned FPUKind) {
157   if (FPUKind >= ARM::FK_LAST)
158     return StringRef();
159   return FPUNames[FPUKind].getName();
160 }
161 
162 FPUVersion ARM::getFPUVersion(unsigned FPUKind) {
163   if (FPUKind >= ARM::FK_LAST)
164     return FPUVersion::NONE;
165   return FPUNames[FPUKind].FPUVersion;
166 }
167 
168 ARM::NeonSupportLevel ARM::getFPUNeonSupportLevel(unsigned FPUKind) {
169   if (FPUKind >= ARM::FK_LAST)
170     return ARM::NeonSupportLevel::None;
171   return FPUNames[FPUKind].NeonSupport;
172 }
173 
174 ARM::FPURestriction ARM::getFPURestriction(unsigned FPUKind) {
175   if (FPUKind >= ARM::FK_LAST)
176     return ARM::FPURestriction::None;
177   return FPUNames[FPUKind].Restriction;
178 }
179 
180 unsigned llvm::ARM::getDefaultFPU(StringRef CPU, ArchKind AK) {
181   if (CPU == "generic")
182     return ARCHNames[static_cast<unsigned>(AK)].DefaultFPU;
183 
184   return StringSwitch<unsigned>(CPU)
185 #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
186     .Case(NAME, DEFAULT_FPU)
187 #include "llvm/Support/ARMTargetParser.def"
188     .Default(ARM::FK_INVALID);
189 }
190 
191 unsigned llvm::ARM::getDefaultExtensions(StringRef CPU, ArchKind AK) {
192   if (CPU == "generic")
193     return ARCHNames[static_cast<unsigned>(AK)].ArchBaseExtensions;
194 
195   return StringSwitch<unsigned>(CPU)
196 #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
197     .Case(NAME, ARCHNames[static_cast<unsigned>(ARM::ArchKind::ID)]\
198             .ArchBaseExtensions | DEFAULT_EXT)
199 #include "llvm/Support/ARMTargetParser.def"
200     .Default(ARM::AEK_INVALID);
201 }
202 
203 bool llvm::ARM::getHWDivFeatures(unsigned HWDivKind,
204                                  std::vector<StringRef> &Features) {
205 
206   if (HWDivKind == ARM::AEK_INVALID)
207     return false;
208 
209   if (HWDivKind & ARM::AEK_HWDIVARM)
210     Features.push_back("+hwdiv-arm");
211   else
212     Features.push_back("-hwdiv-arm");
213 
214   if (HWDivKind & ARM::AEK_HWDIVTHUMB)
215     Features.push_back("+hwdiv");
216   else
217     Features.push_back("-hwdiv");
218 
219   return true;
220 }
221 
222 bool llvm::ARM::getExtensionFeatures(unsigned Extensions,
223                                      std::vector<StringRef> &Features) {
224 
225   if (Extensions == ARM::AEK_INVALID)
226     return false;
227 
228   if (Extensions & ARM::AEK_CRC)
229     Features.push_back("+crc");
230   else
231     Features.push_back("-crc");
232 
233   if (Extensions & ARM::AEK_DSP)
234     Features.push_back("+dsp");
235   else
236     Features.push_back("-dsp");
237 
238   if (Extensions & ARM::AEK_RAS)
239     Features.push_back("+ras");
240   else
241     Features.push_back("-ras");
242 
243   if (Extensions & ARM::AEK_DOTPROD)
244     Features.push_back("+dotprod");
245   else
246     Features.push_back("-dotprod");
247 
248   return getHWDivFeatures(Extensions, Features);
249 }
250 
251 bool llvm::ARM::getFPUFeatures(unsigned FPUKind,
252                                std::vector<StringRef> &Features) {
253 
254   if (FPUKind >= ARM::FK_LAST || FPUKind == ARM::FK_INVALID)
255     return false;
256 
257   // fp-only-sp and d16 subtarget features are independent of each other, so we
258   // must enable/disable both.
259   switch (FPUNames[FPUKind].Restriction) {
260   case ARM::FPURestriction::SP_D16:
261     Features.push_back("+fp-only-sp");
262     Features.push_back("+d16");
263     break;
264   case ARM::FPURestriction::D16:
265     Features.push_back("-fp-only-sp");
266     Features.push_back("+d16");
267     break;
268   case ARM::FPURestriction::None:
269     Features.push_back("-fp-only-sp");
270     Features.push_back("-d16");
271     break;
272   }
273 
274   // FPU version subtarget features are inclusive of lower-numbered ones, so
275   // enable the one corresponding to this version and disable all that are
276   // higher. We also have to make sure to disable fp16 when vfp4 is disabled,
277   // as +vfp4 implies +fp16 but -vfp4 does not imply -fp16.
278   switch (FPUNames[FPUKind].FPUVersion) {
279   case ARM::FPUVersion::VFPV5:
280     Features.push_back("+fp-armv8");
281     break;
282   case ARM::FPUVersion::VFPV4:
283     Features.push_back("+vfp4");
284     Features.push_back("-fp-armv8");
285     break;
286   case ARM::FPUVersion::VFPV3_FP16:
287     Features.push_back("+vfp3");
288     Features.push_back("+fp16");
289     Features.push_back("-vfp4");
290     Features.push_back("-fp-armv8");
291     break;
292   case ARM::FPUVersion::VFPV3:
293     Features.push_back("+vfp3");
294     Features.push_back("-fp16");
295     Features.push_back("-vfp4");
296     Features.push_back("-fp-armv8");
297     break;
298   case ARM::FPUVersion::VFPV2:
299     Features.push_back("+vfp2");
300     Features.push_back("-vfp3");
301     Features.push_back("-fp16");
302     Features.push_back("-vfp4");
303     Features.push_back("-fp-armv8");
304     break;
305   case ARM::FPUVersion::NONE:
306     Features.push_back("-vfp2");
307     Features.push_back("-vfp3");
308     Features.push_back("-fp16");
309     Features.push_back("-vfp4");
310     Features.push_back("-fp-armv8");
311     break;
312   }
313 
314   // crypto includes neon, so we handle this similarly to FPU version.
315   switch (FPUNames[FPUKind].NeonSupport) {
316   case ARM::NeonSupportLevel::Crypto:
317     Features.push_back("+neon");
318     Features.push_back("+crypto");
319     break;
320   case ARM::NeonSupportLevel::Neon:
321     Features.push_back("+neon");
322     Features.push_back("-crypto");
323     break;
324   case ARM::NeonSupportLevel::None:
325     Features.push_back("-neon");
326     Features.push_back("-crypto");
327     break;
328   }
329 
330   return true;
331 }
332 
333 StringRef llvm::ARM::getArchName(ArchKind AK) {
334   return ARCHNames[static_cast<unsigned>(AK)].getName();
335 }
336 
337 StringRef llvm::ARM::getCPUAttr(ArchKind AK) {
338   return ARCHNames[static_cast<unsigned>(AK)].getCPUAttr();
339 }
340 
341 StringRef llvm::ARM::getSubArch(ArchKind AK) {
342   return ARCHNames[static_cast<unsigned>(AK)].getSubArch();
343 }
344 
345 unsigned llvm::ARM::getArchAttr(ArchKind AK) {
346   return ARCHNames[static_cast<unsigned>(AK)].ArchAttr;
347 }
348 
349 StringRef llvm::ARM::getArchExtName(unsigned ArchExtKind) {
350   for (const auto AE : ARCHExtNames) {
351     if (ArchExtKind == AE.ID)
352       return AE.getName();
353   }
354   return StringRef();
355 }
356 
357 StringRef llvm::ARM::getArchExtFeature(StringRef ArchExt) {
358   if (ArchExt.startswith("no")) {
359     StringRef ArchExtBase(ArchExt.substr(2));
360     for (const auto AE : ARCHExtNames) {
361       if (AE.NegFeature && ArchExtBase == AE.getName())
362         return StringRef(AE.NegFeature);
363     }
364   }
365   for (const auto AE : ARCHExtNames) {
366     if (AE.Feature && ArchExt == AE.getName())
367       return StringRef(AE.Feature);
368   }
369 
370   return StringRef();
371 }
372 
373 StringRef llvm::ARM::getHWDivName(unsigned HWDivKind) {
374   for (const auto D : HWDivNames) {
375     if (HWDivKind == D.ID)
376       return D.getName();
377   }
378   return StringRef();
379 }
380 
381 StringRef llvm::ARM::getDefaultCPU(StringRef Arch) {
382   ArchKind AK = parseArch(Arch);
383   if (AK == ARM::ArchKind::INVALID)
384     return StringRef();
385 
386   // Look for multiple AKs to find the default for pair AK+Name.
387   for (const auto CPU : CPUNames) {
388     if (CPU.ArchID == AK && CPU.Default)
389       return CPU.getName();
390   }
391 
392   // If we can't find a default then target the architecture instead
393   return "generic";
394 }
395 
396 StringRef llvm::AArch64::getFPUName(unsigned FPUKind) {
397   return ARM::getFPUName(FPUKind);
398 }
399 
400 ARM::FPUVersion AArch64::getFPUVersion(unsigned FPUKind) {
401   return ARM::getFPUVersion(FPUKind);
402 }
403 
404 ARM::NeonSupportLevel AArch64::getFPUNeonSupportLevel(unsigned FPUKind) {
405   return ARM::getFPUNeonSupportLevel( FPUKind);
406 }
407 
408 ARM::FPURestriction AArch64::getFPURestriction(unsigned FPUKind) {
409   return ARM::getFPURestriction(FPUKind);
410 }
411 
412 unsigned llvm::AArch64::getDefaultFPU(StringRef CPU, ArchKind AK) {
413   if (CPU == "generic")
414     return AArch64ARCHNames[static_cast<unsigned>(AK)].DefaultFPU;
415 
416   return StringSwitch<unsigned>(CPU)
417 #define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
418     .Case(NAME, DEFAULT_FPU)
419 #include "llvm/Support/AArch64TargetParser.def"
420     .Default(ARM::FK_INVALID);
421 }
422 
423 unsigned llvm::AArch64::getDefaultExtensions(StringRef CPU, ArchKind AK) {
424   if (CPU == "generic")
425     return AArch64ARCHNames[static_cast<unsigned>(AK)].ArchBaseExtensions;
426 
427   return StringSwitch<unsigned>(CPU)
428 #define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT)       \
429   .Case(NAME,                                                                  \
430         AArch64ARCHNames[static_cast<unsigned>(AArch64::ArchKind::ID)] \
431             .ArchBaseExtensions | \
432             DEFAULT_EXT)
433 #include "llvm/Support/AArch64TargetParser.def"
434     .Default(AArch64::AEK_INVALID);
435 }
436 
437 bool llvm::AArch64::getExtensionFeatures(unsigned Extensions,
438                                      std::vector<StringRef> &Features) {
439 
440   if (Extensions == AArch64::AEK_INVALID)
441     return false;
442 
443   if (Extensions & AArch64::AEK_FP)
444     Features.push_back("+fp-armv8");
445   if (Extensions & AArch64::AEK_SIMD)
446     Features.push_back("+neon");
447   if (Extensions & AArch64::AEK_CRC)
448     Features.push_back("+crc");
449   if (Extensions & AArch64::AEK_CRYPTO)
450     Features.push_back("+crypto");
451   if (Extensions & AArch64::AEK_DOTPROD)
452     Features.push_back("+dotprod");
453   if (Extensions & AArch64::AEK_FP16)
454     Features.push_back("+fullfp16");
455   if (Extensions & AArch64::AEK_PROFILE)
456     Features.push_back("+spe");
457   if (Extensions & AArch64::AEK_RAS)
458     Features.push_back("+ras");
459   if (Extensions & AArch64::AEK_LSE)
460     Features.push_back("+lse");
461   if (Extensions & AArch64::AEK_RDM)
462     Features.push_back("+rdm");
463   if (Extensions & AArch64::AEK_SVE)
464     Features.push_back("+sve");
465   if (Extensions & AArch64::AEK_RCPC)
466     Features.push_back("+rcpc");
467 
468   return true;
469 }
470 
471 bool llvm::AArch64::getFPUFeatures(unsigned FPUKind,
472                                std::vector<StringRef> &Features) {
473   return ARM::getFPUFeatures(FPUKind, Features);
474 }
475 
476 bool llvm::AArch64::getArchFeatures(AArch64::ArchKind AK,
477                                     std::vector<StringRef> &Features) {
478   if (AK == AArch64::ArchKind::ARMV8_1A)
479     Features.push_back("+v8.1a");
480   if (AK == AArch64::ArchKind::ARMV8_2A)
481     Features.push_back("+v8.2a");
482   if (AK == AArch64::ArchKind::ARMV8_3A)
483     Features.push_back("+v8.3a");
484 
485   return AK != AArch64::ArchKind::INVALID;
486 }
487 
488 StringRef llvm::AArch64::getArchName(ArchKind AK) {
489   return AArch64ARCHNames[static_cast<unsigned>(AK)].getName();
490 }
491 
492 StringRef llvm::AArch64::getCPUAttr(ArchKind AK) {
493   return AArch64ARCHNames[static_cast<unsigned>(AK)].getCPUAttr();
494 }
495 
496 StringRef llvm::AArch64::getSubArch(ArchKind AK) {
497   return AArch64ARCHNames[static_cast<unsigned>(AK)].getSubArch();
498 }
499 
500 unsigned llvm::AArch64::getArchAttr(ArchKind AK) {
501   return AArch64ARCHNames[static_cast<unsigned>(AK)].ArchAttr;
502 }
503 
504 StringRef llvm::AArch64::getArchExtName(unsigned ArchExtKind) {
505   for (const auto &AE : AArch64ARCHExtNames)
506     if (ArchExtKind == AE.ID)
507       return AE.getName();
508   return StringRef();
509 }
510 
511 StringRef llvm::AArch64::getArchExtFeature(StringRef ArchExt) {
512   if (ArchExt.startswith("no")) {
513     StringRef ArchExtBase(ArchExt.substr(2));
514     for (const auto &AE : AArch64ARCHExtNames) {
515       if (AE.NegFeature && ArchExtBase == AE.getName())
516         return StringRef(AE.NegFeature);
517     }
518   }
519 
520   for (const auto &AE : AArch64ARCHExtNames)
521     if (AE.Feature && ArchExt == AE.getName())
522       return StringRef(AE.Feature);
523   return StringRef();
524 }
525 
526 StringRef llvm::AArch64::getDefaultCPU(StringRef Arch) {
527   AArch64::ArchKind AK = parseArch(Arch);
528   if (AK == ArchKind::INVALID)
529     return StringRef();
530 
531   // Look for multiple AKs to find the default for pair AK+Name.
532   for (const auto &CPU : AArch64CPUNames)
533     if (CPU.ArchID == AK && CPU.Default)
534       return CPU.getName();
535 
536   // If we can't find a default then target the architecture instead
537   return "generic";
538 }
539 
540 unsigned llvm::AArch64::checkArchVersion(StringRef Arch) {
541   if (Arch[0] == 'v' && std::isdigit(Arch[1]))
542     return (Arch[1] - 48);
543   return 0;
544 }
545 
546 // ======================================================= //
547 // Parsers
548 // ======================================================= //
549 
550 static StringRef getHWDivSynonym(StringRef HWDiv) {
551   return StringSwitch<StringRef>(HWDiv)
552       .Case("thumb,arm", "arm,thumb")
553       .Default(HWDiv);
554 }
555 
556 static StringRef getFPUSynonym(StringRef FPU) {
557   return StringSwitch<StringRef>(FPU)
558       .Cases("fpa", "fpe2", "fpe3", "maverick", "invalid") // Unsupported
559       .Case("vfp2", "vfpv2")
560       .Case("vfp3", "vfpv3")
561       .Case("vfp4", "vfpv4")
562       .Case("vfp3-d16", "vfpv3-d16")
563       .Case("vfp4-d16", "vfpv4-d16")
564       .Cases("fp4-sp-d16", "vfpv4-sp-d16", "fpv4-sp-d16")
565       .Cases("fp4-dp-d16", "fpv4-dp-d16", "vfpv4-d16")
566       .Case("fp5-sp-d16", "fpv5-sp-d16")
567       .Cases("fp5-dp-d16", "fpv5-dp-d16", "fpv5-d16")
568       // FIXME: Clang uses it, but it's bogus, since neon defaults to vfpv3.
569       .Case("neon-vfpv3", "neon")
570       .Default(FPU);
571 }
572 
573 static StringRef getArchSynonym(StringRef Arch) {
574   return StringSwitch<StringRef>(Arch)
575       .Case("v5", "v5t")
576       .Case("v5e", "v5te")
577       .Case("v6j", "v6")
578       .Case("v6hl", "v6k")
579       .Cases("v6m", "v6sm", "v6s-m", "v6-m")
580       .Cases("v6z", "v6zk", "v6kz")
581       .Cases("v7", "v7a", "v7hl", "v7l", "v7-a")
582       .Case("v7r", "v7-r")
583       .Case("v7m", "v7-m")
584       .Case("v7em", "v7e-m")
585       .Cases("v8", "v8a", "aarch64", "arm64", "v8-a")
586       .Case("v8.1a", "v8.1-a")
587       .Case("v8.2a", "v8.2-a")
588       .Case("v8.3a", "v8.3-a")
589       .Case("v8r", "v8-r")
590       .Case("v8m.base", "v8-m.base")
591       .Case("v8m.main", "v8-m.main")
592       .Default(Arch);
593 }
594 
595 // MArch is expected to be of the form (arm|thumb)?(eb)?(v.+)?(eb)?, but
596 // (iwmmxt|xscale)(eb)? is also permitted. If the former, return
597 // "v.+", if the latter, return unmodified string, minus 'eb'.
598 // If invalid, return empty string.
599 StringRef llvm::ARM::getCanonicalArchName(StringRef Arch) {
600   size_t offset = StringRef::npos;
601   StringRef A = Arch;
602   StringRef Error = "";
603 
604   // Begins with "arm" / "thumb", move past it.
605   if (A.startswith("arm64"))
606     offset = 5;
607   else if (A.startswith("arm"))
608     offset = 3;
609   else if (A.startswith("thumb"))
610     offset = 5;
611   else if (A.startswith("aarch64")) {
612     offset = 7;
613     // AArch64 uses "_be", not "eb" suffix.
614     if (A.find("eb") != StringRef::npos)
615       return Error;
616     if (A.substr(offset, 3) == "_be")
617       offset += 3;
618   }
619 
620   // Ex. "armebv7", move past the "eb".
621   if (offset != StringRef::npos && A.substr(offset, 2) == "eb")
622     offset += 2;
623   // Or, if it ends with eb ("armv7eb"), chop it off.
624   else if (A.endswith("eb"))
625     A = A.substr(0, A.size() - 2);
626   // Trim the head
627   if (offset != StringRef::npos)
628     A = A.substr(offset);
629 
630   // Empty string means offset reached the end, which means it's valid.
631   if (A.empty())
632     return Arch;
633 
634   // Only match non-marketing names
635   if (offset != StringRef::npos) {
636     // Must start with 'vN'.
637     if (A[0] != 'v' || !std::isdigit(A[1]))
638       return Error;
639     // Can't have an extra 'eb'.
640     if (A.find("eb") != StringRef::npos)
641       return Error;
642   }
643 
644   // Arch will either be a 'v' name (v7a) or a marketing name (xscale).
645   return A;
646 }
647 
648 unsigned llvm::ARM::parseHWDiv(StringRef HWDiv) {
649   StringRef Syn = getHWDivSynonym(HWDiv);
650   for (const auto D : HWDivNames) {
651     if (Syn == D.getName())
652       return D.ID;
653   }
654   return ARM::AEK_INVALID;
655 }
656 
657 unsigned llvm::ARM::parseFPU(StringRef FPU) {
658   StringRef Syn = getFPUSynonym(FPU);
659   for (const auto F : FPUNames) {
660     if (Syn == F.getName())
661       return F.ID;
662   }
663   return ARM::FK_INVALID;
664 }
665 
666 // Allows partial match, ex. "v7a" matches "armv7a".
667 ARM::ArchKind ARM::parseArch(StringRef Arch) {
668   Arch = getCanonicalArchName(Arch);
669   StringRef Syn = getArchSynonym(Arch);
670   for (const auto A : ARCHNames) {
671     if (A.getName().endswith(Syn))
672       return A.ID;
673   }
674   return ARM::ArchKind::INVALID;
675 }
676 
677 unsigned llvm::ARM::parseArchExt(StringRef ArchExt) {
678   for (const auto A : ARCHExtNames) {
679     if (ArchExt == A.getName())
680       return A.ID;
681   }
682   return ARM::AEK_INVALID;
683 }
684 
685 ARM::ArchKind llvm::ARM::parseCPUArch(StringRef CPU) {
686   for (const auto C : CPUNames) {
687     if (CPU == C.getName())
688       return C.ArchID;
689   }
690   return ARM::ArchKind::INVALID;
691 }
692 
693 // ARM, Thumb, AArch64
694 ARM::ISAKind ARM::parseArchISA(StringRef Arch) {
695   return StringSwitch<ARM::ISAKind>(Arch)
696       .StartsWith("aarch64", ARM::ISAKind::AARCH64)
697       .StartsWith("arm64", ARM::ISAKind::AARCH64)
698       .StartsWith("thumb", ARM::ISAKind::THUMB)
699       .StartsWith("arm", ARM::ISAKind::ARM)
700       .Default(ARM::ISAKind::INVALID);
701 }
702 
703 // Little/Big endian
704 ARM::EndianKind ARM::parseArchEndian(StringRef Arch) {
705   if (Arch.startswith("armeb") || Arch.startswith("thumbeb") ||
706       Arch.startswith("aarch64_be"))
707     return ARM::EndianKind::BIG;
708 
709   if (Arch.startswith("arm") || Arch.startswith("thumb")) {
710     if (Arch.endswith("eb"))
711       return ARM::EndianKind::BIG;
712     else
713       return ARM::EndianKind::LITTLE;
714   }
715 
716   if (Arch.startswith("aarch64"))
717     return ARM::EndianKind::LITTLE;
718 
719   return ARM::EndianKind::INVALID;
720 }
721 
722 // Profile A/R/M
723 ARM::ProfileKind ARM::parseArchProfile(StringRef Arch) {
724   Arch = getCanonicalArchName(Arch);
725   switch (parseArch(Arch)) {
726   case ARM::ArchKind::ARMV6M:
727   case ARM::ArchKind::ARMV7M:
728   case ARM::ArchKind::ARMV7EM:
729   case ARM::ArchKind::ARMV8MMainline:
730   case ARM::ArchKind::ARMV8MBaseline:
731     return ARM::ProfileKind::M;
732   case ARM::ArchKind::ARMV7R:
733   case ARM::ArchKind::ARMV8R:
734     return ARM::ProfileKind::R;
735   case ARM::ArchKind::ARMV7A:
736   case ARM::ArchKind::ARMV7VE:
737   case ARM::ArchKind::ARMV7K:
738   case ARM::ArchKind::ARMV8A:
739   case ARM::ArchKind::ARMV8_1A:
740   case ARM::ArchKind::ARMV8_2A:
741   case ARM::ArchKind::ARMV8_3A:
742     return ARM::ProfileKind::A;
743     LLVM_FALLTHROUGH;
744   case ARM::ArchKind::ARMV2:
745   case ARM::ArchKind::ARMV2A:
746   case ARM::ArchKind::ARMV3:
747   case ARM::ArchKind::ARMV3M:
748   case ARM::ArchKind::ARMV4:
749   case ARM::ArchKind::ARMV4T:
750   case ARM::ArchKind::ARMV5T:
751   case ARM::ArchKind::ARMV5TE:
752   case ARM::ArchKind::ARMV5TEJ:
753   case ARM::ArchKind::ARMV6:
754   case ARM::ArchKind::ARMV6K:
755   case ARM::ArchKind::ARMV6T2:
756   case ARM::ArchKind::ARMV6KZ:
757   case ARM::ArchKind::ARMV7S:
758   case ARM::ArchKind::IWMMXT:
759   case ARM::ArchKind::IWMMXT2:
760   case ARM::ArchKind::XSCALE:
761   case ARM::ArchKind::INVALID:
762     return ARM::ProfileKind::INVALID;
763   }
764   llvm_unreachable("Unhandled architecture");
765 }
766 
767 // Version number (ex. v7 = 7).
768 unsigned llvm::ARM::parseArchVersion(StringRef Arch) {
769   Arch = getCanonicalArchName(Arch);
770   switch (parseArch(Arch)) {
771   case ARM::ArchKind::ARMV2:
772   case ARM::ArchKind::ARMV2A:
773     return 2;
774   case ARM::ArchKind::ARMV3:
775   case ARM::ArchKind::ARMV3M:
776     return 3;
777   case ARM::ArchKind::ARMV4:
778   case ARM::ArchKind::ARMV4T:
779     return 4;
780   case ARM::ArchKind::ARMV5T:
781   case ARM::ArchKind::ARMV5TE:
782   case ARM::ArchKind::IWMMXT:
783   case ARM::ArchKind::IWMMXT2:
784   case ARM::ArchKind::XSCALE:
785   case ARM::ArchKind::ARMV5TEJ:
786     return 5;
787   case ARM::ArchKind::ARMV6:
788   case ARM::ArchKind::ARMV6K:
789   case ARM::ArchKind::ARMV6T2:
790   case ARM::ArchKind::ARMV6KZ:
791   case ARM::ArchKind::ARMV6M:
792     return 6;
793   case ARM::ArchKind::ARMV7A:
794   case ARM::ArchKind::ARMV7VE:
795   case ARM::ArchKind::ARMV7R:
796   case ARM::ArchKind::ARMV7M:
797   case ARM::ArchKind::ARMV7S:
798   case ARM::ArchKind::ARMV7EM:
799   case ARM::ArchKind::ARMV7K:
800     return 7;
801   case ARM::ArchKind::ARMV8A:
802   case ARM::ArchKind::ARMV8_1A:
803   case ARM::ArchKind::ARMV8_2A:
804   case ARM::ArchKind::ARMV8_3A:
805   case ARM::ArchKind::ARMV8R:
806   case ARM::ArchKind::ARMV8MBaseline:
807   case ARM::ArchKind::ARMV8MMainline:
808     return 8;
809   case ARM::ArchKind::INVALID:
810     return 0;
811   }
812   llvm_unreachable("Unhandled architecture");
813 }
814 
815 StringRef llvm::ARM::computeDefaultTargetABI(const Triple &TT, StringRef CPU) {
816   StringRef ArchName =
817       CPU.empty() ? TT.getArchName() : ARM::getArchName(ARM::parseCPUArch(CPU));
818 
819   if (TT.isOSBinFormatMachO()) {
820     if (TT.getEnvironment() == Triple::EABI ||
821         TT.getOS() == Triple::UnknownOS ||
822         llvm::ARM::parseArchProfile(ArchName) == ARM::ProfileKind::M)
823       return "aapcs";
824     if (TT.isWatchABI())
825       return "aapcs16";
826     return "apcs-gnu";
827   } else if (TT.isOSWindows())
828     // FIXME: this is invalid for WindowsCE.
829     return "aapcs";
830 
831   // Select the default based on the platform.
832   switch (TT.getEnvironment()) {
833   case Triple::Android:
834   case Triple::GNUEABI:
835   case Triple::GNUEABIHF:
836   case Triple::MuslEABI:
837   case Triple::MuslEABIHF:
838     return "aapcs-linux";
839   case Triple::EABIHF:
840   case Triple::EABI:
841     return "aapcs";
842   default:
843     if (TT.isOSNetBSD())
844       return "apcs-gnu";
845     if (TT.isOSOpenBSD())
846       return "aapcs-linux";
847     return "aapcs";
848   }
849 }
850 
851 StringRef llvm::AArch64::getCanonicalArchName(StringRef Arch) {
852   return ARM::getCanonicalArchName(Arch);
853 }
854 
855 unsigned llvm::AArch64::parseFPU(StringRef FPU) {
856   return ARM::parseFPU(FPU);
857 }
858 
859 // Allows partial match, ex. "v8a" matches "armv8a".
860 AArch64::ArchKind AArch64::parseArch(StringRef Arch) {
861   Arch = getCanonicalArchName(Arch);
862   if (checkArchVersion(Arch) < 8)
863     return ArchKind::INVALID;
864 
865   StringRef Syn = getArchSynonym(Arch);
866   for (const auto A : AArch64ARCHNames) {
867     if (A.getName().endswith(Syn))
868       return A.ID;
869   }
870   return ArchKind::INVALID;
871 }
872 
873 unsigned llvm::AArch64::parseArchExt(StringRef ArchExt) {
874   for (const auto A : AArch64ARCHExtNames) {
875     if (ArchExt == A.getName())
876       return A.ID;
877   }
878   return AArch64::AEK_INVALID;
879 }
880 
881 AArch64::ArchKind llvm::AArch64::parseCPUArch(StringRef CPU) {
882   for (const auto C : AArch64CPUNames) {
883     if (CPU == C.getName())
884       return C.ArchID;
885   }
886   return ArchKind::INVALID;
887 }
888 
889 // ARM, Thumb, AArch64
890 ARM::ISAKind AArch64::parseArchISA(StringRef Arch) {
891   return ARM::parseArchISA(Arch);
892 }
893 
894 // Little/Big endian
895 ARM::EndianKind AArch64::parseArchEndian(StringRef Arch) {
896   return ARM::parseArchEndian(Arch);
897 }
898 
899 // Profile A/R/M
900 ARM::ProfileKind AArch64::parseArchProfile(StringRef Arch) {
901   return ARM::parseArchProfile(Arch);
902 }
903 
904 // Version number (ex. v8 = 8).
905 unsigned llvm::AArch64::parseArchVersion(StringRef Arch) {
906   return ARM::parseArchVersion(Arch);
907 }
908