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