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
getName__anond8c810520111::__anond8c81052020840 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 static const struct {
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 ARM::ArchKind ID;
65 ARMBuildAttrs::CPUArch ArchAttr; // Arch ID in build attributes.
66
getName__anond8c810520111::__anond8c81052030867 StringRef getName() const { return StringRef(NameCStr, NameLength); }
68
69 // CPU class in build attributes.
getCPUAttr__anond8c810520111::__anond8c81052030870 StringRef getCPUAttr() const { return StringRef(CPUAttrCStr, CPUAttrLength); }
71
72 // Sub-Arch name.
getSubArch__anond8c810520111::__anond8c81052030873 StringRef getSubArch() const { return StringRef(SubArchCStr, SubArchLength); }
74 } 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, ID, ARCH_ATTR},
78 #include "llvm/Support/ARMTargetParser.def"
79 },AArch64ARCHNames[] = {
80 #define AARCH64_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT) \
81 {NAME, sizeof(NAME) - 1, CPU_ATTR, sizeof(CPU_ATTR) - 1, SUB_ARCH, \
82 sizeof(SUB_ARCH) - 1, ARCH_FPU, ARCH_BASE_EXT, ID, ARCH_ATTR},
83 #include "llvm/Support/AArch64TargetParser.def"
84 };
85
86 // List of Arch Extension names.
87 // FIXME: TableGen this.
88 static const struct {
89 const char *NameCStr;
90 size_t NameLength;
91 unsigned ID;
92 const char *Feature;
93 const char *NegFeature;
94
getName__anond8c810520111::__anond8c81052040895 StringRef getName() const { return StringRef(NameCStr, NameLength); }
96 } ARCHExtNames[] = {
97 #define ARM_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE) \
98 { NAME, sizeof(NAME) - 1, ID, FEATURE, NEGFEATURE },
99 #include "llvm/Support/ARMTargetParser.def"
100 },AArch64ARCHExtNames[] = {
101 #define AARCH64_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE) \
102 { NAME, sizeof(NAME) - 1, ID, FEATURE, NEGFEATURE },
103 #include "llvm/Support/AArch64TargetParser.def"
104 };
105
106 // List of HWDiv names (use getHWDivSynonym) and which architectural
107 // features they correspond to (use getHWDivFeatures).
108 // FIXME: TableGen this.
109 static const struct {
110 const char *NameCStr;
111 size_t NameLength;
112 unsigned ID;
113
getName__anond8c810520111::__anond8c810520508114 StringRef getName() const { return StringRef(NameCStr, NameLength); }
115 } HWDivNames[] = {
116 #define ARM_HW_DIV_NAME(NAME, ID) { NAME, sizeof(NAME) - 1, ID },
117 #include "llvm/Support/ARMTargetParser.def"
118 };
119
120 // List of CPU names and their arches.
121 // The same CPU can have multiple arches and can be default on multiple arches.
122 // When finding the Arch for a CPU, first-found prevails. Sort them accordingly.
123 // When this becomes table-generated, we'd probably need two tables.
124 // FIXME: TableGen this.
125 static const struct {
126 const char *NameCStr;
127 size_t NameLength;
128 ARM::ArchKind ArchID;
129 bool Default; // is $Name the default CPU for $ArchID ?
130 unsigned DefaultExtensions;
131
getName__anond8c810520111::__anond8c810520608132 StringRef getName() const { return StringRef(NameCStr, NameLength); }
133 } CPUNames[] = {
134 #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
135 { NAME, sizeof(NAME) - 1, ID, IS_DEFAULT, DEFAULT_EXT },
136 #include "llvm/Support/ARMTargetParser.def"
137 },AArch64CPUNames[] = {
138 #define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
139 { NAME, sizeof(NAME) - 1, ID, IS_DEFAULT, DEFAULT_EXT },
140 #include "llvm/Support/AArch64TargetParser.def"
141 };
142
143 } // namespace
144
145 // ======================================================= //
146 // Information by ID
147 // ======================================================= //
148
getFPUName(unsigned FPUKind)149 StringRef llvm::ARM::getFPUName(unsigned FPUKind) {
150 if (FPUKind >= ARM::FK_LAST)
151 return StringRef();
152 return FPUNames[FPUKind].getName();
153 }
154
getFPUVersion(unsigned FPUKind)155 unsigned llvm::ARM::getFPUVersion(unsigned FPUKind) {
156 if (FPUKind >= ARM::FK_LAST)
157 return 0;
158 return FPUNames[FPUKind].FPUVersion;
159 }
160
getFPUNeonSupportLevel(unsigned FPUKind)161 unsigned llvm::ARM::getFPUNeonSupportLevel(unsigned FPUKind) {
162 if (FPUKind >= ARM::FK_LAST)
163 return 0;
164 return FPUNames[FPUKind].NeonSupport;
165 }
166
getFPURestriction(unsigned FPUKind)167 unsigned llvm::ARM::getFPURestriction(unsigned FPUKind) {
168 if (FPUKind >= ARM::FK_LAST)
169 return 0;
170 return FPUNames[FPUKind].Restriction;
171 }
172
getDefaultFPU(StringRef CPU,unsigned ArchKind)173 unsigned llvm::ARM::getDefaultFPU(StringRef CPU, unsigned ArchKind) {
174 if (CPU == "generic")
175 return ARCHNames[ArchKind].DefaultFPU;
176
177 return StringSwitch<unsigned>(CPU)
178 #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
179 .Case(NAME, DEFAULT_FPU)
180 #include "llvm/Support/ARMTargetParser.def"
181 .Default(ARM::FK_INVALID);
182 }
183
getDefaultExtensions(StringRef CPU,unsigned ArchKind)184 unsigned llvm::ARM::getDefaultExtensions(StringRef CPU, unsigned ArchKind) {
185 if (CPU == "generic")
186 return ARCHNames[ArchKind].ArchBaseExtensions;
187
188 return StringSwitch<unsigned>(CPU)
189 #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
190 .Case(NAME, ARCHNames[ID].ArchBaseExtensions | DEFAULT_EXT)
191 #include "llvm/Support/ARMTargetParser.def"
192 .Default(ARM::AEK_INVALID);
193 }
194
getHWDivFeatures(unsigned HWDivKind,std::vector<const char * > & Features)195 bool llvm::ARM::getHWDivFeatures(unsigned HWDivKind,
196 std::vector<const char *> &Features) {
197
198 if (HWDivKind == ARM::AEK_INVALID)
199 return false;
200
201 if (HWDivKind & ARM::AEK_HWDIVARM)
202 Features.push_back("+hwdiv-arm");
203 else
204 Features.push_back("-hwdiv-arm");
205
206 if (HWDivKind & ARM::AEK_HWDIV)
207 Features.push_back("+hwdiv");
208 else
209 Features.push_back("-hwdiv");
210
211 return true;
212 }
213
getExtensionFeatures(unsigned Extensions,std::vector<const char * > & Features)214 bool llvm::ARM::getExtensionFeatures(unsigned Extensions,
215 std::vector<const char *> &Features) {
216
217 if (Extensions == ARM::AEK_INVALID)
218 return false;
219
220 if (Extensions & ARM::AEK_CRC)
221 Features.push_back("+crc");
222 else
223 Features.push_back("-crc");
224
225 if (Extensions & ARM::AEK_DSP)
226 Features.push_back("+dsp");
227 else
228 Features.push_back("-dsp");
229
230 return getHWDivFeatures(Extensions, Features);
231 }
232
getFPUFeatures(unsigned FPUKind,std::vector<const char * > & Features)233 bool llvm::ARM::getFPUFeatures(unsigned FPUKind,
234 std::vector<const char *> &Features) {
235
236 if (FPUKind >= ARM::FK_LAST || FPUKind == ARM::FK_INVALID)
237 return false;
238
239 // fp-only-sp and d16 subtarget features are independent of each other, so we
240 // must enable/disable both.
241 switch (FPUNames[FPUKind].Restriction) {
242 case ARM::FR_SP_D16:
243 Features.push_back("+fp-only-sp");
244 Features.push_back("+d16");
245 break;
246 case ARM::FR_D16:
247 Features.push_back("-fp-only-sp");
248 Features.push_back("+d16");
249 break;
250 case ARM::FR_None:
251 Features.push_back("-fp-only-sp");
252 Features.push_back("-d16");
253 break;
254 }
255
256 // FPU version subtarget features are inclusive of lower-numbered ones, so
257 // enable the one corresponding to this version and disable all that are
258 // higher. We also have to make sure to disable fp16 when vfp4 is disabled,
259 // as +vfp4 implies +fp16 but -vfp4 does not imply -fp16.
260 switch (FPUNames[FPUKind].FPUVersion) {
261 case ARM::FV_VFPV5:
262 Features.push_back("+fp-armv8");
263 break;
264 case ARM::FV_VFPV4:
265 Features.push_back("+vfp4");
266 Features.push_back("-fp-armv8");
267 break;
268 case ARM::FV_VFPV3_FP16:
269 Features.push_back("+vfp3");
270 Features.push_back("+fp16");
271 Features.push_back("-vfp4");
272 Features.push_back("-fp-armv8");
273 break;
274 case ARM::FV_VFPV3:
275 Features.push_back("+vfp3");
276 Features.push_back("-fp16");
277 Features.push_back("-vfp4");
278 Features.push_back("-fp-armv8");
279 break;
280 case ARM::FV_VFPV2:
281 Features.push_back("+vfp2");
282 Features.push_back("-vfp3");
283 Features.push_back("-fp16");
284 Features.push_back("-vfp4");
285 Features.push_back("-fp-armv8");
286 break;
287 case ARM::FV_NONE:
288 Features.push_back("-vfp2");
289 Features.push_back("-vfp3");
290 Features.push_back("-fp16");
291 Features.push_back("-vfp4");
292 Features.push_back("-fp-armv8");
293 break;
294 }
295
296 // crypto includes neon, so we handle this similarly to FPU version.
297 switch (FPUNames[FPUKind].NeonSupport) {
298 case ARM::NS_Crypto:
299 Features.push_back("+neon");
300 Features.push_back("+crypto");
301 break;
302 case ARM::NS_Neon:
303 Features.push_back("+neon");
304 Features.push_back("-crypto");
305 break;
306 case ARM::NS_None:
307 Features.push_back("-neon");
308 Features.push_back("-crypto");
309 break;
310 }
311
312 return true;
313 }
314
getArchName(unsigned ArchKind)315 StringRef llvm::ARM::getArchName(unsigned ArchKind) {
316 if (ArchKind >= ARM::AK_LAST)
317 return StringRef();
318 return ARCHNames[ArchKind].getName();
319 }
320
getCPUAttr(unsigned ArchKind)321 StringRef llvm::ARM::getCPUAttr(unsigned ArchKind) {
322 if (ArchKind == ARM::AK_INVALID || ArchKind >= ARM::AK_LAST)
323 return StringRef();
324 return ARCHNames[ArchKind].getCPUAttr();
325 }
326
getSubArch(unsigned ArchKind)327 StringRef llvm::ARM::getSubArch(unsigned ArchKind) {
328 if (ArchKind == ARM::AK_INVALID || ArchKind >= ARM::AK_LAST)
329 return StringRef();
330 return ARCHNames[ArchKind].getSubArch();
331 }
332
getArchAttr(unsigned ArchKind)333 unsigned llvm::ARM::getArchAttr(unsigned ArchKind) {
334 if (ArchKind >= ARM::AK_LAST)
335 return ARMBuildAttrs::CPUArch::Pre_v4;
336 return ARCHNames[ArchKind].ArchAttr;
337 }
338
getArchExtName(unsigned ArchExtKind)339 StringRef llvm::ARM::getArchExtName(unsigned ArchExtKind) {
340 for (const auto AE : ARCHExtNames) {
341 if (ArchExtKind == AE.ID)
342 return AE.getName();
343 }
344 return StringRef();
345 }
346
getArchExtFeature(StringRef ArchExt)347 const char *llvm::ARM::getArchExtFeature(StringRef ArchExt) {
348 if (ArchExt.startswith("no")) {
349 StringRef ArchExtBase(ArchExt.substr(2));
350 for (const auto AE : ARCHExtNames) {
351 if (AE.NegFeature && ArchExtBase == AE.getName())
352 return AE.NegFeature;
353 }
354 }
355 for (const auto AE : ARCHExtNames) {
356 if (AE.Feature && ArchExt == AE.getName())
357 return AE.Feature;
358 }
359
360 return nullptr;
361 }
362
getHWDivName(unsigned HWDivKind)363 StringRef llvm::ARM::getHWDivName(unsigned HWDivKind) {
364 for (const auto D : HWDivNames) {
365 if (HWDivKind == D.ID)
366 return D.getName();
367 }
368 return StringRef();
369 }
370
getDefaultCPU(StringRef Arch)371 StringRef llvm::ARM::getDefaultCPU(StringRef Arch) {
372 unsigned AK = parseArch(Arch);
373 if (AK == ARM::AK_INVALID)
374 return StringRef();
375
376 // Look for multiple AKs to find the default for pair AK+Name.
377 for (const auto CPU : CPUNames) {
378 if (CPU.ArchID == AK && CPU.Default)
379 return CPU.getName();
380 }
381
382 // If we can't find a default then target the architecture instead
383 return "generic";
384 }
385
getFPUName(unsigned FPUKind)386 StringRef llvm::AArch64::getFPUName(unsigned FPUKind) {
387 return ARM::getFPUName(FPUKind);
388 }
389
getFPUVersion(unsigned FPUKind)390 unsigned llvm::AArch64::getFPUVersion(unsigned FPUKind) {
391 return ARM::getFPUVersion(FPUKind);
392 }
393
getFPUNeonSupportLevel(unsigned FPUKind)394 unsigned llvm::AArch64::getFPUNeonSupportLevel(unsigned FPUKind) {
395 return ARM::getFPUNeonSupportLevel( FPUKind);
396 }
397
getFPURestriction(unsigned FPUKind)398 unsigned llvm::AArch64::getFPURestriction(unsigned FPUKind) {
399 return ARM::getFPURestriction(FPUKind);
400 }
401
getDefaultFPU(StringRef CPU,unsigned ArchKind)402 unsigned llvm::AArch64::getDefaultFPU(StringRef CPU, unsigned ArchKind) {
403 if (CPU == "generic")
404 return AArch64ARCHNames[ArchKind].DefaultFPU;
405
406 return StringSwitch<unsigned>(CPU)
407 #define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
408 .Case(NAME, DEFAULT_FPU)
409 #include "llvm/Support/AArch64TargetParser.def"
410 .Default(ARM::FK_INVALID);
411 }
412
getDefaultExtensions(StringRef CPU,unsigned ArchKind)413 unsigned llvm::AArch64::getDefaultExtensions(StringRef CPU, unsigned ArchKind) {
414 if (CPU == "generic")
415 return AArch64ARCHNames[ArchKind].ArchBaseExtensions;
416
417 return StringSwitch<unsigned>(CPU)
418 #define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
419 .Case(NAME, AArch64ARCHNames[ID].ArchBaseExtensions | DEFAULT_EXT)
420 #include "llvm/Support/AArch64TargetParser.def"
421 .Default(AArch64::AEK_INVALID);
422 }
423
getExtensionFeatures(unsigned Extensions,std::vector<const char * > & Features)424 bool llvm::AArch64::getExtensionFeatures(unsigned Extensions,
425 std::vector<const char *> &Features) {
426
427 if (Extensions == AArch64::AEK_INVALID)
428 return false;
429
430 if (Extensions & AArch64::AEK_FP)
431 Features.push_back("+fp-armv8");
432 if (Extensions & AArch64::AEK_SIMD)
433 Features.push_back("+neon");
434 if (Extensions & AArch64::AEK_CRC)
435 Features.push_back("+crc");
436 if (Extensions & AArch64::AEK_CRYPTO)
437 Features.push_back("+crypto");
438 if (Extensions & AArch64::AEK_FP16)
439 Features.push_back("+fullfp16");
440 if (Extensions & AArch64::AEK_PROFILE)
441 Features.push_back("+spe");
442 if (Extensions & AArch64::AEK_RAS)
443 Features.push_back("+ras");
444
445 return true;
446 }
447
getFPUFeatures(unsigned FPUKind,std::vector<const char * > & Features)448 bool llvm::AArch64::getFPUFeatures(unsigned FPUKind,
449 std::vector<const char *> &Features) {
450 return ARM::getFPUFeatures(FPUKind, Features);
451 }
452
getArchFeatures(unsigned ArchKind,std::vector<const char * > & Features)453 bool llvm::AArch64::getArchFeatures(unsigned ArchKind,
454 std::vector<const char *> &Features) {
455 if (ArchKind == ARM::AK_INVALID || ArchKind >= ARM::AK_LAST)
456 return false;
457
458 if (ArchKind == ARM::AK_ARMV8_1A)
459 Features.push_back("+v8.1a");
460 if (ArchKind == ARM::AK_ARMV8_2A)
461 Features.push_back("+v8.2a");
462
463 return true;
464 }
465
getArchName(unsigned ArchKind)466 StringRef llvm::AArch64::getArchName(unsigned ArchKind) {
467 for (const auto &AI : AArch64ARCHNames)
468 if (AI.ID == ArchKind)
469 return AI.getName();
470 return StringRef();
471 }
472
getCPUAttr(unsigned ArchKind)473 StringRef llvm::AArch64::getCPUAttr(unsigned ArchKind) {
474 for (const auto &AI : AArch64ARCHNames)
475 if (AI.ID == ArchKind)
476 return AI.getCPUAttr();
477 return StringRef();
478 }
479
getSubArch(unsigned ArchKind)480 StringRef llvm::AArch64::getSubArch(unsigned ArchKind) {
481 for (const auto &AI : AArch64ARCHNames)
482 if (AI.ID == ArchKind)
483 return AI.getSubArch();
484 return StringRef();
485 }
486
getArchAttr(unsigned ArchKind)487 unsigned llvm::AArch64::getArchAttr(unsigned ArchKind) {
488 for (const auto &AI : AArch64ARCHNames)
489 if (AI.ID == ArchKind)
490 return AI.ArchAttr;
491 return ARMBuildAttrs::CPUArch::v8_A;
492 }
493
getArchExtName(unsigned AArchExtKind)494 StringRef llvm::AArch64::getArchExtName(unsigned AArchExtKind) {
495 for (const auto &AE : AArch64ARCHExtNames)
496 if (AArchExtKind == AE.ID)
497 return AE.getName();
498 return StringRef();
499 }
500
getArchExtFeature(StringRef ArchExt)501 const char *llvm::AArch64::getArchExtFeature(StringRef ArchExt) {
502 if (ArchExt.startswith("no")) {
503 StringRef ArchExtBase(ArchExt.substr(2));
504 for (const auto &AE : AArch64ARCHExtNames) {
505 if (AE.NegFeature && ArchExtBase == AE.getName())
506 return AE.NegFeature;
507 }
508 }
509
510 for (const auto &AE : AArch64ARCHExtNames)
511 if (AE.Feature && ArchExt == AE.getName())
512 return AE.Feature;
513 return nullptr;
514 }
515
getDefaultCPU(StringRef Arch)516 StringRef llvm::AArch64::getDefaultCPU(StringRef Arch) {
517 unsigned AK = parseArch(Arch);
518 if (AK == ARM::AK_INVALID)
519 return StringRef();
520
521 // Look for multiple AKs to find the default for pair AK+Name.
522 for (const auto &CPU : AArch64CPUNames)
523 if (CPU.ArchID == AK && CPU.Default)
524 return CPU.getName();
525
526 // If we can't find a default then target the architecture instead
527 return "generic";
528 }
529
checkArchVersion(StringRef Arch)530 unsigned llvm::AArch64::checkArchVersion(StringRef Arch) {
531 if (Arch[0] == 'v' && std::isdigit(Arch[1]))
532 return (Arch[1] - 48);
533 return 0;
534 }
535
536 // ======================================================= //
537 // Parsers
538 // ======================================================= //
539
getHWDivSynonym(StringRef HWDiv)540 static StringRef getHWDivSynonym(StringRef HWDiv) {
541 return StringSwitch<StringRef>(HWDiv)
542 .Case("thumb,arm", "arm,thumb")
543 .Default(HWDiv);
544 }
545
getFPUSynonym(StringRef FPU)546 static StringRef getFPUSynonym(StringRef FPU) {
547 return StringSwitch<StringRef>(FPU)
548 .Cases("fpa", "fpe2", "fpe3", "maverick", "invalid") // Unsupported
549 .Case("vfp2", "vfpv2")
550 .Case("vfp3", "vfpv3")
551 .Case("vfp4", "vfpv4")
552 .Case("vfp3-d16", "vfpv3-d16")
553 .Case("vfp4-d16", "vfpv4-d16")
554 .Cases("fp4-sp-d16", "vfpv4-sp-d16", "fpv4-sp-d16")
555 .Cases("fp4-dp-d16", "fpv4-dp-d16", "vfpv4-d16")
556 .Case("fp5-sp-d16", "fpv5-sp-d16")
557 .Cases("fp5-dp-d16", "fpv5-dp-d16", "fpv5-d16")
558 // FIXME: Clang uses it, but it's bogus, since neon defaults to vfpv3.
559 .Case("neon-vfpv3", "neon")
560 .Default(FPU);
561 }
562
getArchSynonym(StringRef Arch)563 static StringRef getArchSynonym(StringRef Arch) {
564 return StringSwitch<StringRef>(Arch)
565 .Case("v5", "v5t")
566 .Case("v5e", "v5te")
567 .Case("v6j", "v6")
568 .Case("v6hl", "v6k")
569 .Cases("v6m", "v6sm", "v6s-m", "v6-m")
570 .Cases("v6z", "v6zk", "v6kz")
571 .Cases("v7", "v7a", "v7hl", "v7l", "v7-a")
572 .Case("v7r", "v7-r")
573 .Case("v7m", "v7-m")
574 .Case("v7em", "v7e-m")
575 .Cases("v8", "v8a", "aarch64", "arm64", "v8-a")
576 .Case("v8.1a", "v8.1-a")
577 .Case("v8.2a", "v8.2-a")
578 .Case("v8m.base", "v8-m.base")
579 .Case("v8m.main", "v8-m.main")
580 .Default(Arch);
581 }
582
583 // MArch is expected to be of the form (arm|thumb)?(eb)?(v.+)?(eb)?, but
584 // (iwmmxt|xscale)(eb)? is also permitted. If the former, return
585 // "v.+", if the latter, return unmodified string, minus 'eb'.
586 // If invalid, return empty string.
getCanonicalArchName(StringRef Arch)587 StringRef llvm::ARM::getCanonicalArchName(StringRef Arch) {
588 size_t offset = StringRef::npos;
589 StringRef A = Arch;
590 StringRef Error = "";
591
592 // Begins with "arm" / "thumb", move past it.
593 if (A.startswith("arm64"))
594 offset = 5;
595 else if (A.startswith("arm"))
596 offset = 3;
597 else if (A.startswith("thumb"))
598 offset = 5;
599 else if (A.startswith("aarch64")) {
600 offset = 7;
601 // AArch64 uses "_be", not "eb" suffix.
602 if (A.find("eb") != StringRef::npos)
603 return Error;
604 if (A.substr(offset, 3) == "_be")
605 offset += 3;
606 }
607
608 // Ex. "armebv7", move past the "eb".
609 if (offset != StringRef::npos && A.substr(offset, 2) == "eb")
610 offset += 2;
611 // Or, if it ends with eb ("armv7eb"), chop it off.
612 else if (A.endswith("eb"))
613 A = A.substr(0, A.size() - 2);
614 // Trim the head
615 if (offset != StringRef::npos)
616 A = A.substr(offset);
617
618 // Empty string means offset reached the end, which means it's valid.
619 if (A.empty())
620 return Arch;
621
622 // Only match non-marketing names
623 if (offset != StringRef::npos) {
624 // Must start with 'vN'.
625 if (A[0] != 'v' || !std::isdigit(A[1]))
626 return Error;
627 // Can't have an extra 'eb'.
628 if (A.find("eb") != StringRef::npos)
629 return Error;
630 }
631
632 // Arch will either be a 'v' name (v7a) or a marketing name (xscale).
633 return A;
634 }
635
parseHWDiv(StringRef HWDiv)636 unsigned llvm::ARM::parseHWDiv(StringRef HWDiv) {
637 StringRef Syn = getHWDivSynonym(HWDiv);
638 for (const auto D : HWDivNames) {
639 if (Syn == D.getName())
640 return D.ID;
641 }
642 return ARM::AEK_INVALID;
643 }
644
parseFPU(StringRef FPU)645 unsigned llvm::ARM::parseFPU(StringRef FPU) {
646 StringRef Syn = getFPUSynonym(FPU);
647 for (const auto F : FPUNames) {
648 if (Syn == F.getName())
649 return F.ID;
650 }
651 return ARM::FK_INVALID;
652 }
653
654 // Allows partial match, ex. "v7a" matches "armv7a".
parseArch(StringRef Arch)655 unsigned llvm::ARM::parseArch(StringRef Arch) {
656 Arch = getCanonicalArchName(Arch);
657 StringRef Syn = getArchSynonym(Arch);
658 for (const auto A : ARCHNames) {
659 if (A.getName().endswith(Syn))
660 return A.ID;
661 }
662 return ARM::AK_INVALID;
663 }
664
parseArchExt(StringRef ArchExt)665 unsigned llvm::ARM::parseArchExt(StringRef ArchExt) {
666 for (const auto A : ARCHExtNames) {
667 if (ArchExt == A.getName())
668 return A.ID;
669 }
670 return ARM::AEK_INVALID;
671 }
672
parseCPUArch(StringRef CPU)673 unsigned llvm::ARM::parseCPUArch(StringRef CPU) {
674 for (const auto C : CPUNames) {
675 if (CPU == C.getName())
676 return C.ArchID;
677 }
678 return ARM::AK_INVALID;
679 }
680
681 // ARM, Thumb, AArch64
parseArchISA(StringRef Arch)682 unsigned llvm::ARM::parseArchISA(StringRef Arch) {
683 return StringSwitch<unsigned>(Arch)
684 .StartsWith("aarch64", ARM::IK_AARCH64)
685 .StartsWith("arm64", ARM::IK_AARCH64)
686 .StartsWith("thumb", ARM::IK_THUMB)
687 .StartsWith("arm", ARM::IK_ARM)
688 .Default(ARM::EK_INVALID);
689 }
690
691 // Little/Big endian
parseArchEndian(StringRef Arch)692 unsigned llvm::ARM::parseArchEndian(StringRef Arch) {
693 if (Arch.startswith("armeb") || Arch.startswith("thumbeb") ||
694 Arch.startswith("aarch64_be"))
695 return ARM::EK_BIG;
696
697 if (Arch.startswith("arm") || Arch.startswith("thumb")) {
698 if (Arch.endswith("eb"))
699 return ARM::EK_BIG;
700 else
701 return ARM::EK_LITTLE;
702 }
703
704 if (Arch.startswith("aarch64"))
705 return ARM::EK_LITTLE;
706
707 return ARM::EK_INVALID;
708 }
709
710 // Profile A/R/M
parseArchProfile(StringRef Arch)711 unsigned llvm::ARM::parseArchProfile(StringRef Arch) {
712 Arch = getCanonicalArchName(Arch);
713 switch (parseArch(Arch)) {
714 case ARM::AK_ARMV6M:
715 case ARM::AK_ARMV7M:
716 case ARM::AK_ARMV7EM:
717 case ARM::AK_ARMV8MMainline:
718 case ARM::AK_ARMV8MBaseline:
719 return ARM::PK_M;
720 case ARM::AK_ARMV7R:
721 return ARM::PK_R;
722 case ARM::AK_ARMV7A:
723 case ARM::AK_ARMV7K:
724 case ARM::AK_ARMV8A:
725 case ARM::AK_ARMV8_1A:
726 case ARM::AK_ARMV8_2A:
727 return ARM::PK_A;
728 }
729 return ARM::PK_INVALID;
730 }
731
732 // Version number (ex. v7 = 7).
parseArchVersion(StringRef Arch)733 unsigned llvm::ARM::parseArchVersion(StringRef Arch) {
734 Arch = getCanonicalArchName(Arch);
735 switch (parseArch(Arch)) {
736 case ARM::AK_ARMV2:
737 case ARM::AK_ARMV2A:
738 return 2;
739 case ARM::AK_ARMV3:
740 case ARM::AK_ARMV3M:
741 return 3;
742 case ARM::AK_ARMV4:
743 case ARM::AK_ARMV4T:
744 return 4;
745 case ARM::AK_ARMV5T:
746 case ARM::AK_ARMV5TE:
747 case ARM::AK_IWMMXT:
748 case ARM::AK_IWMMXT2:
749 case ARM::AK_XSCALE:
750 case ARM::AK_ARMV5TEJ:
751 return 5;
752 case ARM::AK_ARMV6:
753 case ARM::AK_ARMV6K:
754 case ARM::AK_ARMV6T2:
755 case ARM::AK_ARMV6KZ:
756 case ARM::AK_ARMV6M:
757 return 6;
758 case ARM::AK_ARMV7A:
759 case ARM::AK_ARMV7R:
760 case ARM::AK_ARMV7M:
761 case ARM::AK_ARMV7S:
762 case ARM::AK_ARMV7EM:
763 case ARM::AK_ARMV7K:
764 return 7;
765 case ARM::AK_ARMV8A:
766 case ARM::AK_ARMV8_1A:
767 case ARM::AK_ARMV8_2A:
768 case ARM::AK_ARMV8MBaseline:
769 case ARM::AK_ARMV8MMainline:
770 return 8;
771 }
772 return 0;
773 }
774
getCanonicalArchName(StringRef Arch)775 StringRef llvm::AArch64::getCanonicalArchName(StringRef Arch) {
776 return ARM::getCanonicalArchName(Arch);
777 }
778
parseFPU(StringRef FPU)779 unsigned llvm::AArch64::parseFPU(StringRef FPU) {
780 return ARM::parseFPU(FPU);
781 }
782
783 // Allows partial match, ex. "v8a" matches "armv8a".
parseArch(StringRef Arch)784 unsigned llvm::AArch64::parseArch(StringRef Arch) {
785 Arch = getCanonicalArchName(Arch);
786 if (checkArchVersion(Arch) < 8)
787 return ARM::AK_INVALID;
788
789 StringRef Syn = getArchSynonym(Arch);
790 for (const auto A : AArch64ARCHNames) {
791 if (A.getName().endswith(Syn))
792 return A.ID;
793 }
794 return ARM::AK_INVALID;
795 }
796
parseArchExt(StringRef ArchExt)797 unsigned llvm::AArch64::parseArchExt(StringRef ArchExt) {
798 for (const auto A : AArch64ARCHExtNames) {
799 if (ArchExt == A.getName())
800 return A.ID;
801 }
802 return AArch64::AEK_INVALID;
803 }
804
parseCPUArch(StringRef CPU)805 unsigned llvm::AArch64::parseCPUArch(StringRef CPU) {
806 for (const auto C : AArch64CPUNames) {
807 if (CPU == C.getName())
808 return C.ArchID;
809 }
810 return ARM::AK_INVALID;
811 }
812
813 // ARM, Thumb, AArch64
parseArchISA(StringRef Arch)814 unsigned llvm::AArch64::parseArchISA(StringRef Arch) {
815 return ARM::parseArchISA(Arch);
816 }
817
818 // Little/Big endian
parseArchEndian(StringRef Arch)819 unsigned llvm::AArch64::parseArchEndian(StringRef Arch) {
820 return ARM::parseArchEndian(Arch);
821 }
822
823 // Profile A/R/M
parseArchProfile(StringRef Arch)824 unsigned llvm::AArch64::parseArchProfile(StringRef Arch) {
825 return ARM::parseArchProfile(Arch);
826 }
827
828 // Version number (ex. v8 = 8).
parseArchVersion(StringRef Arch)829 unsigned llvm::AArch64::parseArchVersion(StringRef Arch) {
830 return ARM::parseArchVersion(Arch);
831 }
832