1 //===----------- TargetParser.cpp - Target Parser -------------------------===//
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 #include "llvm/ADT/STLExtras.h"
11 #include "llvm/Support/ARMBuildAttributes.h"
12 #include "llvm/Support/TargetParser.h"
13 #include "gtest/gtest.h"
14 #include <string>
15 
16 using namespace llvm;
17 
18 namespace {
19 static const unsigned kAArch64ArchExtKinds[] = {
20 #define AARCH64_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE) ID,
21 #include "llvm/Support/AArch64TargetParser.def"
22 #undef AARCH64_ARCH_EXT_NAME
23 };
24 
25 template <typename T> struct ArchNames {
26   const char *Name;
27   unsigned DefaultFPU;
28   unsigned ArchBaseExtensions;
29   T ID;
30   ARMBuildAttrs::CPUArch ArchAttr;
31 };
32 ArchNames<AArch64::ArchKind> kAArch64ARCHNames[] = {
33 #define AARCH64_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU,        \
34                      ARCH_BASE_EXT)                                            \
35   {NAME, ARM::ARCH_FPU, ARCH_BASE_EXT, AArch64::ArchKind::ID, ARCH_ATTR},
36 #include "llvm/Support/AArch64TargetParser.def"
37 #undef AARCH64_ARCH
38 };
39 ArchNames<ARM::ArchKind> kARMARCHNames[] = {
40 #define ARM_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU,            \
41                  ARCH_BASE_EXT)                                                \
42   {NAME, ARM::ARCH_FPU, ARCH_BASE_EXT, ARM::ID, ARCH_ATTR},
43 #include "llvm/Support/ARMTargetParser.def"
44 #undef ARM_ARCH
45 };
46 
47 template <typename T> struct CpuNames {
48   const char *Name;
49   T ID;
50   unsigned DefaultFPU;
51   unsigned DefaultExt;
52 };
53 CpuNames<AArch64::ArchKind> kAArch64CPUNames[] = {
54 #define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT)       \
55   {NAME, AArch64::ArchKind::ID, ARM::DEFAULT_FPU, DEFAULT_EXT},
56 #include "llvm/Support/AArch64TargetParser.def"
57 #undef AARCH64_CPU_NAME
58 };
59 CpuNames<ARM::ArchKind> kARMCPUNames[] = {
60 #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT)           \
61   {NAME, ARM::ID, ARM::DEFAULT_FPU, DEFAULT_EXT},
62 #include "llvm/Support/ARMTargetParser.def"
63 #undef ARM_CPU_NAME
64 };
65 
66 const char *ARMArch[] = {
67     "armv2",        "armv2a",      "armv3",    "armv3m",       "armv4",
68     "armv4t",       "armv5",       "armv5t",   "armv5e",       "armv5te",
69     "armv5tej",     "armv6",       "armv6j",   "armv6k",       "armv6hl",
70     "armv6t2",      "armv6kz",     "armv6z",   "armv6zk",      "armv6-m",
71     "armv6m",       "armv6sm",     "armv6s-m", "armv7-a",      "armv7",
72     "armv7a",       "armv7hl",     "armv7l",   "armv7-r",      "armv7r",
73     "armv7-m",      "armv7m",      "armv7k",   "armv7s",       "armv7e-m",
74     "armv7em",      "armv8-a",     "armv8",    "armv8a",       "armv8.1-a",
75     "armv8.1a",     "armv8.2-a",   "armv8.2a", "armv8-m.base", "armv8m.base",
76     "armv8-m.main", "armv8m.main", "iwmmxt",   "iwmmxt2",      "xscale"};
77 
78 template <typename T, size_t N>
79 bool contains(const T (&array)[N], const T element) {
80   return std::find(std::begin(array), std::end(array), element) !=
81          std::end(array);
82 }
83 
84 TEST(TargetParserTest, ARMArchName) {
85   for (ARM::ArchKind AK = static_cast<ARM::ArchKind>(0);
86        AK <= ARM::ArchKind::AK_LAST;
87        AK = static_cast<ARM::ArchKind>(static_cast<unsigned>(AK) + 1))
88     EXPECT_TRUE(AK == ARM::AK_LAST ? ARM::getArchName(AK).empty()
89                                    : !ARM::getArchName(AK).empty());
90 }
91 
92 TEST(TargetParserTest, ARMCPUAttr) {
93   for (ARM::ArchKind AK = static_cast<ARM::ArchKind>(0);
94        AK <= ARM::ArchKind::AK_LAST;
95        AK = static_cast<ARM::ArchKind>(static_cast<unsigned>(AK) + 1))
96     EXPECT_TRUE((AK == ARM::AK_INVALID || AK == ARM::AK_LAST)
97                     ? ARM::getCPUAttr(AK).empty()
98                     : !ARM::getCPUAttr(AK).empty());
99 }
100 
101 TEST(TargetParserTest, ARMSubArch) {
102   for (ARM::ArchKind AK = static_cast<ARM::ArchKind>(0);
103        AK <= ARM::ArchKind::AK_LAST;
104        AK = static_cast<ARM::ArchKind>(static_cast<unsigned>(AK) + 1))
105     EXPECT_TRUE((AK == ARM::AK_INVALID || AK == ARM::AK_IWMMXT ||
106                  AK == ARM::AK_IWMMXT2 || AK == ARM::AK_LAST)
107                     ? ARM::getSubArch(AK).empty()
108                     : !ARM::getSubArch(AK).empty());
109 }
110 
111 TEST(TargetParserTest, ARMFPUName) {
112   for (ARM::FPUKind FK = static_cast<ARM::FPUKind>(0);
113        FK <= ARM::FPUKind::FK_LAST;
114        FK = static_cast<ARM::FPUKind>(static_cast<unsigned>(FK) + 1))
115     EXPECT_TRUE(FK == ARM::FK_LAST ? ARM::getFPUName(FK).empty()
116                                    : !ARM::getFPUName(FK).empty());
117 }
118 
119 TEST(TargetParserTest, ARMFPUVersion) {
120   for (ARM::FPUKind FK = static_cast<ARM::FPUKind>(0);
121        FK <= ARM::FPUKind::FK_LAST;
122        FK = static_cast<ARM::FPUKind>(static_cast<unsigned>(FK) + 1))
123     if (FK == ARM::FK_LAST)
124       EXPECT_EQ(0U, ARM::getFPUVersion(FK));
125     else
126       EXPECT_LE(0U, ARM::getFPUVersion(FK));
127 }
128 
129 TEST(TargetParserTest, ARMFPUNeonSupportLevel) {
130   for (ARM::FPUKind FK = static_cast<ARM::FPUKind>(0);
131        FK <= ARM::FPUKind::FK_LAST;
132        FK = static_cast<ARM::FPUKind>(static_cast<unsigned>(FK) + 1))
133     if (FK == ARM::FK_LAST)
134       EXPECT_EQ(0U, ARM::getFPUNeonSupportLevel(FK));
135     else
136       EXPECT_LE(0U, ARM::getFPUNeonSupportLevel(FK));
137 }
138 
139 TEST(TargetParserTest, ARMFPURestriction) {
140   for (ARM::FPUKind FK = static_cast<ARM::FPUKind>(0);
141        FK <= ARM::FPUKind::FK_LAST;
142        FK = static_cast<ARM::FPUKind>(static_cast<unsigned>(FK) + 1))
143     if (FK == ARM::FK_LAST)
144       EXPECT_EQ(0U, ARM::getFPURestriction(FK));
145     else
146       EXPECT_LE(0U, ARM::getFPURestriction(FK));
147 }
148 
149 TEST(TargetParserTest, ARMDefaultFPU) {
150   for (ARM::ArchKind AK = static_cast<ARM::ArchKind>(0);
151        AK < ARM::ArchKind::AK_LAST;
152        AK = static_cast<ARM::ArchKind>(static_cast<unsigned>(AK) + 1))
153     EXPECT_EQ(kARMARCHNames[AK].DefaultFPU,
154               ARM::getDefaultFPU(StringRef("generic"), AK));
155 
156   for (const auto &ARMCPUName : kARMCPUNames)
157     EXPECT_EQ(ARMCPUName.DefaultFPU, ARM::getDefaultFPU(ARMCPUName.Name, 0));
158 }
159 
160 TEST(TargetParserTest, ARMDefaultExtensions) {
161   for (ARM::ArchKind AK = static_cast<ARM::ArchKind>(0);
162        AK < ARM::ArchKind::AK_LAST;
163        AK = static_cast<ARM::ArchKind>(static_cast<unsigned>(AK) + 1))
164     EXPECT_EQ(kARMARCHNames[AK].ArchBaseExtensions,
165               ARM::getDefaultExtensions(StringRef("generic"), AK));
166 
167   for (const auto &ARMCPUName : kARMCPUNames) {
168     unsigned DefaultExt =
169         kARMARCHNames[ARMCPUName.ID].ArchBaseExtensions | ARMCPUName.DefaultExt;
170     EXPECT_EQ(DefaultExt, ARM::getDefaultExtensions(ARMCPUName.Name, 0));
171   }
172 }
173 
174 TEST(TargetParserTest, ARMExtensionFeatures) {
175   std::vector<const char *> Features;
176   unsigned Extensions = ARM::AEK_CRC | ARM::AEK_CRYPTO | ARM::AEK_DSP |
177                         ARM::AEK_HWDIVARM | ARM::AEK_HWDIV | ARM::AEK_MP |
178                         ARM::AEK_SEC | ARM::AEK_VIRT | ARM::AEK_RAS;
179 
180   for (unsigned i = 0; i <= Extensions; i++)
181     EXPECT_TRUE(i == 0 ? !ARM::getExtensionFeatures(i, Features)
182                        : ARM::getExtensionFeatures(i, Features));
183 }
184 
185 TEST(TargetParserTest, ARMFPUFeatures) {
186   std::vector<const char *> Features;
187   for (ARM::FPUKind FK = static_cast<ARM::FPUKind>(0);
188        FK <= ARM::FPUKind::FK_LAST;
189        FK = static_cast<ARM::FPUKind>(static_cast<unsigned>(FK) + 1))
190     EXPECT_TRUE((FK == ARM::FK_INVALID || FK >= ARM::FK_LAST)
191                     ? !ARM::getFPUFeatures(FK, Features)
192                     : ARM::getFPUFeatures(FK, Features));
193 }
194 
195 TEST(TargetParserTest, ARMArchAttr) {
196   for (ARM::ArchKind AK = static_cast<ARM::ArchKind>(0);
197        AK <= ARM::ArchKind::AK_LAST;
198        AK = static_cast<ARM::ArchKind>(static_cast<unsigned>(AK) + 1))
199     EXPECT_TRUE(AK == ARM::AK_LAST
200                     ? (ARMBuildAttrs::CPUArch::Pre_v4 == ARM::getArchAttr(AK))
201                     : (kARMARCHNames[AK].ArchAttr == ARM::getArchAttr(AK)));
202 }
203 
204 TEST(TargetParserTest, ARMArchExtFeature) {
205   const char *ArchExt[][4] = {{"crc", "nocrc", "+crc", "-crc"},
206                               {"crypto", "nocrypto", "+crypto", "-crypto"},
207                               {"dsp", "nodsp", "+dsp", "-dsp"},
208                               {"fp", "nofp", nullptr, nullptr},
209                               {"idiv", "noidiv", nullptr, nullptr},
210                               {"mp", "nomp", nullptr, nullptr},
211                               {"simd", "nosimd", nullptr, nullptr},
212                               {"sec", "nosec", nullptr, nullptr},
213                               {"virt", "novirt", nullptr, nullptr},
214                               {"fp16", "nofp16", "+fullfp16", "-fullfp16"},
215                               {"ras", "noras", "+ras", "-ras"},
216                               {"os", "noos", nullptr, nullptr},
217                               {"iwmmxt", "noiwmmxt", nullptr, nullptr},
218                               {"iwmmxt2", "noiwmmxt2", nullptr, nullptr},
219                               {"maverick", "maverick", nullptr, nullptr},
220                               {"xscale", "noxscale", nullptr, nullptr}};
221 
222   for (unsigned i = 0; i < array_lengthof(ArchExt); i++) {
223     EXPECT_STREQ(ArchExt[i][2], ARM::getArchExtFeature(ArchExt[i][0]));
224     EXPECT_STREQ(ArchExt[i][3], ARM::getArchExtFeature(ArchExt[i][1]));
225   }
226 }
227 
228 TEST(TargetParserTest, ARMDefaultCPU) {
229   for (unsigned i = 0; i < array_lengthof(ARMArch); i++)
230     EXPECT_FALSE(ARM::getDefaultCPU(ARMArch[i]).empty());
231 }
232 
233 TEST(TargetParserTest, ARMparseHWDiv) {
234   const char *hwdiv[] = {"thumb", "arm", "arm,thumb", "thumb,arm"};
235 
236   for (unsigned i = 0; i < array_lengthof(hwdiv); i++)
237     EXPECT_NE(ARM::AEK_INVALID, ARM::parseHWDiv((StringRef)hwdiv[i]));
238 }
239 
240 TEST(TargetParserTest, ARMparseFPU) {
241   const char *FPU[] = {"vfp",
242                        "vfpv2",
243                        "vfp2",
244                        "vfpv3",
245                        "vfp3",
246                        "vfpv3-fp16",
247                        "vfpv3-d16",
248                        "vfp3-d16",
249                        "vfpv3-d16-fp16",
250                        "vfpv3xd",
251                        "vfpv3xd-fp16",
252                        "vfpv4",
253                        "vfp4",
254                        "vfpv4-d16",
255                        "vfp4-d16",
256                        "fp4-dp-d16",
257                        "fpv4-dp-d16",
258                        "fpv4-sp-d16",
259                        "fp4-sp-d16",
260                        "vfpv4-sp-d16",
261                        "fpv5-d16",
262                        "fp5-dp-d16",
263                        "fpv5-dp-d16",
264                        "fpv5-sp-d16",
265                        "fp5-sp-d16",
266                        "fp-armv8",
267                        "neon",
268                        "neon-vfpv3",
269                        "neon-fp16",
270                        "neon-vfpv4",
271                        "neon-fp-armv8",
272                        "crypto-neon-fp-armv8",
273                        "softvfp"};
274 
275   for (unsigned i = 0; i < array_lengthof(FPU); i++)
276     EXPECT_NE(ARM::FK_INVALID, ARM::parseFPU((StringRef)FPU[i]));
277 }
278 
279 TEST(TargetParserTest, ARMparseArch) {
280   for (unsigned i = 0; i < array_lengthof(ARMArch); i++)
281     EXPECT_NE(ARM::AEK_INVALID, ARM::parseArch(ARMArch[i]));
282 }
283 
284 TEST(TargetParserTest, ARMparseArchExt) {
285   const char *ArchExt[] = {"none",     "crc",   "crypto", "dsp",    "fp",
286                            "idiv",     "mp",    "simd",   "sec",    "virt",
287                            "fp16",     "ras",   "os",     "iwmmxt", "iwmmxt2",
288                            "maverick", "xscale"};
289 
290   for (unsigned i = 0; i < array_lengthof(ArchExt); i++)
291     EXPECT_NE(ARM::AEK_INVALID, ARM::parseArchExt(ArchExt[i]));
292 }
293 
294 TEST(TargetParserTest, ARMparseCPUArch) {
295   const char *CPU[] = {
296       "arm2",          "arm3",          "arm6",        "arm7m",
297       "arm8",          "arm810",        "strongarm",   "strongarm110",
298       "strongarm1100", "strongarm1110", "arm7tdmi",    "arm7tdmi-s",
299       "arm710t",       "arm720t",       "arm9",        "arm9tdmi",
300       "arm920",        "arm920t",       "arm922t",     "arm9312",
301       "arm940t",       "ep9312",        "arm10tdmi",   "arm1020t",
302       "arm9e",         "arm946e-s",     "arm966e-s",   "arm968e-s",
303       "arm10e",        "arm1020e",      "arm1022e",    "arm926ej-s",
304       "arm1136j-s",    "arm1136jf-s",   "arm1136jz-s", "arm1176j-s",
305       "arm1176jz-s",   "mpcore",        "mpcorenovfp", "arm1176jzf-s",
306       "arm1156t2-s",   "arm1156t2f-s",  "cortex-m0",   "cortex-m0plus",
307       "cortex-m1",     "sc000",         "cortex-a5",   "cortex-a7",
308       "cortex-a8",     "cortex-a9",     "cortex-a12",  "cortex-a15",
309       "cortex-a17",    "krait",         "cortex-r4",   "cortex-r4f",
310       "cortex-r5",     "cortex-r7",     "cortex-r8",   "sc300",
311       "cortex-m3",     "cortex-m4",     "cortex-m7",   "cortex-a32",
312       "cortex-a35",    "cortex-a53",    "cortex-a57",  "cortex-a72",
313       "cortex-a73",    "cyclone",       "exynos-m1",   "exynos-m2",
314       "iwmmxt",        "xscale",        "swift"};
315 
316   for (const auto &ARMCPUName : kARMCPUNames)
317     EXPECT_TRUE(contains(CPU, ARMCPUName.Name)
318                     ? (ARM::AK_INVALID != ARM::parseCPUArch(ARMCPUName.Name))
319                     : (ARM::AK_INVALID == ARM::parseCPUArch(ARMCPUName.Name)));
320 }
321 
322 TEST(TargetParserTest, ARMparseArchEndianAndISA) {
323   const char *Arch[] = {
324       "v2",    "v2a",    "v3",    "v3m",  "v4",   "v4t",  "v5",    "v5t",
325       "v5e",   "v5te",   "v5tej", "v6",   "v6j",  "v6k",  "v6hl",  "v6t2",
326       "v6kz",  "v6z",    "v6zk",  "v6-m", "v6m",  "v6sm", "v6s-m", "v7-a",
327       "v7",    "v7a",    "v7hl",  "v7l",  "v7-r", "v7r",  "v7-m",  "v7m",
328       "v7k",   "v7s",    "v7e-m", "v7em", "v8-a", "v8",   "v8a",   "v8.1-a",
329       "v8.1a", "v8.2-a", "v8.2a"};
330 
331   for (unsigned i = 0; i < array_lengthof(Arch); i++) {
332     std::string arm_1 = "armeb" + (std::string)(Arch[i]);
333     std::string arm_2 = "arm" + (std::string)(Arch[i]) + "eb";
334     std::string arm_3 = "arm" + (std::string)(Arch[i]);
335     std::string thumb_1 = "thumbeb" + (std::string)(Arch[i]);
336     std::string thumb_2 = "thumb" + (std::string)(Arch[i]) + "eb";
337     std::string thumb_3 = "thumb" + (std::string)(Arch[i]);
338 
339     EXPECT_EQ(ARM::EK_BIG, ARM::parseArchEndian(arm_1));
340     EXPECT_EQ(ARM::EK_BIG, ARM::parseArchEndian(arm_2));
341     EXPECT_EQ(ARM::EK_LITTLE, ARM::parseArchEndian(arm_3));
342 
343     EXPECT_EQ(ARM::IK_ARM, ARM::parseArchISA(arm_1));
344     EXPECT_EQ(ARM::IK_ARM, ARM::parseArchISA(arm_2));
345     EXPECT_EQ(ARM::IK_ARM, ARM::parseArchISA(arm_3));
346     if (i >= 4) {
347       EXPECT_EQ(ARM::EK_BIG, ARM::parseArchEndian(thumb_1));
348       EXPECT_EQ(ARM::EK_BIG, ARM::parseArchEndian(thumb_2));
349       EXPECT_EQ(ARM::EK_LITTLE, ARM::parseArchEndian(thumb_3));
350 
351       EXPECT_EQ(ARM::IK_THUMB, ARM::parseArchISA(thumb_1));
352       EXPECT_EQ(ARM::IK_THUMB, ARM::parseArchISA(thumb_2));
353       EXPECT_EQ(ARM::IK_THUMB, ARM::parseArchISA(thumb_3));
354     }
355   }
356 
357   EXPECT_EQ(ARM::EK_LITTLE, ARM::parseArchEndian("aarch64"));
358   EXPECT_EQ(ARM::EK_BIG, ARM::parseArchEndian("aarch64_be"));
359 
360   EXPECT_EQ(ARM::IK_AARCH64, ARM::parseArchISA("aarch64"));
361   EXPECT_EQ(ARM::IK_AARCH64, ARM::parseArchISA("aarch64_be"));
362   EXPECT_EQ(ARM::IK_AARCH64, ARM::parseArchISA("arm64"));
363   EXPECT_EQ(ARM::IK_AARCH64, ARM::parseArchISA("arm64_be"));
364 }
365 
366 TEST(TargetParserTest, ARMparseArchProfile) {
367   for (unsigned i = 0; i < array_lengthof(ARMArch); i++) {
368     switch (ARM::parseArch(ARMArch[i])) {
369     case ARM::AK_ARMV6M:
370     case ARM::AK_ARMV7M:
371     case ARM::AK_ARMV7EM:
372     case ARM::AK_ARMV8MMainline:
373     case ARM::AK_ARMV8MBaseline:
374       EXPECT_EQ(ARM::PK_M, ARM::parseArchProfile(ARMArch[i]));
375       continue;
376     case ARM::AK_ARMV7R:
377       EXPECT_EQ(ARM::PK_R, ARM::parseArchProfile(ARMArch[i]));
378       continue;
379     case ARM::AK_ARMV7A:
380     case ARM::AK_ARMV7K:
381     case ARM::AK_ARMV8A:
382     case ARM::AK_ARMV8_1A:
383     case ARM::AK_ARMV8_2A:
384       EXPECT_EQ(ARM::PK_A, ARM::parseArchProfile(ARMArch[i]));
385       continue;
386     }
387     EXPECT_EQ(ARM::PK_INVALID, ARM::parseArchProfile(ARMArch[i]));
388   }
389 }
390 
391 TEST(TargetParserTest, ARMparseArchVersion) {
392   for (unsigned i = 0; i < array_lengthof(ARMArch); i++)
393     if (((std::string)ARMArch[i]).substr(0, 4) == "armv")
394       EXPECT_EQ((ARMArch[i][4] - 48u), ARM::parseArchVersion(ARMArch[i]));
395     else
396       EXPECT_EQ(5u, ARM::parseArchVersion(ARMArch[i]));
397 }
398 
399 TEST(TargetParserTest, AArch64DefaultFPU) {
400   for (unsigned AK = 0; AK < static_cast<unsigned>(AArch64::ArchKind::AK_LAST);
401        AK++)
402     EXPECT_EQ(kAArch64ARCHNames[AK].DefaultFPU,
403               AArch64::getDefaultFPU(StringRef("generic"), AK));
404 
405   for (const auto &AArch64CPUName : kAArch64CPUNames)
406     EXPECT_EQ(AArch64CPUName.DefaultFPU,
407               AArch64::getDefaultFPU(AArch64CPUName.Name,
408                                      static_cast<unsigned>(AArch64CPUName.ID)));
409 }
410 
411 TEST(TargetParserTest, AArch64DefaultExt) {
412   for (unsigned AK = 0; AK < static_cast<unsigned>(AArch64::ArchKind::AK_LAST);
413        AK++)
414     EXPECT_EQ(kAArch64ARCHNames[AK].ArchBaseExtensions,
415               AArch64::getDefaultExtensions(StringRef("generic"), AK));
416 
417   for (const auto &AArch64CPUName : kAArch64CPUNames)
418     EXPECT_EQ(
419         AArch64CPUName.DefaultExt,
420         AArch64::getDefaultExtensions(
421             AArch64CPUName.Name, static_cast<unsigned>(AArch64CPUName.ID)));
422 }
423 
424 TEST(TargetParserTest, AArch64ExtensionFeatures) {
425   std::vector<const char *> Features;
426   unsigned Extensions = AArch64::AEK_CRC | AArch64::AEK_CRYPTO |
427                         AArch64::AEK_FP | AArch64::AEK_SIMD |
428                         AArch64::AEK_FP16 | AArch64::AEK_PROFILE |
429                         AArch64::AEK_RAS;
430 
431   for (unsigned i = 0; i <= Extensions; i++)
432     EXPECT_TRUE(i == 0 ? !AArch64::getExtensionFeatures(i, Features)
433                        : AArch64::getExtensionFeatures(i, Features));
434 }
435 
436 TEST(TargetParserTest, AArch64ArchFeatures) {
437   std::vector<const char *> Features;
438 
439   for (unsigned AK = 0; AK < static_cast<unsigned>(AArch64::ArchKind::AK_LAST);
440        AK++)
441     EXPECT_TRUE((AK == static_cast<unsigned>(AArch64::ArchKind::AK_INVALID) ||
442                  AK == static_cast<unsigned>(AArch64::ArchKind::AK_LAST))
443                     ? !AArch64::getArchFeatures(AK, Features)
444                     : AArch64::getArchFeatures(AK, Features));
445 }
446 
447 TEST(TargetParserTest, AArch64ArchName) {
448   for (unsigned AK = 0; AK < static_cast<unsigned>(AArch64::ArchKind::AK_LAST);
449        AK++)
450     EXPECT_TRUE(AK == static_cast<unsigned>(AArch64::ArchKind::AK_LAST)
451                     ? AArch64::getArchName(AK).empty()
452                     : !AArch64::getArchName(AK).empty());
453 }
454 
455 TEST(TargetParserTest, AArch64CPUAttr) {
456   for (unsigned AK = 0; AK < static_cast<unsigned>(AArch64::ArchKind::AK_LAST);
457        AK++)
458     EXPECT_TRUE((AK == static_cast<unsigned>(AArch64::ArchKind::AK_INVALID) ||
459                  AK == static_cast<unsigned>(AArch64::ArchKind::AK_LAST))
460                     ? AArch64::getCPUAttr(AK).empty()
461                     : !AArch64::getCPUAttr(AK).empty());
462 }
463 
464 TEST(TargetParserTest, AArch64SubArch) {
465   for (unsigned AK = 0; AK < static_cast<unsigned>(AArch64::ArchKind::AK_LAST);
466        AK++)
467     EXPECT_TRUE((AK == static_cast<unsigned>(AArch64::ArchKind::AK_INVALID) ||
468                  AK == static_cast<unsigned>(AArch64::ArchKind::AK_LAST))
469                     ? AArch64::getSubArch(AK).empty()
470                     : !AArch64::getSubArch(AK).empty());
471 }
472 
473 TEST(TargetParserTest, AArch64ArchAttr) {
474   for (unsigned AK = 0; AK < static_cast<unsigned>(AArch64::ArchKind::AK_LAST);
475        AK++)
476     EXPECT_TRUE(
477         AK == static_cast<unsigned>(AArch64::ArchKind::AK_LAST)
478             ? (ARMBuildAttrs::CPUArch::v8_A == AArch64::getArchAttr(AK))
479             : (kAArch64ARCHNames[AK].ArchAttr == AArch64::getArchAttr(AK)));
480 }
481 
482 TEST(TargetParserTest, AArch64ArchExtName) {
483   for (AArch64::ArchExtKind AEK = static_cast<AArch64::ArchExtKind>(0);
484        AEK <= AArch64::ArchExtKind::AEK_RAS;
485        AEK = static_cast<AArch64::ArchExtKind>(static_cast<unsigned>(AEK) + 1))
486     EXPECT_TRUE(contains(kAArch64ArchExtKinds, static_cast<unsigned>(AEK))
487                     ? !AArch64::getArchExtName(AEK).empty()
488                     : AArch64::getArchExtName(AEK).empty());
489 }
490 
491 TEST(TargetParserTest, AArch64ArchExtFeature) {
492   const char *ArchExt[][4] = {{"crc", "nocrc", "+crc", "-crc"},
493                               {"crypto", "nocrypto", "+crypto", "-crypto"},
494                               {"fp", "nofp", "+fp-armv8", "-fp-armv8"},
495                               {"simd", "nosimd", "+neon", "-neon"},
496                               {"fp16", "nofp16", "+fullfp16", "-fullfp16"},
497                               {"profile", "noprofile", "+spe", "-spe"},
498                               {"ras", "noras", "+ras", "-ras"}};
499 
500   for (unsigned i = 0; i < array_lengthof(ArchExt); i++) {
501     EXPECT_STREQ(ArchExt[i][2], AArch64::getArchExtFeature(ArchExt[i][0]));
502     EXPECT_STREQ(ArchExt[i][3], AArch64::getArchExtFeature(ArchExt[i][1]));
503   }
504 }
505 
506 TEST(TargetParserTest, AArch64DefaultCPU) {
507   const char *Arch[] = {"armv8a",    "armv8-a",  "armv8",    "armv8.1a",
508                         "armv8.1-a", "armv8.2a", "armv8.2-a"};
509 
510   for (unsigned i = 0; i < array_lengthof(Arch); i++)
511     EXPECT_FALSE(AArch64::getDefaultCPU(Arch[i]).empty());
512 }
513 
514 TEST(TargetParserTest, AArch64parseArch) {
515   const char *Arch[] = {"armv8",     "armv8a",   "armv8-a",  "armv8.1a",
516                         "armv8.1-a", "armv8.2a", "armv8.2-a"};
517 
518   for (unsigned i = 0; i < array_lengthof(Arch); i++)
519     EXPECT_NE(static_cast<unsigned>(AArch64::ArchKind::AK_INVALID),
520               AArch64::parseArch(Arch[i]));
521   EXPECT_EQ(static_cast<unsigned>(AArch64::ArchKind::AK_INVALID),
522             AArch64::parseArch("aarch64"));
523   EXPECT_EQ(static_cast<unsigned>(AArch64::ArchKind::AK_INVALID),
524             AArch64::parseArch("arm64"));
525 }
526 
527 TEST(TargetParserTest, AArch64parseArchExt) {
528   const char *ArchExt[] = {"none", "crc",  "crypto",  "fp",
529                            "simd", "fp16", "profile", "ras"};
530 
531   for (unsigned i = 0; i < array_lengthof(ArchExt); i++)
532     EXPECT_NE(AArch64::AEK_INVALID, AArch64::parseArchExt(ArchExt[i]));
533 }
534 
535 TEST(TargetParserTest, AArch64parseCPUArch) {
536   const char *CPU[] = {"cortex-a35", "cortex-a53", "cortex-a57",
537                        "cortex-a72", "cortex-a73", "cyclone",
538                        "exynos-m1",  "exynos-m2",  "kryo",
539                        "vulcan"};
540 
541   for (const auto &AArch64CPUName : kAArch64CPUNames)
542     EXPECT_TRUE(contains(CPU, AArch64CPUName.Name)
543                     ? (static_cast<unsigned>(AArch64::ArchKind::AK_INVALID) !=
544                        AArch64::parseCPUArch(AArch64CPUName.Name))
545                     : (static_cast<unsigned>(AArch64::ArchKind::AK_INVALID) ==
546                        AArch64::parseCPUArch(AArch64CPUName.Name)));
547 }
548 }
549