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