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