1 //===-- RISCVISAInfo.cpp - RISC-V Arch String Parser ------------*- C++ -*-===//
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/Support/RISCVISAInfo.h"
10 #include "llvm/ADT/STLExtras.h"
11 #include "llvm/ADT/SetVector.h"
12 #include "llvm/ADT/StringExtras.h"
13 #include "llvm/ADT/StringRef.h"
14 #include "llvm/Support/Errc.h"
15 #include "llvm/Support/Error.h"
16 #include "llvm/Support/raw_ostream.h"
17 
18 #include <array>
19 #include <atomic>
20 #include <optional>
21 #include <string>
22 #include <vector>
23 
24 using namespace llvm;
25 
26 namespace {
27 /// Represents the major and version number components of a RISC-V extension
28 struct RISCVExtensionVersion {
29   unsigned Major;
30   unsigned Minor;
31 };
32 
33 struct RISCVSupportedExtension {
34   const char *Name;
35   /// Supported version.
36   RISCVExtensionVersion Version;
37 
38   bool operator<(const RISCVSupportedExtension &RHS) const {
39     return StringRef(Name) < StringRef(RHS.Name);
40   }
41 };
42 
43 } // end anonymous namespace
44 
45 static constexpr StringLiteral AllStdExts = "mafdqlcbkjtpvnh";
46 
47 static const char *RISCVGImplications[] = {
48   "i", "m", "a", "f", "d", "zicsr", "zifencei"
49 };
50 
51 // NOTE: This table should be sorted alphabetically by extension name.
52 static const RISCVSupportedExtension SupportedExtensions[] = {
53     {"a", RISCVExtensionVersion{2, 1}},
54     {"c", RISCVExtensionVersion{2, 0}},
55     {"d", RISCVExtensionVersion{2, 2}},
56     {"e", RISCVExtensionVersion{2, 0}},
57     {"f", RISCVExtensionVersion{2, 2}},
58     {"h", RISCVExtensionVersion{1, 0}},
59     {"i", RISCVExtensionVersion{2, 1}},
60     {"m", RISCVExtensionVersion{2, 0}},
61 
62     {"svinval", RISCVExtensionVersion{1, 0}},
63     {"svnapot", RISCVExtensionVersion{1, 0}},
64     {"svpbmt", RISCVExtensionVersion{1, 0}},
65 
66     {"v", RISCVExtensionVersion{1, 0}},
67 
68     // vendor-defined ('X') extensions
69     {"xcvbitmanip", RISCVExtensionVersion{1, 0}},
70     {"xcvmac", RISCVExtensionVersion{1, 0}},
71     {"xsfcie", RISCVExtensionVersion{1, 0}},
72     {"xsfvcp", RISCVExtensionVersion{1, 0}},
73     {"xtheadba", RISCVExtensionVersion{1, 0}},
74     {"xtheadbb", RISCVExtensionVersion{1, 0}},
75     {"xtheadbs", RISCVExtensionVersion{1, 0}},
76     {"xtheadcmo", RISCVExtensionVersion{1, 0}},
77     {"xtheadcondmov", RISCVExtensionVersion{1, 0}},
78     {"xtheadfmemidx", RISCVExtensionVersion{1, 0}},
79     {"xtheadmac", RISCVExtensionVersion{1, 0}},
80     {"xtheadmemidx", RISCVExtensionVersion{1, 0}},
81     {"xtheadmempair", RISCVExtensionVersion{1, 0}},
82     {"xtheadsync", RISCVExtensionVersion{1, 0}},
83     {"xtheadvdot", RISCVExtensionVersion{1, 0}},
84     {"xventanacondops", RISCVExtensionVersion{1, 0}},
85 
86     {"zawrs", RISCVExtensionVersion{1, 0}},
87 
88     {"zba", RISCVExtensionVersion{1, 0}},
89     {"zbb", RISCVExtensionVersion{1, 0}},
90     {"zbc", RISCVExtensionVersion{1, 0}},
91     {"zbkb", RISCVExtensionVersion{1, 0}},
92     {"zbkc", RISCVExtensionVersion{1, 0}},
93     {"zbkx", RISCVExtensionVersion{1, 0}},
94     {"zbs", RISCVExtensionVersion{1, 0}},
95 
96     {"zca", RISCVExtensionVersion{1, 0}},
97     {"zcb", RISCVExtensionVersion{1, 0}},
98     {"zcd", RISCVExtensionVersion{1, 0}},
99     {"zce", RISCVExtensionVersion{1, 0}},
100     {"zcf", RISCVExtensionVersion{1, 0}},
101     {"zcmp", RISCVExtensionVersion{1, 0}},
102     {"zcmt", RISCVExtensionVersion{1, 0}},
103 
104     {"zdinx", RISCVExtensionVersion{1, 0}},
105 
106     {"zfh", RISCVExtensionVersion{1, 0}},
107     {"zfhmin", RISCVExtensionVersion{1, 0}},
108     {"zfinx", RISCVExtensionVersion{1, 0}},
109 
110     {"zhinx", RISCVExtensionVersion{1, 0}},
111     {"zhinxmin", RISCVExtensionVersion{1, 0}},
112 
113     {"zicbom", RISCVExtensionVersion{1, 0}},
114     {"zicbop", RISCVExtensionVersion{1, 0}},
115     {"zicboz", RISCVExtensionVersion{1, 0}},
116     {"zicntr", RISCVExtensionVersion{1, 0}},
117     {"zicsr", RISCVExtensionVersion{2, 0}},
118     {"zifencei", RISCVExtensionVersion{2, 0}},
119     {"zihintpause", RISCVExtensionVersion{2, 0}},
120     {"zihpm", RISCVExtensionVersion{1, 0}},
121 
122     {"zk", RISCVExtensionVersion{1, 0}},
123     {"zkn", RISCVExtensionVersion{1, 0}},
124     {"zknd", RISCVExtensionVersion{1, 0}},
125     {"zkne", RISCVExtensionVersion{1, 0}},
126     {"zknh", RISCVExtensionVersion{1, 0}},
127     {"zkr", RISCVExtensionVersion{1, 0}},
128     {"zks", RISCVExtensionVersion{1, 0}},
129     {"zksed", RISCVExtensionVersion{1, 0}},
130     {"zksh", RISCVExtensionVersion{1, 0}},
131     {"zkt", RISCVExtensionVersion{1, 0}},
132 
133     {"zmmul", RISCVExtensionVersion{1, 0}},
134 
135     {"zve32f", RISCVExtensionVersion{1, 0}},
136     {"zve32x", RISCVExtensionVersion{1, 0}},
137     {"zve64d", RISCVExtensionVersion{1, 0}},
138     {"zve64f", RISCVExtensionVersion{1, 0}},
139     {"zve64x", RISCVExtensionVersion{1, 0}},
140 
141     {"zvfh", RISCVExtensionVersion{1, 0}},
142 
143     {"zvl1024b", RISCVExtensionVersion{1, 0}},
144     {"zvl128b", RISCVExtensionVersion{1, 0}},
145     {"zvl16384b", RISCVExtensionVersion{1, 0}},
146     {"zvl2048b", RISCVExtensionVersion{1, 0}},
147     {"zvl256b", RISCVExtensionVersion{1, 0}},
148     {"zvl32768b", RISCVExtensionVersion{1, 0}},
149     {"zvl32b", RISCVExtensionVersion{1, 0}},
150     {"zvl4096b", RISCVExtensionVersion{1, 0}},
151     {"zvl512b", RISCVExtensionVersion{1, 0}},
152     {"zvl64b", RISCVExtensionVersion{1, 0}},
153     {"zvl65536b", RISCVExtensionVersion{1, 0}},
154     {"zvl8192b", RISCVExtensionVersion{1, 0}},
155 };
156 
157 // NOTE: This table should be sorted alphabetically by extension name.
158 static const RISCVSupportedExtension SupportedExperimentalExtensions[] = {
159     {"smaia", RISCVExtensionVersion{1, 0}},
160     {"ssaia", RISCVExtensionVersion{1, 0}},
161 
162     {"zacas", RISCVExtensionVersion{1, 0}},
163 
164     {"zfa", RISCVExtensionVersion{0, 2}},
165     {"zfbfmin", RISCVExtensionVersion{0, 6}},
166 
167     {"zicond", RISCVExtensionVersion{1, 0}},
168 
169     {"zihintntl", RISCVExtensionVersion{0, 2}},
170 
171     {"ztso", RISCVExtensionVersion{0, 1}},
172 
173     {"zvbb", RISCVExtensionVersion{1, 0}},
174     {"zvbc", RISCVExtensionVersion{1, 0}},
175 
176     {"zvfbfmin", RISCVExtensionVersion{0, 6}},
177     {"zvfbfwma", RISCVExtensionVersion{0, 6}},
178 
179     // vector crypto
180     {"zvkg", RISCVExtensionVersion{1, 0}},
181     {"zvkn", RISCVExtensionVersion{1, 0}},
182     {"zvknc", RISCVExtensionVersion{1, 0}},
183     {"zvkned", RISCVExtensionVersion{1, 0}},
184     {"zvkng", RISCVExtensionVersion{1, 0}},
185     {"zvknha", RISCVExtensionVersion{1, 0}},
186     {"zvknhb", RISCVExtensionVersion{1, 0}},
187     {"zvks", RISCVExtensionVersion{1, 0}},
188     {"zvksc", RISCVExtensionVersion{1, 0}},
189     {"zvksed", RISCVExtensionVersion{1, 0}},
190     {"zvksg", RISCVExtensionVersion{1, 0}},
191     {"zvksh", RISCVExtensionVersion{1, 0}},
192     {"zvkt", RISCVExtensionVersion{1, 0}},
193 };
194 
195 static void verifyTables() {
196 #ifndef NDEBUG
197   static std::atomic<bool> TableChecked(false);
198   if (!TableChecked.load(std::memory_order_relaxed)) {
199     assert(llvm::is_sorted(SupportedExtensions) &&
200            "Extensions are not sorted by name");
201     assert(llvm::is_sorted(SupportedExperimentalExtensions) &&
202            "Experimental extensions are not sorted by name");
203     TableChecked.store(true, std::memory_order_relaxed);
204   }
205 #endif
206 }
207 
208 static bool stripExperimentalPrefix(StringRef &Ext) {
209   return Ext.consume_front("experimental-");
210 }
211 
212 // This function finds the last character that doesn't belong to a version
213 // (e.g. zba1p0 is extension 'zba' of version '1p0'). So the function will
214 // consume [0-9]*p[0-9]* starting from the backward. An extension name will not
215 // end with a digit or the letter 'p', so this function will parse correctly.
216 // NOTE: This function is NOT able to take empty strings or strings that only
217 // have version numbers and no extension name. It assumes the extension name
218 // will be at least more than one character.
219 static size_t findLastNonVersionCharacter(StringRef Ext) {
220   assert(!Ext.empty() &&
221          "Already guarded by if-statement in ::parseArchString");
222 
223   int Pos = Ext.size() - 1;
224   while (Pos > 0 && isDigit(Ext[Pos]))
225     Pos--;
226   if (Pos > 0 && Ext[Pos] == 'p' && isDigit(Ext[Pos - 1])) {
227     Pos--;
228     while (Pos > 0 && isDigit(Ext[Pos]))
229       Pos--;
230   }
231   return Pos;
232 }
233 
234 namespace {
235 struct LessExtName {
236   bool operator()(const RISCVSupportedExtension &LHS, StringRef RHS) {
237     return StringRef(LHS.Name) < RHS;
238   }
239   bool operator()(StringRef LHS, const RISCVSupportedExtension &RHS) {
240     return LHS < StringRef(RHS.Name);
241   }
242 };
243 } // namespace
244 
245 static std::optional<RISCVExtensionVersion>
246 findDefaultVersion(StringRef ExtName) {
247   // Find default version of an extension.
248   // TODO: We might set default version based on profile or ISA spec.
249   for (auto &ExtInfo : {ArrayRef(SupportedExtensions),
250                         ArrayRef(SupportedExperimentalExtensions)}) {
251     auto I = llvm::lower_bound(ExtInfo, ExtName, LessExtName());
252 
253     if (I == ExtInfo.end() || I->Name != ExtName)
254       continue;
255 
256     return I->Version;
257   }
258   return std::nullopt;
259 }
260 
261 void RISCVISAInfo::addExtension(StringRef ExtName, unsigned MajorVersion,
262                                 unsigned MinorVersion) {
263   RISCVExtensionInfo Ext;
264   Ext.MajorVersion = MajorVersion;
265   Ext.MinorVersion = MinorVersion;
266   Exts[ExtName.str()] = Ext;
267 }
268 
269 static StringRef getExtensionTypeDesc(StringRef Ext) {
270   if (Ext.startswith("s"))
271     return "standard supervisor-level extension";
272   if (Ext.startswith("x"))
273     return "non-standard user-level extension";
274   if (Ext.startswith("z"))
275     return "standard user-level extension";
276   return StringRef();
277 }
278 
279 static StringRef getExtensionType(StringRef Ext) {
280   if (Ext.startswith("s"))
281     return "s";
282   if (Ext.startswith("x"))
283     return "x";
284   if (Ext.startswith("z"))
285     return "z";
286   return StringRef();
287 }
288 
289 static std::optional<RISCVExtensionVersion>
290 isExperimentalExtension(StringRef Ext) {
291   auto I =
292       llvm::lower_bound(SupportedExperimentalExtensions, Ext, LessExtName());
293   if (I == std::end(SupportedExperimentalExtensions) || I->Name != Ext)
294     return std::nullopt;
295 
296   return I->Version;
297 }
298 
299 bool RISCVISAInfo::isSupportedExtensionFeature(StringRef Ext) {
300   bool IsExperimental = stripExperimentalPrefix(Ext);
301 
302   ArrayRef<RISCVSupportedExtension> ExtInfo =
303       IsExperimental ? ArrayRef(SupportedExperimentalExtensions)
304                      : ArrayRef(SupportedExtensions);
305 
306   auto I = llvm::lower_bound(ExtInfo, Ext, LessExtName());
307   return I != ExtInfo.end() && I->Name == Ext;
308 }
309 
310 bool RISCVISAInfo::isSupportedExtension(StringRef Ext) {
311   verifyTables();
312 
313   for (auto ExtInfo : {ArrayRef(SupportedExtensions),
314                        ArrayRef(SupportedExperimentalExtensions)}) {
315     auto I = llvm::lower_bound(ExtInfo, Ext, LessExtName());
316     if (I != ExtInfo.end() && I->Name == Ext)
317       return true;
318   }
319 
320   return false;
321 }
322 
323 bool RISCVISAInfo::isSupportedExtension(StringRef Ext, unsigned MajorVersion,
324                                         unsigned MinorVersion) {
325   for (auto ExtInfo : {ArrayRef(SupportedExtensions),
326                        ArrayRef(SupportedExperimentalExtensions)}) {
327     auto Range =
328         std::equal_range(ExtInfo.begin(), ExtInfo.end(), Ext, LessExtName());
329     for (auto I = Range.first, E = Range.second; I != E; ++I)
330       if (I->Version.Major == MajorVersion && I->Version.Minor == MinorVersion)
331         return true;
332   }
333 
334   return false;
335 }
336 
337 bool RISCVISAInfo::hasExtension(StringRef Ext) const {
338   stripExperimentalPrefix(Ext);
339 
340   if (!isSupportedExtension(Ext))
341     return false;
342 
343   return Exts.count(Ext.str()) != 0;
344 }
345 
346 // We rank extensions in the following order:
347 // -Single letter extensions in canonical order.
348 // -Unknown single letter extensions in alphabetical order.
349 // -Multi-letter extensions starting with 'z' sorted by canonical order of
350 //  the second letter then sorted alphabetically.
351 // -Multi-letter extensions starting with 's' in alphabetical order.
352 // -(TODO) Multi-letter extensions starting with 'zxm' in alphabetical order.
353 // -X extensions in alphabetical order.
354 // These flags are used to indicate the category. The first 6 bits store the
355 // single letter extension rank for single letter and multi-letter extensions
356 // starting with 'z'.
357 enum RankFlags {
358   RF_Z_EXTENSION = 1 << 6,
359   RF_S_EXTENSION = 1 << 7,
360   RF_X_EXTENSION = 1 << 8,
361 };
362 
363 // Get the rank for single-letter extension, lower value meaning higher
364 // priority.
365 static unsigned singleLetterExtensionRank(char Ext) {
366   assert(Ext >= 'a' && Ext <= 'z');
367   switch (Ext) {
368   case 'i':
369     return 0;
370   case 'e':
371     return 1;
372   }
373 
374   size_t Pos = AllStdExts.find(Ext);
375   if (Pos != StringRef::npos)
376     return Pos + 2; // Skip 'e' and 'i' from above.
377 
378   // If we got an unknown extension letter, then give it an alphabetical
379   // order, but after all known standard extensions.
380   return 2 + AllStdExts.size() + (Ext - 'a');
381 }
382 
383 // Get the rank for multi-letter extension, lower value meaning higher
384 // priority/order in canonical order.
385 static unsigned getExtensionRank(const std::string &ExtName) {
386   assert(ExtName.size() >= 1);
387   switch (ExtName[0]) {
388   case 's':
389     return RF_S_EXTENSION;
390   case 'z':
391     assert(ExtName.size() >= 2);
392     // `z` extension must be sorted by canonical order of second letter.
393     // e.g. zmx has higher rank than zax.
394     return RF_Z_EXTENSION | singleLetterExtensionRank(ExtName[1]);
395   case 'x':
396     return RF_X_EXTENSION;
397   default:
398     assert(ExtName.size() == 1);
399     return singleLetterExtensionRank(ExtName[0]);
400   }
401 }
402 
403 // Compare function for extension.
404 // Only compare the extension name, ignore version comparison.
405 bool RISCVISAInfo::compareExtension(const std::string &LHS,
406                                     const std::string &RHS) {
407   unsigned LHSRank = getExtensionRank(LHS);
408   unsigned RHSRank = getExtensionRank(RHS);
409 
410   // If the ranks differ, pick the lower rank.
411   if (LHSRank != RHSRank)
412     return LHSRank < RHSRank;
413 
414   // If the rank is same, it must be sorted by lexicographic order.
415   return LHS < RHS;
416 }
417 
418 void RISCVISAInfo::toFeatures(
419     std::vector<StringRef> &Features,
420     llvm::function_ref<StringRef(const Twine &)> StrAlloc,
421     bool AddAllExtensions) const {
422   for (auto const &Ext : Exts) {
423     StringRef ExtName = Ext.first;
424 
425     if (ExtName == "i")
426       continue;
427 
428     if (isExperimentalExtension(ExtName)) {
429       Features.push_back(StrAlloc("+experimental-" + ExtName));
430     } else {
431       Features.push_back(StrAlloc("+" + ExtName));
432     }
433   }
434   if (AddAllExtensions) {
435     for (const RISCVSupportedExtension &Ext : SupportedExtensions) {
436       if (Exts.count(Ext.Name))
437         continue;
438       Features.push_back(StrAlloc(Twine("-") + Ext.Name));
439     }
440 
441     for (const RISCVSupportedExtension &Ext : SupportedExperimentalExtensions) {
442       if (Exts.count(Ext.Name))
443         continue;
444       Features.push_back(StrAlloc(Twine("-experimental-") + Ext.Name));
445     }
446   }
447 }
448 
449 // Extensions may have a version number, and may be separated by
450 // an underscore '_' e.g.: rv32i2_m2.
451 // Version number is divided into major and minor version numbers,
452 // separated by a 'p'. If the minor version is 0 then 'p0' can be
453 // omitted from the version string. E.g., rv32i2p0, rv32i2, rv32i2p1.
454 static Error getExtensionVersion(StringRef Ext, StringRef In, unsigned &Major,
455                                  unsigned &Minor, unsigned &ConsumeLength,
456                                  bool EnableExperimentalExtension,
457                                  bool ExperimentalExtensionVersionCheck) {
458   StringRef MajorStr, MinorStr;
459   Major = 0;
460   Minor = 0;
461   ConsumeLength = 0;
462   MajorStr = In.take_while(isDigit);
463   In = In.substr(MajorStr.size());
464 
465   if (!MajorStr.empty() && In.consume_front("p")) {
466     MinorStr = In.take_while(isDigit);
467     In = In.substr(MajorStr.size() + MinorStr.size() - 1);
468 
469     // Expected 'p' to be followed by minor version number.
470     if (MinorStr.empty()) {
471       return createStringError(
472           errc::invalid_argument,
473           "minor version number missing after 'p' for extension '" + Ext + "'");
474     }
475   }
476 
477   if (!MajorStr.empty() && MajorStr.getAsInteger(10, Major))
478     return createStringError(
479         errc::invalid_argument,
480         "Failed to parse major version number for extension '" + Ext + "'");
481 
482   if (!MinorStr.empty() && MinorStr.getAsInteger(10, Minor))
483     return createStringError(
484         errc::invalid_argument,
485         "Failed to parse minor version number for extension '" + Ext + "'");
486 
487   ConsumeLength = MajorStr.size();
488 
489   if (!MinorStr.empty())
490     ConsumeLength += MinorStr.size() + 1 /*'p'*/;
491 
492   // Expected multi-character extension with version number to have no
493   // subsequent characters (i.e. must either end string or be followed by
494   // an underscore).
495   if (Ext.size() > 1 && In.size()) {
496     std::string Error =
497         "multi-character extensions must be separated by underscores";
498     return createStringError(errc::invalid_argument, Error);
499   }
500 
501   // If experimental extension, require use of current version number number
502   if (auto ExperimentalExtension = isExperimentalExtension(Ext)) {
503     if (!EnableExperimentalExtension) {
504       std::string Error = "requires '-menable-experimental-extensions' for "
505                           "experimental extension '" +
506                           Ext.str() + "'";
507       return createStringError(errc::invalid_argument, Error);
508     }
509 
510     if (ExperimentalExtensionVersionCheck &&
511         (MajorStr.empty() && MinorStr.empty())) {
512       std::string Error =
513           "experimental extension requires explicit version number `" +
514           Ext.str() + "`";
515       return createStringError(errc::invalid_argument, Error);
516     }
517 
518     auto SupportedVers = *ExperimentalExtension;
519     if (ExperimentalExtensionVersionCheck &&
520         (Major != SupportedVers.Major || Minor != SupportedVers.Minor)) {
521       std::string Error = "unsupported version number " + MajorStr.str();
522       if (!MinorStr.empty())
523         Error += "." + MinorStr.str();
524       Error += " for experimental extension '" + Ext.str() +
525                "' (this compiler supports " + utostr(SupportedVers.Major) +
526                "." + utostr(SupportedVers.Minor) + ")";
527       return createStringError(errc::invalid_argument, Error);
528     }
529     return Error::success();
530   }
531 
532   // Exception rule for `g`, we don't have clear version scheme for that on
533   // ISA spec.
534   if (Ext == "g")
535     return Error::success();
536 
537   if (MajorStr.empty() && MinorStr.empty()) {
538     if (auto DefaultVersion = findDefaultVersion(Ext)) {
539       Major = DefaultVersion->Major;
540       Minor = DefaultVersion->Minor;
541     }
542     // No matter found or not, return success, assume other place will
543     // verify.
544     return Error::success();
545   }
546 
547   if (RISCVISAInfo::isSupportedExtension(Ext, Major, Minor))
548     return Error::success();
549 
550   std::string Error = "unsupported version number " + std::string(MajorStr);
551   if (!MinorStr.empty())
552     Error += "." + MinorStr.str();
553   Error += " for extension '" + Ext.str() + "'";
554   return createStringError(errc::invalid_argument, Error);
555 }
556 
557 llvm::Expected<std::unique_ptr<RISCVISAInfo>>
558 RISCVISAInfo::parseFeatures(unsigned XLen,
559                             const std::vector<std::string> &Features) {
560   assert(XLen == 32 || XLen == 64);
561   std::unique_ptr<RISCVISAInfo> ISAInfo(new RISCVISAInfo(XLen));
562 
563   for (auto &Feature : Features) {
564     StringRef ExtName = Feature;
565     bool Experimental = false;
566     assert(ExtName.size() > 1 && (ExtName[0] == '+' || ExtName[0] == '-'));
567     bool Add = ExtName[0] == '+';
568     ExtName = ExtName.drop_front(1); // Drop '+' or '-'
569     Experimental = stripExperimentalPrefix(ExtName);
570     auto ExtensionInfos = Experimental
571                               ? ArrayRef(SupportedExperimentalExtensions)
572                               : ArrayRef(SupportedExtensions);
573     auto ExtensionInfoIterator =
574         llvm::lower_bound(ExtensionInfos, ExtName, LessExtName());
575 
576     // Not all features is related to ISA extension, like `relax` or
577     // `save-restore`, skip those feature.
578     if (ExtensionInfoIterator == ExtensionInfos.end() ||
579         ExtensionInfoIterator->Name != ExtName)
580       continue;
581 
582     if (Add)
583       ISAInfo->addExtension(ExtName, ExtensionInfoIterator->Version.Major,
584                             ExtensionInfoIterator->Version.Minor);
585     else
586       ISAInfo->Exts.erase(ExtName.str());
587   }
588 
589   return RISCVISAInfo::postProcessAndChecking(std::move(ISAInfo));
590 }
591 
592 llvm::Expected<std::unique_ptr<RISCVISAInfo>>
593 RISCVISAInfo::parseNormalizedArchString(StringRef Arch) {
594   if (llvm::any_of(Arch, isupper)) {
595     return createStringError(errc::invalid_argument,
596                              "string must be lowercase");
597   }
598   // Must start with a valid base ISA name.
599   unsigned XLen;
600   if (Arch.startswith("rv32i") || Arch.startswith("rv32e"))
601     XLen = 32;
602   else if (Arch.startswith("rv64i") || Arch.startswith("rv64e"))
603     XLen = 64;
604   else
605     return createStringError(errc::invalid_argument,
606                              "arch string must begin with valid base ISA");
607   std::unique_ptr<RISCVISAInfo> ISAInfo(new RISCVISAInfo(XLen));
608   // Discard rv32/rv64 prefix.
609   Arch = Arch.substr(4);
610 
611   // Each extension is of the form ${name}${major_version}p${minor_version}
612   // and separated by _. Split by _ and then extract the name and version
613   // information for each extension.
614   SmallVector<StringRef, 8> Split;
615   Arch.split(Split, '_');
616   for (StringRef Ext : Split) {
617     StringRef Prefix, MinorVersionStr;
618     std::tie(Prefix, MinorVersionStr) = Ext.rsplit('p');
619     if (MinorVersionStr.empty())
620       return createStringError(errc::invalid_argument,
621                                "extension lacks version in expected format");
622     unsigned MajorVersion, MinorVersion;
623     if (MinorVersionStr.getAsInteger(10, MinorVersion))
624       return createStringError(errc::invalid_argument,
625                                "failed to parse minor version number");
626 
627     // Split Prefix into the extension name and the major version number
628     // (the trailing digits of Prefix).
629     int TrailingDigits = 0;
630     StringRef ExtName = Prefix;
631     while (!ExtName.empty()) {
632       if (!isDigit(ExtName.back()))
633         break;
634       ExtName = ExtName.drop_back(1);
635       TrailingDigits++;
636     }
637     if (!TrailingDigits)
638       return createStringError(errc::invalid_argument,
639                                "extension lacks version in expected format");
640 
641     StringRef MajorVersionStr = Prefix.take_back(TrailingDigits);
642     if (MajorVersionStr.getAsInteger(10, MajorVersion))
643       return createStringError(errc::invalid_argument,
644                                "failed to parse major version number");
645     ISAInfo->addExtension(ExtName, MajorVersion, MinorVersion);
646   }
647   ISAInfo->updateFLen();
648   ISAInfo->updateMinVLen();
649   ISAInfo->updateMaxELen();
650   return std::move(ISAInfo);
651 }
652 
653 llvm::Expected<std::unique_ptr<RISCVISAInfo>>
654 RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension,
655                               bool ExperimentalExtensionVersionCheck,
656                               bool IgnoreUnknown) {
657   // RISC-V ISA strings must be lowercase.
658   if (llvm::any_of(Arch, isupper)) {
659     return createStringError(errc::invalid_argument,
660                              "string must be lowercase");
661   }
662 
663   bool HasRV64 = Arch.startswith("rv64");
664   // ISA string must begin with rv32 or rv64.
665   if (!(Arch.startswith("rv32") || HasRV64) || (Arch.size() < 5)) {
666     return createStringError(
667         errc::invalid_argument,
668         "string must begin with rv32{i,e,g} or rv64{i,e,g}");
669   }
670 
671   unsigned XLen = HasRV64 ? 64 : 32;
672   std::unique_ptr<RISCVISAInfo> ISAInfo(new RISCVISAInfo(XLen));
673 
674   // The canonical order specified in ISA manual.
675   // Ref: Table 22.1 in RISC-V User-Level ISA V2.2
676   StringRef StdExts = AllStdExts;
677   char Baseline = Arch[4];
678 
679   // First letter should be 'e', 'i' or 'g'.
680   switch (Baseline) {
681   default:
682     return createStringError(errc::invalid_argument,
683                              "first letter should be 'e', 'i' or 'g'");
684   case 'e':
685   case 'i':
686     break;
687   case 'g':
688     // g expands to extensions in RISCVGImplications.
689     if (Arch.size() > 5 && isDigit(Arch[5]))
690       return createStringError(errc::invalid_argument,
691                                "version not supported for 'g'");
692     StdExts = StdExts.drop_front(4);
693     break;
694   }
695 
696   if (Arch.back() == '_')
697     return createStringError(errc::invalid_argument,
698                              "extension name missing after separator '_'");
699 
700   // Skip rvxxx
701   StringRef Exts = Arch.substr(5);
702 
703   // Remove multi-letter standard extensions, non-standard extensions and
704   // supervisor-level extensions. They have 'z', 'x', 's' prefixes.
705   // Parse them at the end.
706   // Find the very first occurrence of 's', 'x' or 'z'.
707   StringRef OtherExts;
708   size_t Pos = Exts.find_first_of("zsx");
709   if (Pos != StringRef::npos) {
710     OtherExts = Exts.substr(Pos);
711     Exts = Exts.substr(0, Pos);
712   }
713 
714   unsigned Major, Minor, ConsumeLength;
715   if (Baseline == 'g') {
716     // Versions for g are disallowed, and this was checked for previously.
717     ConsumeLength = 0;
718 
719     // No matter which version is given to `g`, we always set imafd to default
720     // version since the we don't have clear version scheme for that on
721     // ISA spec.
722     for (const auto *Ext : RISCVGImplications) {
723       if (auto Version = findDefaultVersion(Ext))
724         ISAInfo->addExtension(Ext, Version->Major, Version->Minor);
725       else
726         llvm_unreachable("Default extension version not found?");
727     }
728   } else {
729     // Baseline is `i` or `e`
730     if (auto E = getExtensionVersion(
731             StringRef(&Baseline, 1), Exts, Major, Minor, ConsumeLength,
732             EnableExperimentalExtension, ExperimentalExtensionVersionCheck)) {
733       if (!IgnoreUnknown)
734         return std::move(E);
735       // If IgnoreUnknown, then ignore an unrecognised version of the baseline
736       // ISA and just use the default supported version.
737       consumeError(std::move(E));
738       auto Version = findDefaultVersion(StringRef(&Baseline, 1));
739       Major = Version->Major;
740       Minor = Version->Minor;
741     }
742 
743     ISAInfo->addExtension(StringRef(&Baseline, 1), Major, Minor);
744   }
745 
746   // Consume the base ISA version number and any '_' between rvxxx and the
747   // first extension
748   Exts = Exts.drop_front(ConsumeLength);
749   Exts.consume_front("_");
750 
751   auto StdExtsItr = StdExts.begin();
752   auto StdExtsEnd = StdExts.end();
753   auto GoToNextExt = [](StringRef::iterator &I, unsigned ConsumeLength,
754                         StringRef::iterator E) {
755     I += 1 + ConsumeLength;
756     if (I != E && *I == '_')
757       ++I;
758   };
759   for (auto I = Exts.begin(), E = Exts.end(); I != E;) {
760     char C = *I;
761 
762     // Check ISA extensions are specified in the canonical order.
763     while (StdExtsItr != StdExtsEnd && *StdExtsItr != C)
764       ++StdExtsItr;
765 
766     if (StdExtsItr == StdExtsEnd) {
767       // Either c contains a valid extension but it was not given in
768       // canonical order or it is an invalid extension.
769       if (StdExts.contains(C)) {
770         return createStringError(
771             errc::invalid_argument,
772             "standard user-level extension not given in canonical order '%c'",
773             C);
774       }
775 
776       return createStringError(errc::invalid_argument,
777                                "invalid standard user-level extension '%c'", C);
778     }
779 
780     // Move to next char to prevent repeated letter.
781     ++StdExtsItr;
782 
783     StringRef Next;
784     unsigned Major, Minor, ConsumeLength;
785     if (std::next(I) != E)
786       Next = StringRef(std::next(I), E - std::next(I));
787     if (auto E = getExtensionVersion(StringRef(&C, 1), Next, Major, Minor,
788                                      ConsumeLength, EnableExperimentalExtension,
789                                      ExperimentalExtensionVersionCheck)) {
790       if (IgnoreUnknown) {
791         consumeError(std::move(E));
792         GoToNextExt(I, ConsumeLength, Exts.end());
793         continue;
794       }
795       return std::move(E);
796     }
797 
798     // The order is OK, then push it into features.
799     // Currently LLVM supports only "mafdcvh".
800     if (!isSupportedExtension(StringRef(&C, 1))) {
801       if (IgnoreUnknown) {
802         GoToNextExt(I, ConsumeLength, Exts.end());
803         continue;
804       }
805       return createStringError(errc::invalid_argument,
806                                "unsupported standard user-level extension '%c'",
807                                C);
808     }
809     ISAInfo->addExtension(StringRef(&C, 1), Major, Minor);
810 
811     // Consume full extension name and version, including any optional '_'
812     // between this extension and the next
813     GoToNextExt(I, ConsumeLength, Exts.end());
814   }
815 
816   // Handle other types of extensions other than the standard
817   // general purpose and standard user-level extensions.
818   // Parse the ISA string containing non-standard user-level
819   // extensions, standard supervisor-level extensions and
820   // non-standard supervisor-level extensions.
821   // These extensions start with 'z', 's', 'x' prefixes, might have a version
822   // number (major, minor) and are separated by a single underscore '_'. We do
823   // not enforce a canonical order for them.
824   // Set the hardware features for the extensions that are supported.
825 
826   // Multi-letter extensions are seperated by a single underscore
827   // as described in RISC-V User-Level ISA V2.2.
828   SmallVector<StringRef, 8> Split;
829   OtherExts.split(Split, '_');
830 
831   SmallVector<StringRef, 8> AllExts;
832   if (Split.size() > 1 || Split[0] != "") {
833     for (StringRef Ext : Split) {
834       if (Ext.empty())
835         return createStringError(errc::invalid_argument,
836                                  "extension name missing after separator '_'");
837 
838       StringRef Type = getExtensionType(Ext);
839       StringRef Desc = getExtensionTypeDesc(Ext);
840       auto Pos = findLastNonVersionCharacter(Ext) + 1;
841       StringRef Name(Ext.substr(0, Pos));
842       StringRef Vers(Ext.substr(Pos));
843 
844       if (Type.empty()) {
845         if (IgnoreUnknown)
846           continue;
847         return createStringError(errc::invalid_argument,
848                                  "invalid extension prefix '" + Ext + "'");
849       }
850 
851       if (!IgnoreUnknown && Name.size() == Type.size()) {
852         return createStringError(errc::invalid_argument,
853                                  "%s name missing after '%s'",
854                                  Desc.str().c_str(), Type.str().c_str());
855       }
856 
857       unsigned Major, Minor, ConsumeLength;
858       if (auto E = getExtensionVersion(Name, Vers, Major, Minor, ConsumeLength,
859                                        EnableExperimentalExtension,
860                                        ExperimentalExtensionVersionCheck)) {
861         if (IgnoreUnknown) {
862           consumeError(std::move(E));
863           continue;
864         }
865         return std::move(E);
866       }
867 
868       // Check if duplicated extension.
869       if (!IgnoreUnknown && llvm::is_contained(AllExts, Name)) {
870         return createStringError(errc::invalid_argument, "duplicated %s '%s'",
871                                  Desc.str().c_str(), Name.str().c_str());
872       }
873 
874       if (IgnoreUnknown && !isSupportedExtension(Name))
875         continue;
876 
877       ISAInfo->addExtension(Name, Major, Minor);
878       // Extension format is correct, keep parsing the extensions.
879       // TODO: Save Type, Name, Major, Minor to avoid parsing them later.
880       AllExts.push_back(Name);
881     }
882   }
883 
884   for (auto Ext : AllExts) {
885     if (!isSupportedExtension(Ext)) {
886       StringRef Desc = getExtensionTypeDesc(getExtensionType(Ext));
887       return createStringError(errc::invalid_argument, "unsupported %s '%s'",
888                                Desc.str().c_str(), Ext.str().c_str());
889     }
890   }
891 
892   return RISCVISAInfo::postProcessAndChecking(std::move(ISAInfo));
893 }
894 
895 Error RISCVISAInfo::checkDependency() {
896   bool HasC = Exts.count("c") != 0;
897   bool HasF = Exts.count("f") != 0;
898   bool HasZfinx = Exts.count("zfinx") != 0;
899   bool HasVector = Exts.count("zve32x") != 0;
900   bool HasZvl = MinVLen != 0;
901   bool HasZcmt = Exts.count("zcmt") != 0;
902 
903   if (HasF && HasZfinx)
904     return createStringError(errc::invalid_argument,
905                              "'f' and 'zfinx' extensions are incompatible");
906 
907   if (HasZvl && !HasVector)
908     return createStringError(
909         errc::invalid_argument,
910         "'zvl*b' requires 'v' or 'zve*' extension to also be specified");
911 
912   if (Exts.count("zvbb") && !HasVector)
913     return createStringError(
914         errc::invalid_argument,
915         "'zvbb' requires 'v' or 'zve*' extension to also be specified");
916 
917   if (Exts.count("zvbc") && !Exts.count("zve64x"))
918     return createStringError(
919         errc::invalid_argument,
920         "'zvbc' requires 'v' or 'zve64*' extension to also be specified");
921 
922   if ((Exts.count("zvkg") || Exts.count("zvkned") || Exts.count("zvknha") ||
923        Exts.count("zvksed") || Exts.count("zvksh")) &&
924       !HasVector)
925     return createStringError(
926         errc::invalid_argument,
927         "'zvk*' requires 'v' or 'zve*' extension to also be specified");
928 
929   if (Exts.count("zvknhb") && !Exts.count("zve64x"))
930     return createStringError(
931         errc::invalid_argument,
932         "'zvknhb' requires 'v' or 'zve64*' extension to also be specified");
933 
934   if ((HasZcmt || Exts.count("zcmp")) && Exts.count("d") &&
935       (HasC || Exts.count("zcd")))
936     return createStringError(
937         errc::invalid_argument,
938         Twine("'") + (HasZcmt ? "zcmt" : "zcmp") +
939         "' extension is incompatible with '" + (HasC ? "c" : "zcd") +
940         "' extension when 'd' extension is enabled");
941 
942   if (XLen != 32 && Exts.count("zcf"))
943     return createStringError(errc::invalid_argument,
944                              "'zcf' is only supported for 'rv32'");
945 
946   // Additional dependency checks.
947   // TODO: The 'q' extension requires rv64.
948   // TODO: It is illegal to specify 'e' extensions with 'f' and 'd'.
949 
950   return Error::success();
951 }
952 
953 static const char *ImpliedExtsD[] = {"f"};
954 static const char *ImpliedExtsF[] = {"zicsr"};
955 static const char *ImpliedExtsV[] = {"zvl128b", "zve64d"};
956 static const char *ImpliedExtsXTHeadVdot[] = {"v"};
957 static const char *ImpliedExtsXsfvcp[] = {"zve32x"};
958 static const char *ImpliedExtsZacas[] = {"a"};
959 static const char *ImpliedExtsZcb[] = {"zca"};
960 static const char *ImpliedExtsZcd[] = {"zca"};
961 static const char *ImpliedExtsZce[] = {"zcb", "zcmp", "zcmt"};
962 static const char *ImpliedExtsZcf[] = {"zca"};
963 static const char *ImpliedExtsZcmp[] = {"zca"};
964 static const char *ImpliedExtsZcmt[] = {"zca"};
965 static const char *ImpliedExtsZdinx[] = {"zfinx"};
966 static const char *ImpliedExtsZfa[] = {"f"};
967 static const char *ImpliedExtsZfbfmin[] = {"f"};
968 static const char *ImpliedExtsZfh[] = {"f"};
969 static const char *ImpliedExtsZfhmin[] = {"f"};
970 static const char *ImpliedExtsZfinx[] = {"zicsr"};
971 static const char *ImpliedExtsZhinx[] = {"zfinx"};
972 static const char *ImpliedExtsZhinxmin[] = {"zfinx"};
973 static const char *ImpliedExtsZicntr[] = {"zicsr"};
974 static const char *ImpliedExtsZihpm[] = {"zicsr"};
975 static const char *ImpliedExtsZk[] = {"zkn", "zkt", "zkr"};
976 static const char *ImpliedExtsZkn[] = {"zbkb", "zbkc", "zbkx",
977                                        "zkne", "zknd", "zknh"};
978 static const char *ImpliedExtsZks[] = {"zbkb", "zbkc", "zbkx", "zksed", "zksh"};
979 static const char *ImpliedExtsZve32f[] = {"zve32x", "f"};
980 static const char *ImpliedExtsZve32x[] = {"zvl32b", "zicsr"};
981 static const char *ImpliedExtsZve64d[] = {"zve64f", "d"};
982 static const char *ImpliedExtsZve64f[] = {"zve64x", "zve32f"};
983 static const char *ImpliedExtsZve64x[] = {"zve32x", "zvl64b"};
984 static const char *ImpliedExtsZvfbfmin[] = {"zve32f"};
985 static const char *ImpliedExtsZvfbfwma[] = {"zve32f"};
986 static const char *ImpliedExtsZvfh[] = {"zve32f", "zfhmin"};
987 static const char *ImpliedExtsZvkn[] = {"zvbb", "zvkned", "zvknhb", "zvkt"};
988 static const char *ImpliedExtsZvknc[] = {"zvbc", "zvkn"};
989 static const char *ImpliedExtsZvkng[] = {"zvkg", "zvkn"};
990 static const char *ImpliedExtsZvknhb[] = {"zvknha"};
991 static const char *ImpliedExtsZvks[] = {"zvbb", "zvksed", "zvksh", "zvkt"};
992 static const char *ImpliedExtsZvksc[] = {"zvbc", "zvks"};
993 static const char *ImpliedExtsZvksg[] = {"zvkg", "zvks"};
994 static const char *ImpliedExtsZvl1024b[] = {"zvl512b"};
995 static const char *ImpliedExtsZvl128b[] = {"zvl64b"};
996 static const char *ImpliedExtsZvl16384b[] = {"zvl8192b"};
997 static const char *ImpliedExtsZvl2048b[] = {"zvl1024b"};
998 static const char *ImpliedExtsZvl256b[] = {"zvl128b"};
999 static const char *ImpliedExtsZvl32768b[] = {"zvl16384b"};
1000 static const char *ImpliedExtsZvl4096b[] = {"zvl2048b"};
1001 static const char *ImpliedExtsZvl512b[] = {"zvl256b"};
1002 static const char *ImpliedExtsZvl64b[] = {"zvl32b"};
1003 static const char *ImpliedExtsZvl65536b[] = {"zvl32768b"};
1004 static const char *ImpliedExtsZvl8192b[] = {"zvl4096b"};
1005 
1006 struct ImpliedExtsEntry {
1007   StringLiteral Name;
1008   ArrayRef<const char *> Exts;
1009 
1010   bool operator<(const ImpliedExtsEntry &Other) const {
1011     return Name < Other.Name;
1012   }
1013 
1014   bool operator<(StringRef Other) const { return Name < Other; }
1015 };
1016 
1017 // Note: The table needs to be sorted by name.
1018 static constexpr ImpliedExtsEntry ImpliedExts[] = {
1019     {{"d"}, {ImpliedExtsD}},
1020     {{"f"}, {ImpliedExtsF}},
1021     {{"v"}, {ImpliedExtsV}},
1022     {{"xsfvcp"}, {ImpliedExtsXsfvcp}},
1023     {{"xtheadvdot"}, {ImpliedExtsXTHeadVdot}},
1024     {{"zacas"}, {ImpliedExtsZacas}},
1025     {{"zcb"}, {ImpliedExtsZcb}},
1026     {{"zcd"}, {ImpliedExtsZcd}},
1027     {{"zce"}, {ImpliedExtsZce}},
1028     {{"zcf"}, {ImpliedExtsZcf}},
1029     {{"zcmp"}, {ImpliedExtsZcmp}},
1030     {{"zcmt"}, {ImpliedExtsZcmt}},
1031     {{"zdinx"}, {ImpliedExtsZdinx}},
1032     {{"zfa"}, {ImpliedExtsZfa}},
1033     {{"zfbfmin"}, {ImpliedExtsZfbfmin}},
1034     {{"zfh"}, {ImpliedExtsZfh}},
1035     {{"zfhmin"}, {ImpliedExtsZfhmin}},
1036     {{"zfinx"}, {ImpliedExtsZfinx}},
1037     {{"zhinx"}, {ImpliedExtsZhinx}},
1038     {{"zhinxmin"}, {ImpliedExtsZhinxmin}},
1039     {{"zicntr"}, {ImpliedExtsZicntr}},
1040     {{"zihpm"}, {ImpliedExtsZihpm}},
1041     {{"zk"}, {ImpliedExtsZk}},
1042     {{"zkn"}, {ImpliedExtsZkn}},
1043     {{"zks"}, {ImpliedExtsZks}},
1044     {{"zve32f"}, {ImpliedExtsZve32f}},
1045     {{"zve32x"}, {ImpliedExtsZve32x}},
1046     {{"zve64d"}, {ImpliedExtsZve64d}},
1047     {{"zve64f"}, {ImpliedExtsZve64f}},
1048     {{"zve64x"}, {ImpliedExtsZve64x}},
1049     {{"zvfbfmin"}, {ImpliedExtsZvfbfmin}},
1050     {{"zvfbfwma"}, {ImpliedExtsZvfbfwma}},
1051     {{"zvfh"}, {ImpliedExtsZvfh}},
1052     {{"zvkn"}, {ImpliedExtsZvkn}},
1053     {{"zvknc"}, {ImpliedExtsZvknc}},
1054     {{"zvkng"}, {ImpliedExtsZvkng}},
1055     {{"zvknhb"}, {ImpliedExtsZvknhb}},
1056     {{"zvks"}, {ImpliedExtsZvks}},
1057     {{"zvksc"}, {ImpliedExtsZvksc}},
1058     {{"zvksg"}, {ImpliedExtsZvksg}},
1059     {{"zvl1024b"}, {ImpliedExtsZvl1024b}},
1060     {{"zvl128b"}, {ImpliedExtsZvl128b}},
1061     {{"zvl16384b"}, {ImpliedExtsZvl16384b}},
1062     {{"zvl2048b"}, {ImpliedExtsZvl2048b}},
1063     {{"zvl256b"}, {ImpliedExtsZvl256b}},
1064     {{"zvl32768b"}, {ImpliedExtsZvl32768b}},
1065     {{"zvl4096b"}, {ImpliedExtsZvl4096b}},
1066     {{"zvl512b"}, {ImpliedExtsZvl512b}},
1067     {{"zvl64b"}, {ImpliedExtsZvl64b}},
1068     {{"zvl65536b"}, {ImpliedExtsZvl65536b}},
1069     {{"zvl8192b"}, {ImpliedExtsZvl8192b}},
1070 };
1071 
1072 void RISCVISAInfo::updateImplication() {
1073   bool HasE = Exts.count("e") != 0;
1074   bool HasI = Exts.count("i") != 0;
1075 
1076   // If not in e extension and i extension does not exist, i extension is
1077   // implied
1078   if (!HasE && !HasI) {
1079     auto Version = findDefaultVersion("i");
1080     addExtension("i", Version->Major, Version->Minor);
1081   }
1082 
1083   assert(llvm::is_sorted(ImpliedExts) && "Table not sorted by Name");
1084 
1085   // This loop may execute over 1 iteration since implication can be layered
1086   // Exits loop if no more implication is applied
1087   SmallSetVector<StringRef, 16> WorkList;
1088   for (auto const &Ext : Exts)
1089     WorkList.insert(Ext.first);
1090 
1091   while (!WorkList.empty()) {
1092     StringRef ExtName = WorkList.pop_back_val();
1093     auto I = llvm::lower_bound(ImpliedExts, ExtName);
1094     if (I != std::end(ImpliedExts) && I->Name == ExtName) {
1095       for (const char *ImpliedExt : I->Exts) {
1096         if (WorkList.count(ImpliedExt))
1097           continue;
1098         if (Exts.count(ImpliedExt))
1099           continue;
1100         auto Version = findDefaultVersion(ImpliedExt);
1101         addExtension(ImpliedExt, Version->Major, Version->Minor);
1102         WorkList.insert(ImpliedExt);
1103       }
1104     }
1105   }
1106 
1107   // Add Zcf if Zce and F are enabled on RV32.
1108   if (XLen == 32 && Exts.count("zce") && Exts.count("f") &&
1109       !Exts.count("zcf")) {
1110     auto Version = findDefaultVersion("zcf");
1111     addExtension("zcf", Version->Major, Version->Minor);
1112   }
1113 }
1114 
1115 struct CombinedExtsEntry {
1116   StringLiteral CombineExt;
1117   ArrayRef<const char *> RequiredExts;
1118 };
1119 
1120 static constexpr CombinedExtsEntry CombineIntoExts[] = {
1121     {{"zk"}, {ImpliedExtsZk}},
1122     {{"zkn"}, {ImpliedExtsZkn}},
1123     {{"zks"}, {ImpliedExtsZks}},
1124     {{"zvkn"}, {ImpliedExtsZvkn}},
1125     {{"zvknc"}, {ImpliedExtsZvknc}},
1126     {{"zvkng"}, {ImpliedExtsZvkng}},
1127     {{"zvks"}, {ImpliedExtsZvks}},
1128     {{"zvksc"}, {ImpliedExtsZvksc}},
1129     {{"zvksg"}, {ImpliedExtsZvksg}},
1130 };
1131 
1132 void RISCVISAInfo::updateCombination() {
1133   bool IsNewCombine = false;
1134   do {
1135     IsNewCombine = false;
1136     for (CombinedExtsEntry CombineIntoExt : CombineIntoExts) {
1137       auto CombineExt = CombineIntoExt.CombineExt;
1138       auto RequiredExts = CombineIntoExt.RequiredExts;
1139       if (hasExtension(CombineExt))
1140         continue;
1141       bool IsAllRequiredFeatureExist = true;
1142       for (const char *Ext : RequiredExts)
1143         IsAllRequiredFeatureExist &= hasExtension(Ext);
1144       if (IsAllRequiredFeatureExist) {
1145         auto Version = findDefaultVersion(CombineExt);
1146         addExtension(CombineExt, Version->Major, Version->Minor);
1147         IsNewCombine = true;
1148       }
1149     }
1150   } while (IsNewCombine);
1151 }
1152 
1153 void RISCVISAInfo::updateFLen() {
1154   FLen = 0;
1155   // TODO: Handle q extension.
1156   if (Exts.count("d"))
1157     FLen = 64;
1158   else if (Exts.count("f"))
1159     FLen = 32;
1160 }
1161 
1162 void RISCVISAInfo::updateMinVLen() {
1163   for (auto const &Ext : Exts) {
1164     StringRef ExtName = Ext.first;
1165     bool IsZvlExt = ExtName.consume_front("zvl") && ExtName.consume_back("b");
1166     if (IsZvlExt) {
1167       unsigned ZvlLen;
1168       if (!ExtName.getAsInteger(10, ZvlLen))
1169         MinVLen = std::max(MinVLen, ZvlLen);
1170     }
1171   }
1172 }
1173 
1174 void RISCVISAInfo::updateMaxELen() {
1175   // handles EEW restriction by sub-extension zve
1176   for (auto const &Ext : Exts) {
1177     StringRef ExtName = Ext.first;
1178     bool IsZveExt = ExtName.consume_front("zve");
1179     if (IsZveExt) {
1180       if (ExtName.back() == 'f')
1181         MaxELenFp = std::max(MaxELenFp, 32u);
1182       if (ExtName.back() == 'd')
1183         MaxELenFp = std::max(MaxELenFp, 64u);
1184       ExtName = ExtName.drop_back();
1185       unsigned ZveELen;
1186       ExtName.getAsInteger(10, ZveELen);
1187       MaxELen = std::max(MaxELen, ZveELen);
1188     }
1189   }
1190 }
1191 
1192 std::string RISCVISAInfo::toString() const {
1193   std::string Buffer;
1194   raw_string_ostream Arch(Buffer);
1195 
1196   Arch << "rv" << XLen;
1197 
1198   ListSeparator LS("_");
1199   for (auto const &Ext : Exts) {
1200     StringRef ExtName = Ext.first;
1201     auto ExtInfo = Ext.second;
1202     Arch << LS << ExtName;
1203     Arch << ExtInfo.MajorVersion << "p" << ExtInfo.MinorVersion;
1204   }
1205 
1206   return Arch.str();
1207 }
1208 
1209 std::vector<std::string> RISCVISAInfo::toFeatureVector() const {
1210   std::vector<std::string> FeatureVector;
1211   for (auto const &Ext : Exts) {
1212     std::string ExtName = Ext.first;
1213     if (ExtName == "i") // i is not recognized in clang -cc1
1214       continue;
1215     if (!isSupportedExtension(ExtName))
1216       continue;
1217     std::string Feature = isExperimentalExtension(ExtName)
1218                               ? "+experimental-" + ExtName
1219                               : "+" + ExtName;
1220     FeatureVector.push_back(Feature);
1221   }
1222   return FeatureVector;
1223 }
1224 
1225 llvm::Expected<std::unique_ptr<RISCVISAInfo>>
1226 RISCVISAInfo::postProcessAndChecking(std::unique_ptr<RISCVISAInfo> &&ISAInfo) {
1227   ISAInfo->updateImplication();
1228   ISAInfo->updateCombination();
1229   ISAInfo->updateFLen();
1230   ISAInfo->updateMinVLen();
1231   ISAInfo->updateMaxELen();
1232 
1233   if (Error Result = ISAInfo->checkDependency())
1234     return std::move(Result);
1235   return std::move(ISAInfo);
1236 }
1237 
1238 StringRef RISCVISAInfo::computeDefaultABI() const {
1239   if (XLen == 32) {
1240     if (hasExtension("d"))
1241       return "ilp32d";
1242     if (hasExtension("e"))
1243       return "ilp32e";
1244     return "ilp32";
1245   } else if (XLen == 64) {
1246     if (hasExtension("d"))
1247       return "lp64d";
1248     if (hasExtension("e"))
1249       return "lp64e";
1250     return "lp64";
1251   }
1252   llvm_unreachable("Invalid XLEN");
1253 }
1254