xref: /llvm-project/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp (revision 762546565173e27b1851dfd1f3bfcc7fc847a2f9)
1 //===-- unittests/RISCVISAInfoTest.cpp ------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "llvm/TargetParser/RISCVISAInfo.h"
10 #include "llvm/ADT/StringMap.h"
11 #include "llvm/Testing/Support/Error.h"
12 #include "gtest/gtest.h"
13 
14 using ::testing::ElementsAre;
15 
16 using namespace llvm;
17 
18 bool operator==(const RISCVISAUtils::ExtensionVersion &A,
19                 const RISCVISAUtils::ExtensionVersion &B) {
20   return A.Major == B.Major && A.Minor == B.Minor;
21 }
22 
23 TEST(ParseNormalizedArchString, RejectsInvalidChars) {
24   for (StringRef Input : {"RV32", "rV64", "rv32i2P0", "rv64i2p0_A2p0",
25                           "rv32e2.0", "rva20u64+zbc"}) {
26     EXPECT_EQ(
27         toString(RISCVISAInfo::parseNormalizedArchString(Input).takeError()),
28         "string may only contain [a-z0-9_]");
29   }
30 }
31 
32 TEST(ParseNormalizedArchString, RejectsInvalidBaseISA) {
33   for (StringRef Input : {"rv32", "rv64", "rv32j", "rv65i"}) {
34     EXPECT_EQ(
35         toString(RISCVISAInfo::parseNormalizedArchString(Input).takeError()),
36         "arch string must begin with valid base ISA");
37   }
38 }
39 
40 TEST(ParseNormalizedArchString, RejectsMalformedInputs) {
41   for (StringRef Input : {"rv64e2p", "rv32i", "rv64ip1"}) {
42     EXPECT_EQ(
43         toString(RISCVISAInfo::parseNormalizedArchString(Input).takeError()),
44         "extension lacks version in expected format");
45   }
46 
47   for (StringRef Input : {"rv64i2p0_", "rv32i2p0__a2p0"}) {
48     EXPECT_EQ(
49         toString(RISCVISAInfo::parseNormalizedArchString(Input).takeError()),
50         "extension name missing after separator '_'");
51   }
52 }
53 
54 TEST(ParseNormalizedArchString, RejectsOnlyVersion) {
55   for (StringRef Input : {"rv64i2p0_1p0", "rv32i2p0_1p0"}) {
56     EXPECT_EQ(
57         toString(RISCVISAInfo::parseNormalizedArchString(Input).takeError()),
58         "missing extension name");
59   }
60 }
61 
62 TEST(ParseNormalizedArchString, RejectsBadZ) {
63   for (StringRef Input : {"rv64i2p0_z1p0", "rv32i2p0_z2a1p0"}) {
64     EXPECT_EQ(
65         toString(RISCVISAInfo::parseNormalizedArchString(Input).takeError()),
66         "'z' must be followed by a letter");
67   }
68 }
69 
70 TEST(ParseNormalizedArchString, RejectsBadS) {
71   for (StringRef Input : {"rv64i2p0_s1p0", "rv32i2p0_s2a1p0"}) {
72     EXPECT_EQ(
73         toString(RISCVISAInfo::parseNormalizedArchString(Input).takeError()),
74         "'s' must be followed by a letter");
75   }
76 }
77 
78 TEST(ParseNormalizedArchString, RejectsBadX) {
79   for (StringRef Input : {"rv64i2p0_x1p0", "rv32i2p0_x2a1p0"}) {
80     EXPECT_EQ(
81         toString(RISCVISAInfo::parseNormalizedArchString(Input).takeError()),
82         "'x' must be followed by a letter");
83   }
84 }
85 
86 TEST(ParseNormalizedArchString, DuplicateExtension) {
87   for (StringRef Input : {"rv64i2p0_a2p0_a1p0"}) {
88     EXPECT_EQ(
89         toString(RISCVISAInfo::parseNormalizedArchString(Input).takeError()),
90         "duplicate extension 'a'");
91   }
92 }
93 
94 TEST(ParseNormalizedArchString, AcceptsValidBaseISAsAndSetsXLen) {
95   auto MaybeRV32I = RISCVISAInfo::parseNormalizedArchString("rv32i2p0");
96   ASSERT_THAT_EXPECTED(MaybeRV32I, Succeeded());
97   RISCVISAInfo &InfoRV32I = **MaybeRV32I;
98   EXPECT_EQ(InfoRV32I.getExtensions().size(), 1UL);
99   EXPECT_TRUE(InfoRV32I.getExtensions().at("i") ==
100               (RISCVISAUtils::ExtensionVersion{2, 0}));
101   EXPECT_EQ(InfoRV32I.getXLen(), 32U);
102 
103   auto MaybeRV32E = RISCVISAInfo::parseNormalizedArchString("rv32e2p0");
104   ASSERT_THAT_EXPECTED(MaybeRV32E, Succeeded());
105   RISCVISAInfo &InfoRV32E = **MaybeRV32E;
106   EXPECT_EQ(InfoRV32E.getExtensions().size(), 1UL);
107   EXPECT_TRUE(InfoRV32E.getExtensions().at("e") ==
108               (RISCVISAUtils::ExtensionVersion{2, 0}));
109   EXPECT_EQ(InfoRV32E.getXLen(), 32U);
110 
111   auto MaybeRV64I = RISCVISAInfo::parseNormalizedArchString("rv64i2p0");
112   ASSERT_THAT_EXPECTED(MaybeRV64I, Succeeded());
113   RISCVISAInfo &InfoRV64I = **MaybeRV64I;
114   EXPECT_EQ(InfoRV64I.getExtensions().size(), 1UL);
115   EXPECT_TRUE(InfoRV64I.getExtensions().at("i") ==
116               (RISCVISAUtils::ExtensionVersion{2, 0}));
117   EXPECT_EQ(InfoRV64I.getXLen(), 64U);
118 
119   auto MaybeRV64E = RISCVISAInfo::parseNormalizedArchString("rv64e2p0");
120   ASSERT_THAT_EXPECTED(MaybeRV64E, Succeeded());
121   RISCVISAInfo &InfoRV64E = **MaybeRV64E;
122   EXPECT_EQ(InfoRV64E.getExtensions().size(), 1UL);
123   EXPECT_TRUE(InfoRV64E.getExtensions().at("e") ==
124               (RISCVISAUtils::ExtensionVersion{2, 0}));
125   EXPECT_EQ(InfoRV64E.getXLen(), 64U);
126 }
127 
128 TEST(ParseNormalizedArchString, AcceptsArbitraryExtensionsAndVersions) {
129   auto MaybeISAInfo = RISCVISAInfo::parseNormalizedArchString(
130       "rv64i5p1_m3p2_zmadeup11p12_sfoo2p0_xbar3p0");
131   ASSERT_THAT_EXPECTED(MaybeISAInfo, Succeeded());
132   RISCVISAInfo &Info = **MaybeISAInfo;
133   EXPECT_EQ(Info.getExtensions().size(), 5UL);
134   EXPECT_TRUE(Info.getExtensions().at("i") ==
135               (RISCVISAUtils::ExtensionVersion{5, 1}));
136   EXPECT_TRUE(Info.getExtensions().at("m") ==
137               (RISCVISAUtils::ExtensionVersion{3, 2}));
138   EXPECT_TRUE(Info.getExtensions().at("zmadeup") ==
139               (RISCVISAUtils::ExtensionVersion{11, 12}));
140   EXPECT_TRUE(Info.getExtensions().at("sfoo") ==
141               (RISCVISAUtils::ExtensionVersion{2, 0}));
142   EXPECT_TRUE(Info.getExtensions().at("xbar") ==
143               (RISCVISAUtils::ExtensionVersion{3, 0}));
144 }
145 
146 TEST(ParseNormalizedArchString, UpdatesFLenMinVLenMaxELen) {
147   auto MaybeISAInfo = RISCVISAInfo::parseNormalizedArchString(
148       "rv64i2p0_d2p0_zvl64b1p0_zve64d1p0");
149   ASSERT_THAT_EXPECTED(MaybeISAInfo, Succeeded());
150   RISCVISAInfo &Info = **MaybeISAInfo;
151   EXPECT_EQ(Info.getXLen(), 64U);
152   EXPECT_EQ(Info.getFLen(), 64U);
153   EXPECT_EQ(Info.getMinVLen(), 64U);
154   EXPECT_EQ(Info.getMaxELen(), 64U);
155   EXPECT_EQ(Info.getMaxELenFp(), 64U);
156 }
157 
158 TEST(ParseNormalizedArchString, AcceptsUnknownMultiletter) {
159   auto MaybeISAInfo = RISCVISAInfo::parseNormalizedArchString(
160       "rv64i2p0_f2p0_d2p0_zicsr2p0_ykk1p0");
161   ASSERT_THAT_EXPECTED(MaybeISAInfo, Succeeded());
162   RISCVISAInfo &Info = **MaybeISAInfo;
163   EXPECT_EQ(Info.toString(), "rv64i2p0_f2p0_d2p0_zicsr2p0_ykk1p0");
164 }
165 
166 TEST(ParseArchString, RejectsInvalidChars) {
167   for (StringRef Input : {"RV32", "rV64", "rv32i2P0", "rv64i2p0_A2p0"}) {
168     EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()),
169               "string may only contain [a-z0-9_]");
170   }
171 }
172 
173 TEST(ParseArchString, RejectsInvalidBaseISA) {
174   for (StringRef Input : {"rv32", "rv64", "rv65i"}) {
175     EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()),
176               "string must begin with rv32{i,e,g}, rv64{i,e,g}, or a supported "
177               "profile name");
178   }
179 
180   for (StringRef Input : {"rv32j", "rv32_i"}) {
181     EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()),
182               "first letter after 'rv32' should be 'e', 'i' or 'g'");
183   }
184 
185   EXPECT_EQ(toString(RISCVISAInfo::parseArchString("rv64k", true).takeError()),
186             "first letter after 'rv64' should be 'e', 'i' or 'g'");
187 }
188 
189 TEST(ParseArchString, RejectsUnsupportedBaseISA) {
190   for (StringRef Input : {"rv128i", "rv128g"}) {
191     EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()),
192               "string must begin with rv32{i,e,g}, rv64{i,e,g}, or a supported "
193               "profile name");
194   }
195 }
196 
197 TEST(ParseArchString, AcceptsSupportedBaseISAsAndSetsXLenAndFLen) {
198   auto MaybeRV32I = RISCVISAInfo::parseArchString("rv32i", true);
199   ASSERT_THAT_EXPECTED(MaybeRV32I, Succeeded());
200   RISCVISAInfo &InfoRV32I = **MaybeRV32I;
201   const auto &ExtsRV32I = InfoRV32I.getExtensions();
202   EXPECT_EQ(ExtsRV32I.size(), 1UL);
203   EXPECT_TRUE(ExtsRV32I.at("i") == (RISCVISAUtils::ExtensionVersion{2, 1}));
204   EXPECT_EQ(InfoRV32I.getXLen(), 32U);
205   EXPECT_EQ(InfoRV32I.getFLen(), 0U);
206   EXPECT_EQ(InfoRV32I.getMinVLen(), 0U);
207   EXPECT_EQ(InfoRV32I.getMaxELen(), 0U);
208   EXPECT_EQ(InfoRV32I.getMaxELenFp(), 0U);
209 
210   auto MaybeRV32E = RISCVISAInfo::parseArchString("rv32e", true);
211   ASSERT_THAT_EXPECTED(MaybeRV32E, Succeeded());
212   RISCVISAInfo &InfoRV32E = **MaybeRV32E;
213   const auto &ExtsRV32E = InfoRV32E.getExtensions();
214   EXPECT_EQ(ExtsRV32E.size(), 1UL);
215   EXPECT_TRUE(ExtsRV32E.at("e") == (RISCVISAUtils::ExtensionVersion{2, 0}));
216   EXPECT_EQ(InfoRV32E.getXLen(), 32U);
217   EXPECT_EQ(InfoRV32E.getFLen(), 0U);
218   EXPECT_EQ(InfoRV32E.getMinVLen(), 0U);
219   EXPECT_EQ(InfoRV32E.getMaxELen(), 0U);
220   EXPECT_EQ(InfoRV32E.getMaxELenFp(), 0U);
221 
222   auto MaybeRV32G = RISCVISAInfo::parseArchString("rv32g", true);
223   ASSERT_THAT_EXPECTED(MaybeRV32G, Succeeded());
224   RISCVISAInfo &InfoRV32G = **MaybeRV32G;
225   const auto &ExtsRV32G = InfoRV32G.getExtensions();
226   EXPECT_EQ(ExtsRV32G.size(), 8UL);
227   EXPECT_TRUE(ExtsRV32G.at("i") == (RISCVISAUtils::ExtensionVersion{2, 1}));
228   EXPECT_TRUE(ExtsRV32G.at("m") == (RISCVISAUtils::ExtensionVersion{2, 0}));
229   EXPECT_TRUE(ExtsRV32G.at("a") == (RISCVISAUtils::ExtensionVersion{2, 1}));
230   EXPECT_TRUE(ExtsRV32G.at("f") == (RISCVISAUtils::ExtensionVersion{2, 2}));
231   EXPECT_TRUE(ExtsRV32G.at("d") == (RISCVISAUtils::ExtensionVersion{2, 2}));
232   EXPECT_TRUE(ExtsRV32G.at("zicsr") == (RISCVISAUtils::ExtensionVersion{2, 0}));
233   EXPECT_TRUE(ExtsRV32G.at("zifencei") ==
234               (RISCVISAUtils::ExtensionVersion{2, 0}));
235   EXPECT_TRUE(ExtsRV32G.at("zmmul") == (RISCVISAUtils::ExtensionVersion{1, 0}));
236   EXPECT_EQ(InfoRV32G.getXLen(), 32U);
237   EXPECT_EQ(InfoRV32G.getFLen(), 64U);
238   EXPECT_EQ(InfoRV32G.getMinVLen(), 0U);
239   EXPECT_EQ(InfoRV32G.getMaxELen(), 0U);
240   EXPECT_EQ(InfoRV32G.getMaxELenFp(), 0U);
241 
242   auto MaybeRV64I = RISCVISAInfo::parseArchString("rv64i", true);
243   ASSERT_THAT_EXPECTED(MaybeRV64I, Succeeded());
244   RISCVISAInfo &InfoRV64I = **MaybeRV64I;
245   const auto &ExtsRV64I = InfoRV64I.getExtensions();
246   EXPECT_EQ(ExtsRV64I.size(), 1UL);
247   EXPECT_TRUE(ExtsRV64I.at("i") == (RISCVISAUtils::ExtensionVersion{2, 1}));
248   EXPECT_EQ(InfoRV64I.getXLen(), 64U);
249   EXPECT_EQ(InfoRV64I.getFLen(), 0U);
250   EXPECT_EQ(InfoRV64I.getMinVLen(), 0U);
251   EXPECT_EQ(InfoRV64I.getMaxELen(), 0U);
252   EXPECT_EQ(InfoRV64I.getMaxELenFp(), 0U);
253 
254   auto MaybeRV64E = RISCVISAInfo::parseArchString("rv64e", true);
255   ASSERT_THAT_EXPECTED(MaybeRV64E, Succeeded());
256   RISCVISAInfo &InfoRV64E = **MaybeRV64E;
257   const auto &ExtsRV64E = InfoRV64E.getExtensions();
258   EXPECT_EQ(ExtsRV64E.size(), 1UL);
259   EXPECT_TRUE(ExtsRV64E.at("e") == (RISCVISAUtils::ExtensionVersion{2, 0}));
260   EXPECT_EQ(InfoRV64E.getXLen(), 64U);
261   EXPECT_EQ(InfoRV64E.getFLen(), 0U);
262   EXPECT_EQ(InfoRV64E.getMinVLen(), 0U);
263   EXPECT_EQ(InfoRV64E.getMaxELen(), 0U);
264   EXPECT_EQ(InfoRV64E.getMaxELenFp(), 0U);
265 
266   auto MaybeRV64G = RISCVISAInfo::parseArchString("rv64g", true);
267   ASSERT_THAT_EXPECTED(MaybeRV64G, Succeeded());
268   RISCVISAInfo &InfoRV64G = **MaybeRV64G;
269   const auto &ExtsRV64G = InfoRV64G.getExtensions();
270   EXPECT_EQ(ExtsRV64G.size(), 8UL);
271   EXPECT_TRUE(ExtsRV64G.at("i") == (RISCVISAUtils::ExtensionVersion{2, 1}));
272   EXPECT_TRUE(ExtsRV64G.at("m") == (RISCVISAUtils::ExtensionVersion{2, 0}));
273   EXPECT_TRUE(ExtsRV64G.at("a") == (RISCVISAUtils::ExtensionVersion{2, 1}));
274   EXPECT_TRUE(ExtsRV64G.at("f") == (RISCVISAUtils::ExtensionVersion{2, 2}));
275   EXPECT_TRUE(ExtsRV64G.at("d") == (RISCVISAUtils::ExtensionVersion{2, 2}));
276   EXPECT_TRUE(ExtsRV64G.at("zicsr") == (RISCVISAUtils::ExtensionVersion{2, 0}));
277   EXPECT_TRUE(ExtsRV64G.at("zifencei") ==
278               (RISCVISAUtils::ExtensionVersion{2, 0}));
279   EXPECT_TRUE(ExtsRV32G.at("zmmul") == (RISCVISAUtils::ExtensionVersion{1, 0}));
280   EXPECT_EQ(InfoRV64G.getXLen(), 64U);
281   EXPECT_EQ(InfoRV64G.getFLen(), 64U);
282   EXPECT_EQ(InfoRV64G.getMinVLen(), 0U);
283   EXPECT_EQ(InfoRV64G.getMaxELen(), 0U);
284   EXPECT_EQ(InfoRV64G.getMaxELenFp(), 0U);
285 
286   auto MaybeRV64GCV = RISCVISAInfo::parseArchString("rv64gcv", true);
287   ASSERT_THAT_EXPECTED(MaybeRV64GCV, Succeeded());
288   RISCVISAInfo &InfoRV64GCV = **MaybeRV64GCV;
289   const auto &ExtsRV64GCV = InfoRV64GCV.getExtensions();
290   EXPECT_EQ(ExtsRV64GCV.size(), 18UL);
291   EXPECT_TRUE(ExtsRV64GCV.at("i") == (RISCVISAUtils::ExtensionVersion{2, 1}));
292   EXPECT_TRUE(ExtsRV64GCV.at("m") == (RISCVISAUtils::ExtensionVersion{2, 0}));
293   EXPECT_TRUE(ExtsRV64GCV.at("a") == (RISCVISAUtils::ExtensionVersion{2, 1}));
294   EXPECT_TRUE(ExtsRV64GCV.at("f") == (RISCVISAUtils::ExtensionVersion{2, 2}));
295   EXPECT_TRUE(ExtsRV64GCV.at("d") == (RISCVISAUtils::ExtensionVersion{2, 2}));
296   EXPECT_TRUE(ExtsRV64GCV.at("c") == (RISCVISAUtils::ExtensionVersion{2, 0}));
297   EXPECT_TRUE(ExtsRV64GCV.at("zicsr") == (RISCVISAUtils::ExtensionVersion{2, 0}));
298   EXPECT_TRUE(ExtsRV64GCV.at("zifencei") ==
299               (RISCVISAUtils::ExtensionVersion{2, 0}));
300   EXPECT_TRUE(ExtsRV32G.at("zmmul") == (RISCVISAUtils::ExtensionVersion{1, 0}));
301   EXPECT_TRUE(ExtsRV64GCV.at("v") == (RISCVISAUtils::ExtensionVersion{1, 0}));
302   EXPECT_TRUE(ExtsRV64GCV.at("zve32x") == (RISCVISAUtils::ExtensionVersion{1, 0}));
303   EXPECT_TRUE(ExtsRV64GCV.at("zve32f") == (RISCVISAUtils::ExtensionVersion{1, 0}));
304   EXPECT_TRUE(ExtsRV64GCV.at("zve64x") == (RISCVISAUtils::ExtensionVersion{1, 0}));
305   EXPECT_TRUE(ExtsRV64GCV.at("zve64f") == (RISCVISAUtils::ExtensionVersion{1, 0}));
306   EXPECT_TRUE(ExtsRV64GCV.at("zve64d") == (RISCVISAUtils::ExtensionVersion{1, 0}));
307   EXPECT_TRUE(ExtsRV64GCV.at("zvl32b") == (RISCVISAUtils::ExtensionVersion{1, 0}));
308   EXPECT_TRUE(ExtsRV64GCV.at("zvl64b") == (RISCVISAUtils::ExtensionVersion{1, 0}));
309   EXPECT_TRUE(ExtsRV64GCV.at("zvl128b") == (RISCVISAUtils::ExtensionVersion{1, 0}));
310   EXPECT_EQ(InfoRV64GCV.getXLen(), 64U);
311   EXPECT_EQ(InfoRV64GCV.getFLen(), 64U);
312   EXPECT_EQ(InfoRV64GCV.getMinVLen(), 128U);
313   EXPECT_EQ(InfoRV64GCV.getMaxELen(), 64U);
314   EXPECT_EQ(InfoRV64GCV.getMaxELenFp(), 64U);
315 }
316 
317 TEST(ParseArchString, RejectsUnrecognizedExtensionNamesByDefault) {
318   EXPECT_EQ(
319       toString(
320           RISCVISAInfo::parseArchString("rv32i_zmadeup", true).takeError()),
321       "unsupported standard user-level extension 'zmadeup'");
322   EXPECT_EQ(
323       toString(
324           RISCVISAInfo::parseArchString("rv64g_smadeup", true).takeError()),
325       "unsupported standard supervisor-level extension 'smadeup'");
326   EXPECT_EQ(
327       toString(
328           RISCVISAInfo::parseArchString("rv64g_xmadeup", true).takeError()),
329       "unsupported non-standard user-level extension 'xmadeup'");
330   EXPECT_EQ(
331       toString(
332           RISCVISAInfo::parseArchString("rv32i_zmadeup1p0", true).takeError()),
333       "unsupported standard user-level extension 'zmadeup'");
334   EXPECT_EQ(
335       toString(
336           RISCVISAInfo::parseArchString("rv64g_smadeup1p0", true).takeError()),
337       "unsupported standard supervisor-level extension 'smadeup'");
338   EXPECT_EQ(
339       toString(
340           RISCVISAInfo::parseArchString("rv64g_xmadeup1p0", true).takeError()),
341       "unsupported non-standard user-level extension 'xmadeup'");
342 }
343 
344 TEST(ParseArchString, IgnoresUnrecognizedExtensionNamesWithIgnoreUnknown) {
345   for (StringRef Input : {"rv32i_zmadeup", "rv64i_smadeup", "rv64i_xmadeup"}) {
346     auto MaybeISAInfo = RISCVISAInfo::parseArchString(Input, true, false, true);
347     ASSERT_THAT_EXPECTED(MaybeISAInfo, Succeeded());
348     RISCVISAInfo &Info = **MaybeISAInfo;
349     const auto &Exts = Info.getExtensions();
350     EXPECT_EQ(Exts.size(), 1UL);
351     EXPECT_TRUE(Exts.at("i") == (RISCVISAUtils::ExtensionVersion{2, 1}));
352   }
353 
354   // Checks that supported extensions aren't incorrectly ignored when a
355   // version is present (an early version of the patch had this mistake).
356   auto MaybeISAInfo =
357       RISCVISAInfo::parseArchString("rv32i_zbc1p0_xmadeup", true, false, true);
358   ASSERT_THAT_EXPECTED(MaybeISAInfo, Succeeded());
359   const auto &Exts = (*MaybeISAInfo)->getExtensions();
360   EXPECT_TRUE(Exts.at("zbc") == (RISCVISAUtils::ExtensionVersion{1, 0}));
361 }
362 
363 TEST(ParseArchString, AcceptsVersionInLongOrShortForm) {
364   for (StringRef Input : {"rv64i2p1"}) {
365     auto MaybeISAInfo = RISCVISAInfo::parseArchString(Input, true);
366     ASSERT_THAT_EXPECTED(MaybeISAInfo, Succeeded());
367     const auto &Exts = (*MaybeISAInfo)->getExtensions();
368     EXPECT_TRUE(Exts.at("i") == (RISCVISAUtils::ExtensionVersion{2, 1}));
369   }
370   for (StringRef Input : {"rv32i_zfinx1", "rv32i_zfinx1p0"}) {
371     auto MaybeISAInfo = RISCVISAInfo::parseArchString(Input, true);
372     ASSERT_THAT_EXPECTED(MaybeISAInfo, Succeeded());
373     const auto &Exts = (*MaybeISAInfo)->getExtensions();
374     EXPECT_TRUE(Exts.at("zfinx") == (RISCVISAUtils::ExtensionVersion{1, 0}));
375   }
376 }
377 
378 TEST(ParseArchString, RejectsUnrecognizedExtensionVersionsByDefault) {
379   EXPECT_EQ(
380       toString(RISCVISAInfo::parseArchString("rv64i2p", true).takeError()),
381       "minor version number missing after 'p' for extension 'i'");
382   EXPECT_EQ(
383       toString(RISCVISAInfo::parseArchString("rv64i1p0", true).takeError()),
384       "unsupported version number 1.0 for extension 'i'");
385   EXPECT_EQ(
386       toString(RISCVISAInfo::parseArchString("rv64i9p9", true).takeError()),
387       "unsupported version number 9.9 for extension 'i'");
388   EXPECT_EQ(
389       toString(RISCVISAInfo::parseArchString("rv32im0p1", true).takeError()),
390       "unsupported version number 0.1 for extension 'm'");
391   EXPECT_EQ(toString(RISCVISAInfo::parseArchString("rv32izifencei10p10", true)
392                          .takeError()),
393             "unsupported version number 10.10 for extension 'zifencei'");
394 }
395 
396 TEST(ParseArchString,
397      UsesDefaultVersionForUnrecognisedBaseISAVersionWithIgnoreUnknown) {
398   for (StringRef Input : {"rv32i0p1", "rv32i99p99", "rv64i0p1", "rv64i99p99"}) {
399     auto MaybeISAInfo = RISCVISAInfo::parseArchString(Input, true, false, true);
400     ASSERT_THAT_EXPECTED(MaybeISAInfo, Succeeded());
401     const auto &Exts = (*MaybeISAInfo)->getExtensions();
402     EXPECT_EQ(Exts.size(), 1UL);
403     EXPECT_TRUE(Exts.at("i") == (RISCVISAUtils::ExtensionVersion{2, 1}));
404   }
405   for (StringRef Input : {"rv32e0p1", "rv32e99p99", "rv64e0p1", "rv64e99p99"}) {
406     auto MaybeISAInfo = RISCVISAInfo::parseArchString(Input, true, false, true);
407     ASSERT_THAT_EXPECTED(MaybeISAInfo, Succeeded());
408     const auto &Exts = (*MaybeISAInfo)->getExtensions();
409     EXPECT_EQ(Exts.size(), 1UL);
410     EXPECT_TRUE(Exts.at("e") == (RISCVISAUtils::ExtensionVersion{2, 0}));
411   }
412 }
413 
414 TEST(ParseArchString,
415      IgnoresExtensionsWithUnrecognizedVersionsWithIgnoreUnknown) {
416   for (StringRef Input : {"rv32im1p1", "rv64i_svnapot10p9", "rv32i_zicsr0p5"}) {
417     auto MaybeISAInfo = RISCVISAInfo::parseArchString(Input, true, false, true);
418     ASSERT_THAT_EXPECTED(MaybeISAInfo, Succeeded());
419     const auto &Exts = (*MaybeISAInfo)->getExtensions();
420     EXPECT_EQ(Exts.size(), 1UL);
421     EXPECT_TRUE(Exts.at("i") == (RISCVISAUtils::ExtensionVersion{2, 1}));
422   }
423 }
424 
425 TEST(ParseArchString, AcceptsUnderscoreSplittingExtensions) {
426   for (StringRef Input : {"rv32imafdczifencei", "rv32i_m_a_f_d_c_zifencei"}) {
427     auto MaybeISAInfo = RISCVISAInfo::parseArchString(Input, true);
428     ASSERT_THAT_EXPECTED(MaybeISAInfo, Succeeded());
429     const auto &Exts = (*MaybeISAInfo)->getExtensions();
430     EXPECT_EQ(Exts.size(), 9UL);
431     EXPECT_EQ(Exts.count("i"), 1U);
432     EXPECT_EQ(Exts.count("m"), 1U);
433     EXPECT_EQ(Exts.count("a"), 1U);
434     EXPECT_EQ(Exts.count("f"), 1U);
435     EXPECT_EQ(Exts.count("d"), 1U);
436     EXPECT_EQ(Exts.count("c"), 1U);
437     EXPECT_EQ(Exts.count("zicsr"), 1U);
438     EXPECT_EQ(Exts.count("zifencei"), 1U);
439     EXPECT_EQ(Exts.count("zmmul"), 1U);
440   }
441 }
442 
443 TEST(ParseArchString, AcceptsRelaxSingleLetterExtensions) {
444   for (StringRef Input :
445        {"rv32imfad", "rv32im_fa_d", "rv32im2p0fad", "rv32i2p1m2p0fad"}) {
446     auto MaybeISAInfo = RISCVISAInfo::parseArchString(Input, true);
447     ASSERT_THAT_EXPECTED(MaybeISAInfo, Succeeded());
448     const auto &Exts = (*MaybeISAInfo)->getExtensions();
449     EXPECT_EQ(Exts.size(), 7UL);
450     EXPECT_EQ(Exts.count("i"), 1U);
451     EXPECT_EQ(Exts.count("m"), 1U);
452     EXPECT_EQ(Exts.count("f"), 1U);
453     EXPECT_EQ(Exts.count("a"), 1U);
454     EXPECT_EQ(Exts.count("d"), 1U);
455     EXPECT_EQ(Exts.count("zicsr"), 1U);
456     EXPECT_EQ(Exts.count("zmmul"), 1U);
457   }
458 }
459 
460 TEST(ParseArchString, AcceptsRelaxMixedLetterExtensions) {
461   for (StringRef Input :
462        {"rv32i_zihintntl_m_a_f_d_svinval", "rv32izihintntl_mafdsvinval",
463         "rv32i_zihintntl_mafd_svinval"}) {
464     auto MaybeISAInfo = RISCVISAInfo::parseArchString(Input, true);
465     ASSERT_THAT_EXPECTED(MaybeISAInfo, Succeeded());
466     const auto &Exts = (*MaybeISAInfo)->getExtensions();
467     EXPECT_EQ(Exts.size(), 9UL);
468     EXPECT_EQ(Exts.count("i"), 1U);
469     EXPECT_EQ(Exts.count("m"), 1U);
470     EXPECT_EQ(Exts.count("a"), 1U);
471     EXPECT_EQ(Exts.count("f"), 1U);
472     EXPECT_EQ(Exts.count("d"), 1U);
473     EXPECT_EQ(Exts.count("zihintntl"), 1U);
474     EXPECT_EQ(Exts.count("svinval"), 1U);
475     EXPECT_EQ(Exts.count("zicsr"), 1U);
476     EXPECT_EQ(Exts.count("zmmul"), 1U);
477   }
478 }
479 
480 TEST(ParseArchString, AcceptsAmbiguousFromRelaxExtensions) {
481   for (StringRef Input : {"rv32i_zba_m", "rv32izba_m", "rv32izba1p0_m2p0"}) {
482     auto MaybeISAInfo = RISCVISAInfo::parseArchString(Input, true);
483     ASSERT_THAT_EXPECTED(MaybeISAInfo, Succeeded());
484     const auto &Exts = (*MaybeISAInfo)->getExtensions();
485     EXPECT_EQ(Exts.size(), 4UL);
486     EXPECT_EQ(Exts.count("i"), 1U);
487     EXPECT_EQ(Exts.count("zba"), 1U);
488     EXPECT_EQ(Exts.count("m"), 1U);
489     EXPECT_EQ(Exts.count("zmmul"), 1U);
490   }
491   for (StringRef Input :
492        {"rv32ia_zba_m", "rv32iazba_m", "rv32ia2p1zba1p0_m2p0"}) {
493     auto MaybeISAInfo = RISCVISAInfo::parseArchString(Input, true);
494     ASSERT_THAT_EXPECTED(MaybeISAInfo, Succeeded());
495     const auto &Exts = (*MaybeISAInfo)->getExtensions();
496     EXPECT_EQ(Exts.size(), 5UL);
497     EXPECT_EQ(Exts.count("i"), 1U);
498     EXPECT_EQ(Exts.count("zba"), 1U);
499     EXPECT_EQ(Exts.count("m"), 1U);
500     EXPECT_EQ(Exts.count("a"), 1U);
501     EXPECT_EQ(Exts.count("zmmul"), 1U);
502   }
503 }
504 
505 TEST(ParseArchString, RejectsRelaxExtensionsNotStartWithEorIorG) {
506   EXPECT_EQ(
507       toString(RISCVISAInfo::parseArchString("rv32zba_im", true).takeError()),
508       "first letter after 'rv32' should be 'e', 'i' or 'g'");
509 }
510 
511 TEST(ParseArchString,
512      RejectsMultiLetterExtensionFollowBySingleLetterExtensions) {
513   for (StringRef Input : {"rv32izbam", "rv32i_zbam"})
514     EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()),
515               "unsupported standard user-level extension 'zbam'");
516   EXPECT_EQ(
517       toString(RISCVISAInfo::parseArchString("rv32izbai_m", true).takeError()),
518       "unsupported standard user-level extension 'zbai'");
519   EXPECT_EQ(
520       toString(RISCVISAInfo::parseArchString("rv32izbaim", true).takeError()),
521       "unsupported standard user-level extension 'zbaim'");
522   EXPECT_EQ(
523       toString(
524           RISCVISAInfo::parseArchString("rv32i_zba1p0m", true).takeError()),
525       "unsupported standard user-level extension 'zba1p0m'");
526 }
527 
528 TEST(ParseArchString, RejectsDoubleOrTrailingUnderscore) {
529   EXPECT_EQ(
530       toString(RISCVISAInfo::parseArchString("rv64i__m", true).takeError()),
531       "extension name missing after separator '_'");
532 
533   for (StringRef Input :
534        {"rv32ezicsr__zifencei", "rv32i_", "rv32izicsr_", "rv64im_"}) {
535     EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()),
536               "extension name missing after separator '_'");
537   }
538 }
539 
540 TEST(ParseArchString, RejectsDuplicateExtensionNames) {
541   EXPECT_EQ(toString(RISCVISAInfo::parseArchString("rv64ii", true).takeError()),
542             "invalid standard user-level extension 'i'");
543   EXPECT_EQ(toString(RISCVISAInfo::parseArchString("rv32ee", true).takeError()),
544             "invalid standard user-level extension 'e'");
545   EXPECT_EQ(
546       toString(RISCVISAInfo::parseArchString("rv64imm", true).takeError()),
547       "duplicated standard user-level extension 'm'");
548   EXPECT_EQ(
549       toString(
550           RISCVISAInfo::parseArchString("rv32i_zicsr_zicsr", true).takeError()),
551       "duplicated standard user-level extension 'zicsr'");
552 }
553 
554 TEST(ParseArchString,
555      RejectsExperimentalExtensionsIfNotEnableExperimentalExtension) {
556   EXPECT_EQ(
557       toString(RISCVISAInfo::parseArchString("rv64iztso", false).takeError()),
558       "requires '-menable-experimental-extensions' for experimental extension "
559       "'ztso'");
560 }
561 
562 TEST(ParseArchString,
563      AcceptsExperimentalExtensionsIfEnableExperimentalExtension) {
564   // Note: If ztso becomes none-experimental, this test will need
565   // updating (and unfortunately, it will still pass). The failure of
566   // RejectsExperimentalExtensionsIfNotEnableExperimentalExtension will
567   // hopefully serve as a reminder to update.
568   auto MaybeISAInfo = RISCVISAInfo::parseArchString("rv64iztso", true, false);
569   ASSERT_THAT_EXPECTED(MaybeISAInfo, Succeeded());
570   const auto &Exts = (*MaybeISAInfo)->getExtensions();
571   EXPECT_EQ(Exts.size(), 2UL);
572   EXPECT_EQ(Exts.count("ztso"), 1U);
573   auto MaybeISAInfo2 = RISCVISAInfo::parseArchString("rv64iztso0p1", true);
574   ASSERT_THAT_EXPECTED(MaybeISAInfo2, Succeeded());
575   const auto &Exts2 = (*MaybeISAInfo2)->getExtensions();
576   EXPECT_EQ(Exts2.size(), 2UL);
577   EXPECT_EQ(Exts2.count("ztso"), 1U);
578 }
579 
580 TEST(ParseArchString,
581      RequiresExplicitVersionNumberForExperimentalExtensionByDefault) {
582   EXPECT_EQ(
583       toString(RISCVISAInfo::parseArchString("rv64iztso", true).takeError()),
584       "experimental extension requires explicit version number `ztso`");
585 }
586 
587 TEST(ParseArchString,
588      AcceptsUnrecognizedVersionIfNotExperimentalExtensionVersionCheck) {
589   auto MaybeISAInfo =
590       RISCVISAInfo::parseArchString("rv64iztso9p9", true, false);
591   ASSERT_THAT_EXPECTED(MaybeISAInfo, Succeeded());
592   const auto &Exts = (*MaybeISAInfo)->getExtensions();
593   EXPECT_EQ(Exts.size(), 2UL);
594   EXPECT_TRUE(Exts.at("ztso") == (RISCVISAUtils::ExtensionVersion{9, 9}));
595 }
596 
597 TEST(ParseArchString, RejectsUnrecognizedVersionForExperimentalExtension) {
598   EXPECT_EQ(
599       toString(RISCVISAInfo::parseArchString("rv64iztso9p9", true).takeError()),
600       "unsupported version number 9.9 for experimental extension 'ztso' "
601       "(this compiler supports 0.1)");
602 }
603 
604 TEST(ParseArchString, RejectsExtensionVersionForG) {
605   for (StringRef Input : {"rv32g1c", "rv64g2p0"}) {
606     EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()),
607               "version not supported for 'g'");
608   }
609 }
610 
611 TEST(ParseArchString, AddsImpliedExtensions) {
612   // Does not attempt to exhaustively test all implications.
613   auto MaybeRV64ID = RISCVISAInfo::parseArchString("rv64id", true);
614   ASSERT_THAT_EXPECTED(MaybeRV64ID, Succeeded());
615   const auto &ExtsRV64ID = (*MaybeRV64ID)->getExtensions();
616   EXPECT_EQ(ExtsRV64ID.size(), 4UL);
617   EXPECT_EQ(ExtsRV64ID.count("i"), 1U);
618   EXPECT_EQ(ExtsRV64ID.count("f"), 1U);
619   EXPECT_EQ(ExtsRV64ID.count("d"), 1U);
620   EXPECT_EQ(ExtsRV64ID.count("zicsr"), 1U);
621 
622   auto MaybeRV32IZKN = RISCVISAInfo::parseArchString("rv64izkn", true);
623   ASSERT_THAT_EXPECTED(MaybeRV32IZKN, Succeeded());
624   const auto &ExtsRV32IZKN = (*MaybeRV32IZKN)->getExtensions();
625   EXPECT_EQ(ExtsRV32IZKN.size(), 8UL);
626   EXPECT_EQ(ExtsRV32IZKN.count("i"), 1U);
627   EXPECT_EQ(ExtsRV32IZKN.count("zbkb"), 1U);
628   EXPECT_EQ(ExtsRV32IZKN.count("zbkc"), 1U);
629   EXPECT_EQ(ExtsRV32IZKN.count("zbkx"), 1U);
630   EXPECT_EQ(ExtsRV32IZKN.count("zkne"), 1U);
631   EXPECT_EQ(ExtsRV32IZKN.count("zknd"), 1U);
632   EXPECT_EQ(ExtsRV32IZKN.count("zknh"), 1U);
633   EXPECT_EQ(ExtsRV32IZKN.count("zkn"), 1U);
634 }
635 
636 TEST(ParseArchString, RejectsConflictingExtensions) {
637   for (StringRef Input : {"rv32ifzfinx", "rv64gzdinx"}) {
638     EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()),
639               "'f' and 'zfinx' extensions are incompatible");
640   }
641 
642   for (StringRef Input : {"rv32idc_zcmp1p0", "rv64idc_zcmp1p0"}) {
643     EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()),
644               "'zcmp' extension is incompatible with 'c' extension when 'd' "
645               "extension is enabled");
646   }
647 
648   for (StringRef Input : {"rv32id_zcd1p0_zcmp1p0", "rv64id_zcd1p0_zcmp1p0"}) {
649     EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()),
650               "'zcmp' extension is incompatible with 'zcd' extension when 'd' "
651               "extension is enabled");
652   }
653 
654   for (StringRef Input : {"rv32idc_zcmt1p0", "rv64idc_zcmt1p0"}) {
655     EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()),
656               "'zcmt' extension is incompatible with 'c' extension when 'd' "
657               "extension is enabled");
658   }
659 
660   for (StringRef Input : {"rv32id_zcd1p0_zcmt1p0", "rv64id_zcd1p0_zcmt1p0"}) {
661     EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()),
662               "'zcmt' extension is incompatible with 'zcd' extension when 'd' "
663               "extension is enabled");
664   }
665 
666   for (StringRef Input : {"rv64if_zcf"}) {
667     EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()),
668               "'zcf' is only supported for 'rv32'");
669   }
670 }
671 
672 TEST(ParseArchString, RejectsUnrecognizedProfileNames) {
673   for (StringRef Input : {"rvi23u99", "rvz23u64", "rva99u32"}) {
674     EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()),
675               "string must begin with rv32{i,e,g}, rv64{i,e,g}, or a supported "
676               "profile name");
677   }
678 }
679 
680 TEST(ParseArchString, RejectsProfilesWithUnseparatedExtraExtensions) {
681   for (StringRef Input : {"rvi20u32m", "rvi20u64c"}) {
682     EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()),
683               "additional extensions must be after separator '_'");
684   }
685 }
686 
687 TEST(ParseArchString, AcceptsBareProfileNames) {
688   auto MaybeRVA20U64 = RISCVISAInfo::parseArchString("rva20u64", true);
689   ASSERT_THAT_EXPECTED(MaybeRVA20U64, Succeeded());
690   const auto &Exts = (*MaybeRVA20U64)->getExtensions();
691   EXPECT_EQ(Exts.size(), 14UL);
692   EXPECT_EQ(Exts.count("i"), 1U);
693   EXPECT_EQ(Exts.count("m"), 1U);
694   EXPECT_EQ(Exts.count("f"), 1U);
695   EXPECT_EQ(Exts.count("a"), 1U);
696   EXPECT_EQ(Exts.count("d"), 1U);
697   EXPECT_EQ(Exts.count("c"), 1U);
698   EXPECT_EQ(Exts.count("za128rs"), 1U);
699   EXPECT_EQ(Exts.count("zicntr"), 1U);
700   EXPECT_EQ(Exts.count("ziccif"), 1U);
701   EXPECT_EQ(Exts.count("zicsr"), 1U);
702   EXPECT_EQ(Exts.count("ziccrse"), 1U);
703   EXPECT_EQ(Exts.count("ziccamoa"), 1U);
704   EXPECT_EQ(Exts.count("zicclsm"), 1U);
705   EXPECT_EQ(Exts.count("zmmul"), 1U);
706 
707   auto MaybeRVA23U64 = RISCVISAInfo::parseArchString("rva23u64", true);
708   ASSERT_THAT_EXPECTED(MaybeRVA23U64, Succeeded());
709   EXPECT_GT((*MaybeRVA23U64)->getExtensions().size(), 13UL);
710 }
711 
712 TEST(ParseArchSTring, AcceptsProfileNamesWithSeparatedAdditionalExtensions) {
713   auto MaybeRVI20U64 = RISCVISAInfo::parseArchString("rvi20u64_m_zba", true);
714   ASSERT_THAT_EXPECTED(MaybeRVI20U64, Succeeded());
715   const auto &Exts = (*MaybeRVI20U64)->getExtensions();
716   EXPECT_EQ(Exts.size(), 4UL);
717   EXPECT_EQ(Exts.count("i"), 1U);
718   EXPECT_EQ(Exts.count("m"), 1U);
719   EXPECT_EQ(Exts.count("zba"), 1U);
720   EXPECT_EQ(Exts.count("zmmul"), 1U);
721 }
722 
723 TEST(ParseArchString,
724      RejectsProfilesWithAdditionalExtensionsGivenAlreadyInProfile) {
725   // This test was added to document the current behaviour. Discussion isn't
726   // believed to have taken place about if this is desirable or not.
727   EXPECT_EQ(
728       toString(
729           RISCVISAInfo::parseArchString("rva20u64_zicntr", true).takeError()),
730       "duplicated standard user-level extension 'zicntr'");
731 }
732 
733 TEST(ParseArchString,
734      RejectsExperimentalProfilesIfEnableExperimentalExtensionsNotSet) {
735   EXPECT_EQ(
736       toString(RISCVISAInfo::parseArchString("rva23u64", false).takeError()),
737       "requires '-menable-experimental-extensions' for profile 'rva23u64'");
738 }
739 
740 TEST(ToFeatures, IIsDroppedAndExperimentalExtensionsArePrefixed) {
741   auto MaybeISAInfo1 =
742       RISCVISAInfo::parseArchString("rv64im_ztso", true, false);
743   ASSERT_THAT_EXPECTED(MaybeISAInfo1, Succeeded());
744   EXPECT_THAT((*MaybeISAInfo1)->toFeatures(),
745               ElementsAre("+m", "+zmmul", "+experimental-ztso"));
746 
747   auto MaybeISAInfo2 =
748       RISCVISAInfo::parseArchString("rv32e_ztso_xventanacondops", true, false);
749   ASSERT_THAT_EXPECTED(MaybeISAInfo2, Succeeded());
750   EXPECT_THAT((*MaybeISAInfo2)->toFeatures(),
751               ElementsAre("+e", "+experimental-ztso", "+xventanacondops"));
752 }
753 
754 TEST(ToFeatures, UnsupportedExtensionsAreDropped) {
755   auto MaybeISAInfo =
756       RISCVISAInfo::parseNormalizedArchString("rv64i2p0_m2p0_xmadeup1p0");
757   ASSERT_THAT_EXPECTED(MaybeISAInfo, Succeeded());
758   EXPECT_THAT((*MaybeISAInfo)->toFeatures(), ElementsAre("+m"));
759 }
760 
761 TEST(ToFeatures, UnsupportedExtensionsAreKeptIfIgnoreUnknownIsFalse) {
762   auto MaybeISAInfo =
763       RISCVISAInfo::parseNormalizedArchString("rv64i2p0_m2p0_xmadeup1p0");
764   ASSERT_THAT_EXPECTED(MaybeISAInfo, Succeeded());
765   EXPECT_THAT((*MaybeISAInfo)->toFeatures(false, false),
766               ElementsAre("+m", "+xmadeup"));
767 }
768 
769 TEST(ToFeatures, AddAllExtensionsAddsNegativeExtensions) {
770   auto MaybeISAInfo = RISCVISAInfo::parseNormalizedArchString("rv64i2p0_m2p0");
771   ASSERT_THAT_EXPECTED(MaybeISAInfo, Succeeded());
772 
773   auto Features = (*MaybeISAInfo)->toFeatures(true);
774   EXPECT_GT(Features.size(), 1UL);
775   EXPECT_EQ(Features.front(), "+m");
776   // Every feature after should be a negative feature
777   for (auto &NegativeExt : llvm::drop_begin(Features))
778     EXPECT_TRUE(NegativeExt.substr(0, 1) == "-");
779 }
780 
781 TEST(OrderedExtensionMap, ExtensionsAreCorrectlyOrdered) {
782   RISCVISAUtils::OrderedExtensionMap Exts;
783   for (auto ExtName : {"y", "l", "m", "c", "i", "xfoo", "xbar", "sfoo", "sbar",
784                        "zmfoo", "zzfoo", "zfinx", "zicsr"})
785     Exts[ExtName] = {1, 0};
786 
787   std::vector<std::string> ExtNames;
788   for (const auto &Ext : Exts)
789     ExtNames.push_back(Ext.first);
790 
791   // FIXME: 'l' and 'y' should be ordered after 'i', 'm', 'c'.
792   EXPECT_THAT(ExtNames,
793               ElementsAre("i", "m", "l", "c", "y", "zicsr", "zmfoo", "zfinx",
794                            "zzfoo", "sbar", "sfoo", "xbar", "xfoo"));
795 }
796 
797 TEST(ParseArchString, ZceImplication) {
798   auto MaybeRV32IZce = RISCVISAInfo::parseArchString("rv32izce", true);
799   ASSERT_THAT_EXPECTED(MaybeRV32IZce, Succeeded());
800   const auto &ExtsRV32IZce = (*MaybeRV32IZce)->getExtensions();
801   EXPECT_EQ(ExtsRV32IZce.size(), 7UL);
802   EXPECT_EQ(ExtsRV32IZce.count("i"), 1U);
803   EXPECT_EQ(ExtsRV32IZce.count("zicsr"), 1U);
804   EXPECT_EQ(ExtsRV32IZce.count("zca"), 1U);
805   EXPECT_EQ(ExtsRV32IZce.count("zcb"), 1U);
806   EXPECT_EQ(ExtsRV32IZce.count("zce"), 1U);
807   EXPECT_EQ(ExtsRV32IZce.count("zcmp"), 1U);
808   EXPECT_EQ(ExtsRV32IZce.count("zcmt"), 1U);
809 
810   auto MaybeRV32IFZce = RISCVISAInfo::parseArchString("rv32ifzce", true);
811   ASSERT_THAT_EXPECTED(MaybeRV32IFZce, Succeeded());
812   const auto &ExtsRV32IFZce = (*MaybeRV32IFZce)->getExtensions();
813   EXPECT_EQ(ExtsRV32IFZce.size(), 9UL);
814   EXPECT_EQ(ExtsRV32IFZce.count("i"), 1U);
815   EXPECT_EQ(ExtsRV32IFZce.count("zicsr"), 1U);
816   EXPECT_EQ(ExtsRV32IFZce.count("f"), 1U);
817   EXPECT_EQ(ExtsRV32IFZce.count("zca"), 1U);
818   EXPECT_EQ(ExtsRV32IFZce.count("zcb"), 1U);
819   EXPECT_EQ(ExtsRV32IFZce.count("zce"), 1U);
820   EXPECT_EQ(ExtsRV32IFZce.count("zcf"), 1U);
821   EXPECT_EQ(ExtsRV32IFZce.count("zcmp"), 1U);
822   EXPECT_EQ(ExtsRV32IFZce.count("zcmt"), 1U);
823 
824   auto MaybeRV32IDZce = RISCVISAInfo::parseArchString("rv32idzce", true);
825   ASSERT_THAT_EXPECTED(MaybeRV32IDZce, Succeeded());
826   const auto &ExtsRV32IDZce = (*MaybeRV32IDZce)->getExtensions();
827   EXPECT_EQ(ExtsRV32IDZce.size(), 10UL);
828   EXPECT_EQ(ExtsRV32IDZce.count("i"), 1U);
829   EXPECT_EQ(ExtsRV32IDZce.count("zicsr"), 1U);
830   EXPECT_EQ(ExtsRV32IDZce.count("f"), 1U);
831   EXPECT_EQ(ExtsRV32IDZce.count("d"), 1U);
832   EXPECT_EQ(ExtsRV32IDZce.count("zca"), 1U);
833   EXPECT_EQ(ExtsRV32IDZce.count("zcb"), 1U);
834   EXPECT_EQ(ExtsRV32IDZce.count("zce"), 1U);
835   EXPECT_EQ(ExtsRV32IDZce.count("zcf"), 1U);
836   EXPECT_EQ(ExtsRV32IDZce.count("zcmp"), 1U);
837   EXPECT_EQ(ExtsRV32IDZce.count("zcmt"), 1U);
838 
839   auto MaybeRV64IZce = RISCVISAInfo::parseArchString("rv64izce", true);
840   ASSERT_THAT_EXPECTED(MaybeRV64IZce, Succeeded());
841   const auto &ExtsRV64IZce = (*MaybeRV64IZce)->getExtensions();
842   EXPECT_EQ(ExtsRV64IZce.size(), 7UL);
843   EXPECT_EQ(ExtsRV64IZce.count("i"), 1U);
844   EXPECT_EQ(ExtsRV64IZce.count("zicsr"), 1U);
845   EXPECT_EQ(ExtsRV64IZce.count("zca"), 1U);
846   EXPECT_EQ(ExtsRV64IZce.count("zcb"), 1U);
847   EXPECT_EQ(ExtsRV64IZce.count("zce"), 1U);
848   EXPECT_EQ(ExtsRV64IZce.count("zcmp"), 1U);
849   EXPECT_EQ(ExtsRV64IZce.count("zcmt"), 1U);
850 
851   auto MaybeRV64IFZce = RISCVISAInfo::parseArchString("rv64ifzce", true);
852   ASSERT_THAT_EXPECTED(MaybeRV64IFZce, Succeeded());
853   const auto &ExtsRV64IFZce = (*MaybeRV64IFZce)->getExtensions();
854   EXPECT_EQ(ExtsRV64IFZce.size(), 8UL);
855   EXPECT_EQ(ExtsRV64IFZce.count("i"), 1U);
856   EXPECT_EQ(ExtsRV64IFZce.count("zicsr"), 1U);
857   EXPECT_EQ(ExtsRV64IFZce.count("f"), 1U);
858   EXPECT_EQ(ExtsRV64IFZce.count("zca"), 1U);
859   EXPECT_EQ(ExtsRV64IFZce.count("zcb"), 1U);
860   EXPECT_EQ(ExtsRV64IFZce.count("zce"), 1U);
861   EXPECT_EQ(ExtsRV64IFZce.count("zcmp"), 1U);
862   EXPECT_EQ(ExtsRV64IFZce.count("zcmt"), 1U);
863 
864   EXPECT_EQ(ExtsRV64IFZce.count("zca"), 1U);
865   EXPECT_EQ(ExtsRV64IFZce.count("zcb"), 1U);
866   EXPECT_EQ(ExtsRV64IFZce.count("zce"), 1U);
867   EXPECT_EQ(ExtsRV64IFZce.count("zcmp"), 1U);
868   EXPECT_EQ(ExtsRV64IFZce.count("zcmt"), 1U);
869 
870   auto MaybeRV64IDZce = RISCVISAInfo::parseArchString("rv64idzce", true);
871   ASSERT_THAT_EXPECTED(MaybeRV64IDZce, Succeeded());
872   const auto &ExtsRV64IDZce = (*MaybeRV64IDZce)->getExtensions();
873   EXPECT_EQ(ExtsRV64IDZce.size(), 9UL);
874   EXPECT_EQ(ExtsRV64IDZce.count("i"), 1U);
875   EXPECT_EQ(ExtsRV64IDZce.count("zicsr"), 1U);
876   EXPECT_EQ(ExtsRV64IDZce.count("f"), 1U);
877   EXPECT_EQ(ExtsRV64IDZce.count("d"), 1U);
878   EXPECT_EQ(ExtsRV64IDZce.count("zca"), 1U);
879   EXPECT_EQ(ExtsRV64IDZce.count("zcb"), 1U);
880   EXPECT_EQ(ExtsRV64IDZce.count("zce"), 1U);
881   EXPECT_EQ(ExtsRV64IDZce.count("zcmp"), 1U);
882   EXPECT_EQ(ExtsRV64IDZce.count("zcmt"), 1U);
883 }
884 
885 TEST(isSupportedExtensionWithVersion, AcceptsSingleExtensionWithVersion) {
886   EXPECT_TRUE(RISCVISAInfo::isSupportedExtensionWithVersion("zbb1p0"));
887   EXPECT_FALSE(RISCVISAInfo::isSupportedExtensionWithVersion("zbb"));
888   EXPECT_FALSE(RISCVISAInfo::isSupportedExtensionWithVersion("zfoo1p0"));
889   EXPECT_FALSE(RISCVISAInfo::isSupportedExtensionWithVersion("zfoo"));
890   EXPECT_FALSE(RISCVISAInfo::isSupportedExtensionWithVersion(""));
891   EXPECT_FALSE(RISCVISAInfo::isSupportedExtensionWithVersion("c2p0zbb1p0"));
892 }
893 
894 TEST(getTargetFeatureForExtension, RetrieveTargetFeatureFromOneExt) {
895   EXPECT_EQ(RISCVISAInfo::getTargetFeatureForExtension("zbb"), "zbb");
896   EXPECT_EQ(RISCVISAInfo::getTargetFeatureForExtension("ztso0p1"),
897             "experimental-ztso");
898   EXPECT_EQ(RISCVISAInfo::getTargetFeatureForExtension("ztso"),
899             "experimental-ztso");
900   EXPECT_EQ(RISCVISAInfo::getTargetFeatureForExtension("zihintntl1234p4321"),
901             "");
902   EXPECT_EQ(RISCVISAInfo::getTargetFeatureForExtension("zfoo"), "");
903   EXPECT_EQ(RISCVISAInfo::getTargetFeatureForExtension(""), "");
904   EXPECT_EQ(RISCVISAInfo::getTargetFeatureForExtension("zbbzihintntl"), "");
905 }
906 
907 TEST(RiscvExtensionsHelp, CheckExtensions) {
908   // clang-format off
909   std::string ExpectedOutput =
910 R"(All available -march extensions for RISC-V
911 
912     Name                 Version   Description
913     i                    2.1       This is a long dummy description
914     e                    2.0
915     m                    2.0
916     a                    2.1
917     f                    2.2
918     d                    2.2
919     c                    2.0
920     b                    1.0
921     v                    1.0
922     h                    1.0
923     zic64b               1.0
924     zicbom               1.0
925     zicbop               1.0
926     zicboz               1.0
927     ziccamoa             1.0
928     ziccif               1.0
929     zicclsm              1.0
930     ziccrse              1.0
931     zicntr               2.0
932     zicond               1.0
933     zicsr                2.0
934     zifencei             2.0
935     zihintntl            1.0
936     zihintpause          2.0
937     zihpm                2.0
938     zimop                1.0
939     zmmul                1.0
940     za128rs              1.0
941     za64rs               1.0
942     zaamo                1.0
943     zabha                1.0
944     zacas                1.0
945     zalrsc               1.0
946     zama16b              1.0
947     zawrs                1.0
948     zfa                  1.0
949     zfh                  1.0
950     zfhmin               1.0
951     zfinx                1.0
952     zdinx                1.0
953     zca                  1.0
954     zcb                  1.0
955     zcd                  1.0
956     zce                  1.0
957     zcf                  1.0
958     zcmop                1.0
959     zcmp                 1.0
960     zcmt                 1.0
961     zba                  1.0
962     zbb                  1.0
963     zbc                  1.0
964     zbkb                 1.0
965     zbkc                 1.0
966     zbkx                 1.0
967     zbs                  1.0
968     zk                   1.0
969     zkn                  1.0
970     zknd                 1.0
971     zkne                 1.0
972     zknh                 1.0
973     zkr                  1.0
974     zks                  1.0
975     zksed                1.0
976     zksh                 1.0
977     zkt                  1.0
978     zvbb                 1.0
979     zvbc                 1.0
980     zve32f               1.0
981     zve32x               1.0
982     zve64d               1.0
983     zve64f               1.0
984     zve64x               1.0
985     zvfh                 1.0
986     zvfhmin              1.0
987     zvkb                 1.0
988     zvkg                 1.0
989     zvkn                 1.0
990     zvknc                1.0
991     zvkned               1.0
992     zvkng                1.0
993     zvknha               1.0
994     zvknhb               1.0
995     zvks                 1.0
996     zvksc                1.0
997     zvksed               1.0
998     zvksg                1.0
999     zvksh                1.0
1000     zvkt                 1.0
1001     zvl1024b             1.0
1002     zvl128b              1.0
1003     zvl16384b            1.0
1004     zvl2048b             1.0
1005     zvl256b              1.0
1006     zvl32768b            1.0
1007     zvl32b               1.0
1008     zvl4096b             1.0
1009     zvl512b              1.0
1010     zvl64b               1.0
1011     zvl65536b            1.0
1012     zvl8192b             1.0
1013     zhinx                1.0
1014     zhinxmin             1.0
1015     shcounterenw         1.0
1016     shgatpa              1.0
1017     shtvala              1.0
1018     shvsatpa             1.0
1019     shvstvala            1.0
1020     shvstvecd            1.0
1021     smaia                1.0
1022     smcdeleg             1.0
1023     smcsrind             1.0
1024     smepmp               1.0
1025     smstateen            1.0
1026     ssaia                1.0
1027     ssccfg               1.0
1028     ssccptr              1.0
1029     sscofpmf             1.0
1030     sscounterenw         1.0
1031     sscsrind             1.0
1032     ssstateen            1.0
1033     ssstrict             1.0
1034     sstc                 1.0
1035     sstvala              1.0
1036     sstvecd              1.0
1037     ssu64xl              1.0
1038     svade                1.0
1039     svadu                1.0
1040     svbare               1.0
1041     svinval              1.0
1042     svnapot              1.0
1043     svpbmt               1.0
1044     xcvalu               1.0
1045     xcvbi                1.0
1046     xcvbitmanip          1.0
1047     xcvelw               1.0
1048     xcvmac               1.0
1049     xcvmem               1.0
1050     xcvsimd              1.0
1051     xsfcease             1.0
1052     xsfvcp               1.0
1053     xsfvfnrclipxfqf      1.0
1054     xsfvfwmaccqqq        1.0
1055     xsfvqmaccdod         1.0
1056     xsfvqmaccqoq         1.0
1057     xsifivecdiscarddlone 1.0
1058     xsifivecflushdlone   1.0
1059     xtheadba             1.0
1060     xtheadbb             1.0
1061     xtheadbs             1.0
1062     xtheadcmo            1.0
1063     xtheadcondmov        1.0
1064     xtheadfmemidx        1.0
1065     xtheadmac            1.0
1066     xtheadmemidx         1.0
1067     xtheadmempair        1.0
1068     xtheadsync           1.0
1069     xtheadvdot           1.0
1070     xventanacondops      1.0
1071 
1072 Experimental extensions
1073     zicfilp              0.4       This is a long dummy description
1074     zicfiss              0.4
1075     zalasr               0.1
1076     zfbfmin              1.0
1077     ztso                 0.1
1078     zvfbfmin             1.0
1079     zvfbfwma             1.0
1080     smmpm                0.8
1081     smnpm                0.8
1082     ssnpm                0.8
1083     sspm                 0.8
1084     ssqosid              1.0
1085     supm                 0.8
1086 
1087 Supported Profiles
1088     rva20s64
1089     rva20u64
1090     rva22s64
1091     rva22u64
1092     rvi20u32
1093     rvi20u64
1094 
1095 Experimental Profiles
1096     rva23s64
1097     rva23u64
1098     rvb23s64
1099     rvb23u64
1100     rvm23u32
1101 
1102 Use -march to specify the target's extension.
1103 For example, clang -march=rv32i_v1p0)";
1104   // clang-format on
1105 
1106   StringMap<StringRef> DummyMap;
1107   DummyMap["i"] = "This is a long dummy description";
1108   DummyMap["experimental-zicfilp"] = "This is a long dummy description";
1109 
1110   outs().flush();
1111   testing::internal::CaptureStdout();
1112   riscvExtensionsHelp(DummyMap);
1113   outs().flush();
1114 
1115   std::string CapturedOutput = testing::internal::GetCapturedStdout();
1116   EXPECT_TRUE([](std::string &Captured, std::string &Expected) {
1117                 return Captured.find(Expected) != std::string::npos;
1118               }(CapturedOutput, ExpectedOutput));
1119 }
1120