1 //===-- RISCVISAInfo.cpp - RISCV Arch String Parser --------------===//
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/None.h"
11 #include "llvm/ADT/STLExtras.h"
12 #include "llvm/ADT/SetVector.h"
13 #include "llvm/ADT/StringExtras.h"
14 #include "llvm/ADT/StringRef.h"
15 #include "llvm/Support/Errc.h"
16 #include "llvm/Support/Error.h"
17 #include "llvm/Support/raw_ostream.h"
18 
19 #include <array>
20 #include <string>
21 #include <vector>
22 
23 using namespace llvm;
24 
25 namespace {
26 /// Represents the major and version number components of a RISC-V extension
27 struct RISCVExtensionVersion {
28   unsigned Major;
29   unsigned Minor;
30 };
31 
32 struct RISCVSupportedExtension {
33   const char *Name;
34   /// Supported version.
35   RISCVExtensionVersion Version;
36 };
37 
38 } // end anonymous namespace
39 
40 static constexpr StringLiteral AllStdExts = "mafdqlcbkjtpvn";
41 
42 static const RISCVSupportedExtension SupportedExtensions[] = {
43     {"i", RISCVExtensionVersion{2, 0}},
44     {"e", RISCVExtensionVersion{1, 9}},
45     {"m", RISCVExtensionVersion{2, 0}},
46     {"a", RISCVExtensionVersion{2, 0}},
47     {"f", RISCVExtensionVersion{2, 0}},
48     {"d", RISCVExtensionVersion{2, 0}},
49     {"c", RISCVExtensionVersion{2, 0}},
50 
51     {"zihintpause", RISCVExtensionVersion{2, 0}},
52 
53     {"zfhmin", RISCVExtensionVersion{1, 0}},
54     {"zfh", RISCVExtensionVersion{1, 0}},
55 
56     {"zfinx", RISCVExtensionVersion{1, 0}},
57     {"zdinx", RISCVExtensionVersion{1, 0}},
58     {"zhinxmin", RISCVExtensionVersion{1, 0}},
59     {"zhinx", RISCVExtensionVersion{1, 0}},
60 
61     {"zba", RISCVExtensionVersion{1, 0}},
62     {"zbb", RISCVExtensionVersion{1, 0}},
63     {"zbc", RISCVExtensionVersion{1, 0}},
64     {"zbs", RISCVExtensionVersion{1, 0}},
65 
66     {"zbkb", RISCVExtensionVersion{1, 0}},
67     {"zbkc", RISCVExtensionVersion{1, 0}},
68     {"zbkx", RISCVExtensionVersion{1, 0}},
69     {"zknd", RISCVExtensionVersion{1, 0}},
70     {"zkne", RISCVExtensionVersion{1, 0}},
71     {"zknh", RISCVExtensionVersion{1, 0}},
72     {"zksed", RISCVExtensionVersion{1, 0}},
73     {"zksh", RISCVExtensionVersion{1, 0}},
74     {"zkr", RISCVExtensionVersion{1, 0}},
75     {"zkn", RISCVExtensionVersion{1, 0}},
76     {"zks", RISCVExtensionVersion{1, 0}},
77     {"zkt", RISCVExtensionVersion{1, 0}},
78     {"zk", RISCVExtensionVersion{1, 0}},
79 
80     {"zmmul", RISCVExtensionVersion{1, 0}},
81 
82     {"v", RISCVExtensionVersion{1, 0}},
83     {"zvl32b", RISCVExtensionVersion{1, 0}},
84     {"zvl64b", RISCVExtensionVersion{1, 0}},
85     {"zvl128b", RISCVExtensionVersion{1, 0}},
86     {"zvl256b", RISCVExtensionVersion{1, 0}},
87     {"zvl512b", RISCVExtensionVersion{1, 0}},
88     {"zvl1024b", RISCVExtensionVersion{1, 0}},
89     {"zvl2048b", RISCVExtensionVersion{1, 0}},
90     {"zvl4096b", RISCVExtensionVersion{1, 0}},
91     {"zvl8192b", RISCVExtensionVersion{1, 0}},
92     {"zvl16384b", RISCVExtensionVersion{1, 0}},
93     {"zvl32768b", RISCVExtensionVersion{1, 0}},
94     {"zvl65536b", RISCVExtensionVersion{1, 0}},
95     {"zve32x", RISCVExtensionVersion{1, 0}},
96     {"zve32f", RISCVExtensionVersion{1, 0}},
97     {"zve64x", RISCVExtensionVersion{1, 0}},
98     {"zve64f", RISCVExtensionVersion{1, 0}},
99     {"zve64d", RISCVExtensionVersion{1, 0}},
100 
101     {"zicbom", RISCVExtensionVersion{1, 0}},
102     {"zicboz", RISCVExtensionVersion{1, 0}},
103     {"zicbop", RISCVExtensionVersion{1, 0}},
104 };
105 
106 static const RISCVSupportedExtension SupportedExperimentalExtensions[] = {
107     {"zbe", RISCVExtensionVersion{0, 93}},
108     {"zbf", RISCVExtensionVersion{0, 93}},
109     {"zbm", RISCVExtensionVersion{0, 93}},
110     {"zbp", RISCVExtensionVersion{0, 93}},
111     {"zbr", RISCVExtensionVersion{0, 93}},
112     {"zbt", RISCVExtensionVersion{0, 93}},
113     {"zvfh", RISCVExtensionVersion{0, 1}},
114 };
115 
116 static bool stripExperimentalPrefix(StringRef &Ext) {
117   return Ext.consume_front("experimental-");
118 }
119 
120 // This function finds the first character that doesn't belong to a version
121 // (e.g. zbe0p93 is extension 'zbe' of version '0p93'). So the function will
122 // consume [0-9]*p[0-9]* starting from the backward. An extension name will not
123 // end with a digit or the letter 'p', so this function will parse correctly.
124 // NOTE: This function is NOT able to take empty strings or strings that only
125 // have version numbers and no extension name. It assumes the extension name
126 // will be at least more than one character.
127 static size_t findFirstNonVersionCharacter(StringRef Ext) {
128    assert(!Ext.empty() &&
129           "Already guarded by if-statement in ::parseArchString");
130 
131   int Pos = Ext.size() - 1;
132   while (Pos > 0 && isDigit(Ext[Pos]))
133     Pos--;
134   if (Pos > 0 && Ext[Pos] == 'p' && isDigit(Ext[Pos - 1])) {
135     Pos--;
136     while (Pos > 0 && isDigit(Ext[Pos]))
137       Pos--;
138   }
139   return Pos;
140 }
141 
142 struct FindByName {
143   FindByName(StringRef Ext) : Ext(Ext){};
144   StringRef Ext;
145   bool operator()(const RISCVSupportedExtension &ExtInfo) {
146     return ExtInfo.Name == Ext;
147   }
148 };
149 
150 static Optional<RISCVExtensionVersion> findDefaultVersion(StringRef ExtName) {
151   // Find default version of an extension.
152   // TODO: We might set default version based on profile or ISA spec.
153   for (auto &ExtInfo : {makeArrayRef(SupportedExtensions),
154                         makeArrayRef(SupportedExperimentalExtensions)}) {
155     auto ExtensionInfoIterator = llvm::find_if(ExtInfo, FindByName(ExtName));
156 
157     if (ExtensionInfoIterator == ExtInfo.end()) {
158       continue;
159     }
160     return ExtensionInfoIterator->Version;
161   }
162   return None;
163 }
164 
165 void RISCVISAInfo::addExtension(StringRef ExtName, unsigned MajorVersion,
166                                 unsigned MinorVersion) {
167   RISCVExtensionInfo Ext;
168   Ext.ExtName = ExtName.str();
169   Ext.MajorVersion = MajorVersion;
170   Ext.MinorVersion = MinorVersion;
171   Exts[ExtName.str()] = Ext;
172 }
173 
174 static StringRef getExtensionTypeDesc(StringRef Ext) {
175   if (Ext.startswith("sx"))
176     return "non-standard supervisor-level extension";
177   if (Ext.startswith("s"))
178     return "standard supervisor-level extension";
179   if (Ext.startswith("x"))
180     return "non-standard user-level extension";
181   if (Ext.startswith("z"))
182     return "standard user-level extension";
183   return StringRef();
184 }
185 
186 static StringRef getExtensionType(StringRef Ext) {
187   if (Ext.startswith("sx"))
188     return "sx";
189   if (Ext.startswith("s"))
190     return "s";
191   if (Ext.startswith("x"))
192     return "x";
193   if (Ext.startswith("z"))
194     return "z";
195   return StringRef();
196 }
197 
198 static Optional<RISCVExtensionVersion> isExperimentalExtension(StringRef Ext) {
199   auto ExtIterator =
200       llvm::find_if(SupportedExperimentalExtensions, FindByName(Ext));
201   if (ExtIterator == std::end(SupportedExperimentalExtensions))
202     return None;
203 
204   return ExtIterator->Version;
205 }
206 
207 bool RISCVISAInfo::isSupportedExtensionFeature(StringRef Ext) {
208   bool IsExperimental = stripExperimentalPrefix(Ext);
209 
210   if (IsExperimental)
211     return llvm::any_of(SupportedExperimentalExtensions, FindByName(Ext));
212   else
213     return llvm::any_of(SupportedExtensions, FindByName(Ext));
214 }
215 
216 bool RISCVISAInfo::isSupportedExtension(StringRef Ext) {
217   return llvm::any_of(SupportedExtensions, FindByName(Ext)) ||
218          llvm::any_of(SupportedExperimentalExtensions, FindByName(Ext));
219 }
220 
221 bool RISCVISAInfo::isSupportedExtension(StringRef Ext, unsigned MajorVersion,
222                                         unsigned MinorVersion) {
223   auto FindByNameAndVersion = [=](const RISCVSupportedExtension &ExtInfo) {
224     return ExtInfo.Name == Ext && (MajorVersion == ExtInfo.Version.Major) &&
225            (MinorVersion == ExtInfo.Version.Minor);
226   };
227   return llvm::any_of(SupportedExtensions, FindByNameAndVersion) ||
228          llvm::any_of(SupportedExperimentalExtensions, FindByNameAndVersion);
229 }
230 
231 bool RISCVISAInfo::hasExtension(StringRef Ext) const {
232   stripExperimentalPrefix(Ext);
233 
234   if (!isSupportedExtension(Ext))
235     return false;
236 
237   return Exts.count(Ext.str()) != 0;
238 }
239 
240 // Get the rank for single-letter extension, lower value meaning higher
241 // priority.
242 static int singleLetterExtensionRank(char Ext) {
243   switch (Ext) {
244   case 'i':
245     return -2;
246   case 'e':
247     return -1;
248   default:
249     break;
250   }
251 
252   size_t Pos = AllStdExts.find(Ext);
253   int Rank;
254   if (Pos == StringRef::npos)
255     // If we got an unknown extension letter, then give it an alphabetical
256     // order, but after all known standard extensions.
257     Rank = AllStdExts.size() + (Ext - 'a');
258   else
259     Rank = Pos;
260 
261   return Rank;
262 }
263 
264 // Get the rank for multi-letter extension, lower value meaning higher
265 // priority/order in canonical order.
266 static int multiLetterExtensionRank(const std::string &ExtName) {
267   assert(ExtName.length() >= 2);
268   int HighOrder;
269   int LowOrder = 0;
270   // The order between multi-char extensions: s -> h -> z -> x.
271   char ExtClass = ExtName[0];
272   switch (ExtClass) {
273   case 's':
274     HighOrder = 0;
275     break;
276   case 'h':
277     HighOrder = 1;
278     break;
279   case 'z':
280     HighOrder = 2;
281     // `z` extension must be sorted by canonical order of second letter.
282     // e.g. zmx has higher rank than zax.
283     LowOrder = singleLetterExtensionRank(ExtName[1]);
284     break;
285   case 'x':
286     HighOrder = 3;
287     break;
288   default:
289     llvm_unreachable("Unknown prefix for multi-char extension");
290     return -1;
291   }
292 
293   return (HighOrder << 8) + LowOrder;
294 }
295 
296 // Compare function for extension.
297 // Only compare the extension name, ignore version comparison.
298 bool RISCVISAInfo::compareExtension(const std::string &LHS,
299                                     const std::string &RHS) {
300   size_t LHSLen = LHS.length();
301   size_t RHSLen = RHS.length();
302   if (LHSLen == 1 && RHSLen != 1)
303     return true;
304 
305   if (LHSLen != 1 && RHSLen == 1)
306     return false;
307 
308   if (LHSLen == 1 && RHSLen == 1)
309     return singleLetterExtensionRank(LHS[0]) <
310            singleLetterExtensionRank(RHS[0]);
311 
312   // Both are multi-char ext here.
313   int LHSRank = multiLetterExtensionRank(LHS);
314   int RHSRank = multiLetterExtensionRank(RHS);
315   if (LHSRank != RHSRank)
316     return LHSRank < RHSRank;
317 
318   // If the rank is same, it must be sorted by lexicographic order.
319   return LHS < RHS;
320 }
321 
322 void RISCVISAInfo::toFeatures(
323     std::vector<StringRef> &Features,
324     std::function<StringRef(const Twine &)> StrAlloc) const {
325   for (auto const &Ext : Exts) {
326     StringRef ExtName = Ext.first;
327 
328     if (ExtName == "i")
329       continue;
330 
331     if (isExperimentalExtension(ExtName)) {
332       Features.push_back(StrAlloc("+experimental-" + ExtName));
333     } else {
334       Features.push_back(StrAlloc("+" + ExtName));
335     }
336   }
337 }
338 
339 // Extensions may have a version number, and may be separated by
340 // an underscore '_' e.g.: rv32i2_m2.
341 // Version number is divided into major and minor version numbers,
342 // separated by a 'p'. If the minor version is 0 then 'p0' can be
343 // omitted from the version string. E.g., rv32i2p0, rv32i2, rv32i2p1.
344 static Error getExtensionVersion(StringRef Ext, StringRef In, unsigned &Major,
345                                  unsigned &Minor, unsigned &ConsumeLength,
346                                  bool EnableExperimentalExtension,
347                                  bool ExperimentalExtensionVersionCheck) {
348   StringRef MajorStr, MinorStr;
349   Major = 0;
350   Minor = 0;
351   ConsumeLength = 0;
352   MajorStr = In.take_while(isDigit);
353   In = In.substr(MajorStr.size());
354 
355   if (!MajorStr.empty() && In.consume_front("p")) {
356     MinorStr = In.take_while(isDigit);
357     In = In.substr(MajorStr.size() + MinorStr.size() - 1);
358 
359     // Expected 'p' to be followed by minor version number.
360     if (MinorStr.empty()) {
361       return createStringError(
362           errc::invalid_argument,
363           "minor version number missing after 'p' for extension '" + Ext + "'");
364     }
365   }
366 
367   if (!MajorStr.empty() && MajorStr.getAsInteger(10, Major))
368     return createStringError(
369         errc::invalid_argument,
370         "Failed to parse major version number for extension '" + Ext + "'");
371 
372   if (!MinorStr.empty() && MinorStr.getAsInteger(10, Minor))
373     return createStringError(
374         errc::invalid_argument,
375         "Failed to parse minor version number for extension '" + Ext + "'");
376 
377   ConsumeLength = MajorStr.size();
378 
379   if (!MinorStr.empty())
380     ConsumeLength += MinorStr.size() + 1 /*'p'*/;
381 
382   // Expected multi-character extension with version number to have no
383   // subsequent characters (i.e. must either end string or be followed by
384   // an underscore).
385   if (Ext.size() > 1 && In.size()) {
386     std::string Error =
387         "multi-character extensions must be separated by underscores";
388     return createStringError(errc::invalid_argument, Error);
389   }
390 
391   // If experimental extension, require use of current version number number
392   if (auto ExperimentalExtension = isExperimentalExtension(Ext)) {
393     if (!EnableExperimentalExtension) {
394       std::string Error = "requires '-menable-experimental-extensions' for "
395                           "experimental extension '" +
396                           Ext.str() + "'";
397       return createStringError(errc::invalid_argument, Error);
398     }
399 
400     if (ExperimentalExtensionVersionCheck &&
401         (MajorStr.empty() && MinorStr.empty())) {
402       std::string Error =
403           "experimental extension requires explicit version number `" +
404           Ext.str() + "`";
405       return createStringError(errc::invalid_argument, Error);
406     }
407 
408     auto SupportedVers = *ExperimentalExtension;
409     if (ExperimentalExtensionVersionCheck &&
410         (Major != SupportedVers.Major || Minor != SupportedVers.Minor)) {
411       std::string Error = "unsupported version number " + MajorStr.str();
412       if (!MinorStr.empty())
413         Error += "." + MinorStr.str();
414       Error += " for experimental extension '" + Ext.str() +
415                "' (this compiler supports " + utostr(SupportedVers.Major) +
416                "." + utostr(SupportedVers.Minor) + ")";
417       return createStringError(errc::invalid_argument, Error);
418     }
419     return Error::success();
420   }
421 
422   // Exception rule for `g`, we don't have clear version scheme for that on
423   // ISA spec.
424   if (Ext == "g")
425     return Error::success();
426 
427   if (MajorStr.empty() && MinorStr.empty()) {
428     if (auto DefaultVersion = findDefaultVersion(Ext)) {
429       Major = DefaultVersion->Major;
430       Minor = DefaultVersion->Minor;
431     }
432     // No matter found or not, return success, assume other place will
433     // verify.
434     return Error::success();
435   }
436 
437   if (RISCVISAInfo::isSupportedExtension(Ext, Major, Minor))
438     return Error::success();
439 
440   std::string Error = "unsupported version number " + std::string(MajorStr);
441   if (!MinorStr.empty())
442     Error += "." + MinorStr.str();
443   Error += " for extension '" + Ext.str() + "'";
444   return createStringError(errc::invalid_argument, Error);
445 }
446 
447 llvm::Expected<std::unique_ptr<RISCVISAInfo>>
448 RISCVISAInfo::parseFeatures(unsigned XLen,
449                             const std::vector<std::string> &Features) {
450   assert(XLen == 32 || XLen == 64);
451   std::unique_ptr<RISCVISAInfo> ISAInfo(new RISCVISAInfo(XLen));
452 
453   for (auto &Feature : Features) {
454     StringRef ExtName = Feature;
455     bool Experimental = false;
456     assert(ExtName.size() > 1 && (ExtName[0] == '+' || ExtName[0] == '-'));
457     bool Add = ExtName[0] == '+';
458     ExtName = ExtName.drop_front(1); // Drop '+' or '-'
459     Experimental = stripExperimentalPrefix(ExtName);
460     auto ExtensionInfos = Experimental
461                               ? makeArrayRef(SupportedExperimentalExtensions)
462                               : makeArrayRef(SupportedExtensions);
463     auto ExtensionInfoIterator =
464         llvm::find_if(ExtensionInfos, FindByName(ExtName));
465 
466     // Not all features is related to ISA extension, like `relax` or
467     // `save-restore`, skip those feature.
468     if (ExtensionInfoIterator == ExtensionInfos.end())
469       continue;
470 
471     if (Add)
472       ISAInfo->addExtension(ExtName, ExtensionInfoIterator->Version.Major,
473                             ExtensionInfoIterator->Version.Minor);
474     else
475       ISAInfo->Exts.erase(ExtName.str());
476   }
477 
478   return RISCVISAInfo::postProcessAndChecking(std::move(ISAInfo));
479 }
480 
481 llvm::Expected<std::unique_ptr<RISCVISAInfo>>
482 RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension,
483                               bool ExperimentalExtensionVersionCheck) {
484   // RISC-V ISA strings must be lowercase.
485   if (llvm::any_of(Arch, isupper)) {
486     return createStringError(errc::invalid_argument,
487                              "string must be lowercase");
488   }
489 
490   bool HasRV64 = Arch.startswith("rv64");
491   // ISA string must begin with rv32 or rv64.
492   if (!(Arch.startswith("rv32") || HasRV64) || (Arch.size() < 5)) {
493     return createStringError(errc::invalid_argument,
494                              "string must begin with rv32{i,e,g} or rv64{i,g}");
495   }
496 
497   unsigned XLen = HasRV64 ? 64 : 32;
498   std::unique_ptr<RISCVISAInfo> ISAInfo(new RISCVISAInfo(XLen));
499 
500   // The canonical order specified in ISA manual.
501   // Ref: Table 22.1 in RISC-V User-Level ISA V2.2
502   StringRef StdExts = AllStdExts;
503   char Baseline = Arch[4];
504 
505   // First letter should be 'e', 'i' or 'g'.
506   switch (Baseline) {
507   default:
508     return createStringError(errc::invalid_argument,
509                              "first letter should be 'e', 'i' or 'g'");
510   case 'e': {
511     // Extension 'e' is not allowed in rv64.
512     if (HasRV64)
513       return createStringError(
514           errc::invalid_argument,
515           "standard user-level extension 'e' requires 'rv32'");
516     break;
517   }
518   case 'i':
519     break;
520   case 'g':
521     // g = imafd
522     StdExts = StdExts.drop_front(4);
523     break;
524   }
525 
526   // Skip rvxxx
527   StringRef Exts = Arch.substr(5);
528 
529   // Remove multi-letter standard extensions, non-standard extensions and
530   // supervisor-level extensions. They have 'z', 'x', 's', 'sx' prefixes.
531   // Parse them at the end.
532   // Find the very first occurrence of 's', 'x' or 'z'.
533   StringRef OtherExts;
534   size_t Pos = Exts.find_first_of("zsx");
535   if (Pos != StringRef::npos) {
536     OtherExts = Exts.substr(Pos);
537     Exts = Exts.substr(0, Pos);
538   }
539 
540   unsigned Major, Minor, ConsumeLength;
541   if (auto E = getExtensionVersion(std::string(1, Baseline), Exts, Major, Minor,
542                                    ConsumeLength, EnableExperimentalExtension,
543                                    ExperimentalExtensionVersionCheck))
544     return std::move(E);
545 
546   if (Baseline == 'g') {
547     // No matter which version is given to `g`, we always set imafd to default
548     // version since the we don't have clear version scheme for that on
549     // ISA spec.
550     for (auto Ext : {"i", "m", "a", "f", "d"})
551       if (auto Version = findDefaultVersion(Ext))
552         ISAInfo->addExtension(Ext, Version->Major, Version->Minor);
553       else
554         llvm_unreachable("Default extension version not found?");
555   } else
556     // Baseline is `i` or `e`
557     ISAInfo->addExtension(std::string(1, Baseline), Major, Minor);
558 
559   // Consume the base ISA version number and any '_' between rvxxx and the
560   // first extension
561   Exts = Exts.drop_front(ConsumeLength);
562   Exts.consume_front("_");
563 
564   // TODO: Use version number when setting target features
565 
566   auto StdExtsItr = StdExts.begin();
567   auto StdExtsEnd = StdExts.end();
568   for (auto I = Exts.begin(), E = Exts.end(); I != E;) {
569     char C = *I;
570 
571     // Check ISA extensions are specified in the canonical order.
572     while (StdExtsItr != StdExtsEnd && *StdExtsItr != C)
573       ++StdExtsItr;
574 
575     if (StdExtsItr == StdExtsEnd) {
576       // Either c contains a valid extension but it was not given in
577       // canonical order or it is an invalid extension.
578       if (StdExts.contains(C)) {
579         return createStringError(
580             errc::invalid_argument,
581             "standard user-level extension not given in canonical order '%c'",
582             C);
583       }
584 
585       return createStringError(errc::invalid_argument,
586                                "invalid standard user-level extension '%c'", C);
587     }
588 
589     // Move to next char to prevent repeated letter.
590     ++StdExtsItr;
591 
592     std::string Next;
593     unsigned Major, Minor, ConsumeLength;
594     if (std::next(I) != E)
595       Next = std::string(std::next(I), E);
596     if (auto E = getExtensionVersion(std::string(1, C), Next, Major, Minor,
597                                      ConsumeLength, EnableExperimentalExtension,
598                                      ExperimentalExtensionVersionCheck))
599       return std::move(E);
600 
601     // The order is OK, then push it into features.
602     // TODO: Use version number when setting target features
603     // Currently LLVM supports only "mafdcbv".
604     StringRef SupportedStandardExtension = "mafdcbv";
605     if (!SupportedStandardExtension.contains(C))
606       return createStringError(errc::invalid_argument,
607                                "unsupported standard user-level extension '%c'",
608                                C);
609     ISAInfo->addExtension(std::string(1, C), Major, Minor);
610 
611     // Consume full extension name and version, including any optional '_'
612     // between this extension and the next
613     ++I;
614     I += ConsumeLength;
615     if (*I == '_')
616       ++I;
617   }
618 
619   // Handle other types of extensions other than the standard
620   // general purpose and standard user-level extensions.
621   // Parse the ISA string containing non-standard user-level
622   // extensions, standard supervisor-level extensions and
623   // non-standard supervisor-level extensions.
624   // These extensions start with 'z', 'x', 's', 'sx' prefixes, follow a
625   // canonical order, might have a version number (major, minor)
626   // and are separated by a single underscore '_'.
627   // Set the hardware features for the extensions that are supported.
628 
629   // Multi-letter extensions are seperated by a single underscore
630   // as described in RISC-V User-Level ISA V2.2.
631   SmallVector<StringRef, 8> Split;
632   OtherExts.split(Split, '_');
633 
634   SmallVector<StringRef, 8> AllExts;
635   std::array<StringRef, 4> Prefix{"z", "x", "s", "sx"};
636   auto I = Prefix.begin();
637   auto E = Prefix.end();
638   if (Split.size() > 1 || Split[0] != "") {
639     for (StringRef Ext : Split) {
640       if (Ext.empty())
641         return createStringError(errc::invalid_argument,
642                                  "extension name missing after separator '_'");
643 
644       StringRef Type = getExtensionType(Ext);
645       StringRef Desc = getExtensionTypeDesc(Ext);
646       auto Pos = findFirstNonVersionCharacter(Ext) + 1;
647       StringRef Name(Ext.substr(0, Pos));
648       StringRef Vers(Ext.substr(Pos));
649 
650       if (Type.empty())
651         return createStringError(errc::invalid_argument,
652                                  "invalid extension prefix '" + Ext + "'");
653 
654       // Check ISA extensions are specified in the canonical order.
655       while (I != E && *I != Type)
656         ++I;
657 
658       if (I == E)
659         return createStringError(errc::invalid_argument,
660                                  "%s not given in canonical order '%s'",
661                                  Desc.str().c_str(), Ext.str().c_str());
662 
663       if (Name.size() == Type.size()) {
664         return createStringError(errc::invalid_argument,
665                                  "%s name missing after '%s'",
666                                  Desc.str().c_str(), Type.str().c_str());
667       }
668 
669       unsigned Major, Minor, ConsumeLength;
670       if (auto E = getExtensionVersion(Name, Vers, Major, Minor, ConsumeLength,
671                                        EnableExperimentalExtension,
672                                        ExperimentalExtensionVersionCheck))
673         return std::move(E);
674 
675       // Check if duplicated extension.
676       if (llvm::is_contained(AllExts, Name))
677         return createStringError(errc::invalid_argument, "duplicated %s '%s'",
678                                  Desc.str().c_str(), Name.str().c_str());
679 
680       ISAInfo->addExtension(Name, Major, Minor);
681       // Extension format is correct, keep parsing the extensions.
682       // TODO: Save Type, Name, Major, Minor to avoid parsing them later.
683       AllExts.push_back(Name);
684     }
685   }
686 
687   for (auto Ext : AllExts) {
688     if (!isSupportedExtension(Ext)) {
689       StringRef Desc = getExtensionTypeDesc(getExtensionType(Ext));
690       return createStringError(errc::invalid_argument, "unsupported %s '%s'",
691                                Desc.str().c_str(), Ext.str().c_str());
692     }
693   }
694 
695   return RISCVISAInfo::postProcessAndChecking(std::move(ISAInfo));
696 }
697 
698 Error RISCVISAInfo::checkDependency() {
699   bool IsRv32 = XLen == 32;
700   bool HasE = Exts.count("e") != 0;
701   bool HasD = Exts.count("d") != 0;
702   bool HasF = Exts.count("f") != 0;
703   bool HasZfinx = Exts.count("zfinx") != 0;
704   bool HasZdinx = Exts.count("zdinx") != 0;
705   bool HasVector = Exts.count("zve32x") != 0;
706   bool HasZve32f = Exts.count("zve32f") != 0;
707   bool HasZve64d = Exts.count("zve64d") != 0;
708   bool HasZvl = MinVLen != 0;
709 
710   if (HasE && !IsRv32)
711     return createStringError(
712         errc::invalid_argument,
713         "standard user-level extension 'e' requires 'rv32'");
714 
715   // It's illegal to specify the 'd' (double-precision floating point)
716   // extension without also specifying the 'f' (single precision
717   // floating-point) extension.
718   // TODO: This has been removed in later specs, which specify that D implies F
719   if (HasD && !HasF)
720     return createStringError(errc::invalid_argument,
721                              "d requires f extension to also be specified");
722 
723   if (HasZve32f && !HasF && !HasZfinx)
724     return createStringError(
725         errc::invalid_argument,
726         "zve32f requires f or zfinx extension to also be specified");
727 
728   if (HasZve64d && !HasD && !HasZdinx)
729     return createStringError(
730         errc::invalid_argument,
731         "zve64d requires d or zdinx extension to also be specified");
732 
733   if (Exts.count("zvfh") && !Exts.count("zfh") && !Exts.count("zfhmin") &&
734       !Exts.count("zhinx") && !Exts.count("zhinxmin"))
735     return createStringError(
736         errc::invalid_argument,
737         "zvfh requires zfh, zfhmin, zhinx or zhinxmin extension to also be "
738         "specified");
739 
740   if (HasZvl && !HasVector)
741     return createStringError(
742         errc::invalid_argument,
743         "zvl*b requires v or zve* extension to also be specified");
744 
745   // Additional dependency checks.
746   // TODO: The 'q' extension requires rv64.
747   // TODO: It is illegal to specify 'e' extensions with 'f' and 'd'.
748 
749   return Error::success();
750 }
751 
752 static const char *ImpliedExtsV[] = {"zvl128b", "zve64d", "f", "d"};
753 static const char *ImpliedExtsZfhmin[] = {"f"};
754 static const char *ImpliedExtsZfh[] = {"f"};
755 static const char *ImpliedExtsZdinx[] = {"zfinx"};
756 static const char *ImpliedExtsZhinxmin[] = {"zfinx"};
757 static const char *ImpliedExtsZhinx[] = {"zfinx"};
758 static const char *ImpliedExtsZve64d[] = {"zve64f"};
759 static const char *ImpliedExtsZve64f[] = {"zve64x", "zve32f"};
760 static const char *ImpliedExtsZve64x[] = {"zve32x", "zvl64b"};
761 static const char *ImpliedExtsZve32f[] = {"zve32x"};
762 static const char *ImpliedExtsZve32x[] = {"zvl32b"};
763 static const char *ImpliedExtsZvl65536b[] = {"zvl32768b"};
764 static const char *ImpliedExtsZvl32768b[] = {"zvl16384b"};
765 static const char *ImpliedExtsZvl16384b[] = {"zvl8192b"};
766 static const char *ImpliedExtsZvl8192b[] = {"zvl4096b"};
767 static const char *ImpliedExtsZvl4096b[] = {"zvl2048b"};
768 static const char *ImpliedExtsZvl2048b[] = {"zvl1024b"};
769 static const char *ImpliedExtsZvl1024b[] = {"zvl512b"};
770 static const char *ImpliedExtsZvl512b[] = {"zvl256b"};
771 static const char *ImpliedExtsZvl256b[] = {"zvl128b"};
772 static const char *ImpliedExtsZvl128b[] = {"zvl64b"};
773 static const char *ImpliedExtsZvl64b[] = {"zvl32b"};
774 static const char *ImpliedExtsZk[] = {"zkn", "zkt", "zkr"};
775 static const char *ImpliedExtsZkn[] = {"zbkb", "zbkc", "zbkx", "zkne", "zknd", "zknh"};
776 static const char *ImpliedExtsZks[] = {"zbkb", "zbkc", "zbkx", "zksed", "zksh"};
777 static const char *ImpliedExtsZvfh[] = {"zve32f"};
778 
779 struct ImpliedExtsEntry {
780   StringLiteral Name;
781   ArrayRef<const char *> Exts;
782 
783   bool operator<(const ImpliedExtsEntry &Other) const {
784     return Name < Other.Name;
785   }
786 
787   bool operator<(StringRef Other) const { return Name < Other; }
788 };
789 
790 // Note: The table needs to be sorted by name.
791 static constexpr ImpliedExtsEntry ImpliedExts[] = {
792     {{"v"}, {ImpliedExtsV}},
793     {{"zdinx"}, {ImpliedExtsZdinx}},
794     {{"zfh"}, {ImpliedExtsZfh}},
795     {{"zfhmin"}, {ImpliedExtsZfhmin}},
796     {{"zhinx"}, {ImpliedExtsZhinx}},
797     {{"zhinxmin"}, {ImpliedExtsZhinxmin}},
798     {{"zk"}, {ImpliedExtsZk}},
799     {{"zkn"}, {ImpliedExtsZkn}},
800     {{"zks"}, {ImpliedExtsZks}},
801     {{"zve32f"}, {ImpliedExtsZve32f}},
802     {{"zve32x"}, {ImpliedExtsZve32x}},
803     {{"zve64d"}, {ImpliedExtsZve64d}},
804     {{"zve64f"}, {ImpliedExtsZve64f}},
805     {{"zve64x"}, {ImpliedExtsZve64x}},
806     {{"zvfh"}, {ImpliedExtsZvfh}},
807     {{"zvl1024b"}, {ImpliedExtsZvl1024b}},
808     {{"zvl128b"}, {ImpliedExtsZvl128b}},
809     {{"zvl16384b"}, {ImpliedExtsZvl16384b}},
810     {{"zvl2048b"}, {ImpliedExtsZvl2048b}},
811     {{"zvl256b"}, {ImpliedExtsZvl256b}},
812     {{"zvl32768b"}, {ImpliedExtsZvl32768b}},
813     {{"zvl4096b"}, {ImpliedExtsZvl4096b}},
814     {{"zvl512b"}, {ImpliedExtsZvl512b}},
815     {{"zvl64b"}, {ImpliedExtsZvl64b}},
816     {{"zvl65536b"}, {ImpliedExtsZvl65536b}},
817     {{"zvl8192b"}, {ImpliedExtsZvl8192b}},
818 };
819 
820 void RISCVISAInfo::updateImplication() {
821   bool HasE = Exts.count("e") != 0;
822   bool HasI = Exts.count("i") != 0;
823 
824   // If not in e extension and i extension does not exist, i extension is
825   // implied
826   if (!HasE && !HasI) {
827     auto Version = findDefaultVersion("i");
828     addExtension("i", Version->Major, Version->Minor);
829   }
830 
831   assert(llvm::is_sorted(ImpliedExts) && "Table not sorted by Name");
832 
833   // This loop may execute over 1 iteration since implication can be layered
834   // Exits loop if no more implication is applied
835   SmallSetVector<StringRef, 16> WorkList;
836   for (auto const &Ext : Exts)
837     WorkList.insert(Ext.first);
838 
839   while (!WorkList.empty()) {
840     StringRef ExtName = WorkList.pop_back_val();
841     auto I = llvm::lower_bound(ImpliedExts, ExtName);
842     if (I != std::end(ImpliedExts) && I->Name == ExtName) {
843       for (const char *ImpliedExt : I->Exts) {
844         if (WorkList.count(ImpliedExt))
845           continue;
846         if (Exts.count(ImpliedExt))
847           continue;
848         auto Version = findDefaultVersion(ImpliedExt);
849         addExtension(ImpliedExt, Version->Major, Version->Minor);
850         WorkList.insert(ImpliedExt);
851       }
852     }
853   }
854 }
855 
856 struct CombinedExtsEntry {
857   StringLiteral CombineExt;
858   ArrayRef<const char *> RequiredExts;
859 };
860 
861 static constexpr CombinedExtsEntry CombineIntoExts[] = {
862     {{"zk"}, {ImpliedExtsZk}},
863     {{"zkn"}, {ImpliedExtsZkn}},
864     {{"zks"}, {ImpliedExtsZks}},
865 };
866 
867 void RISCVISAInfo::updateCombination() {
868   bool IsNewCombine = false;
869   do {
870     IsNewCombine = false;
871     for (CombinedExtsEntry CombineIntoExt : CombineIntoExts) {
872       auto CombineExt = CombineIntoExt.CombineExt;
873       auto RequiredExts = CombineIntoExt.RequiredExts;
874       if (hasExtension(CombineExt))
875         continue;
876       bool IsAllRequiredFeatureExist = true;
877       for (const char *Ext : RequiredExts)
878         IsAllRequiredFeatureExist &= hasExtension(Ext);
879       if (IsAllRequiredFeatureExist) {
880         auto Version = findDefaultVersion(CombineExt);
881         addExtension(CombineExt, Version->Major, Version->Minor);
882         IsNewCombine = true;
883       }
884     }
885   } while (IsNewCombine);
886 }
887 
888 void RISCVISAInfo::updateFLen() {
889   FLen = 0;
890   // TODO: Handle q extension.
891   if (Exts.count("d"))
892     FLen = 64;
893   else if (Exts.count("f"))
894     FLen = 32;
895 }
896 
897 void RISCVISAInfo::updateMinVLen() {
898   for (auto const &Ext : Exts) {
899     StringRef ExtName = Ext.first;
900     bool IsZvlExt = ExtName.consume_front("zvl") && ExtName.consume_back("b");
901     if (IsZvlExt) {
902       unsigned ZvlLen;
903       if (!ExtName.getAsInteger(10, ZvlLen))
904         MinVLen = std::max(MinVLen, ZvlLen);
905     }
906   }
907 }
908 
909 void RISCVISAInfo::updateMaxELen() {
910   // handles EEW restriction by sub-extension zve
911   for (auto const &Ext : Exts) {
912     StringRef ExtName = Ext.first;
913     bool IsZveExt = ExtName.consume_front("zve");
914     if (IsZveExt) {
915       if (ExtName.back() == 'f')
916         MaxELenFp = std::max(MaxELenFp, 32u);
917       if (ExtName.back() == 'd')
918         MaxELenFp = std::max(MaxELenFp, 64u);
919       ExtName = ExtName.drop_back();
920       unsigned ZveELen;
921       ExtName.getAsInteger(10, ZveELen);
922       MaxELen = std::max(MaxELen, ZveELen);
923     }
924   }
925 }
926 
927 std::string RISCVISAInfo::toString() const {
928   std::string Buffer;
929   raw_string_ostream Arch(Buffer);
930 
931   Arch << "rv" << XLen;
932 
933   ListSeparator LS("_");
934   for (auto const &Ext : Exts) {
935     StringRef ExtName = Ext.first;
936     auto ExtInfo = Ext.second;
937     Arch << LS << ExtName;
938     Arch << ExtInfo.MajorVersion << "p" << ExtInfo.MinorVersion;
939   }
940 
941   return Arch.str();
942 }
943 
944 std::vector<std::string> RISCVISAInfo::toFeatureVector() const {
945   std::vector<std::string> FeatureVector;
946   for (auto const &Ext : Exts) {
947     std::string ExtName = Ext.first;
948     if (ExtName == "i") // i is not recognized in clang -cc1
949       continue;
950     std::string Feature = isExperimentalExtension(ExtName)
951                               ? "+experimental-" + ExtName
952                               : "+" + ExtName;
953     FeatureVector.push_back(Feature);
954   }
955   return FeatureVector;
956 }
957 
958 llvm::Expected<std::unique_ptr<RISCVISAInfo>>
959 RISCVISAInfo::postProcessAndChecking(std::unique_ptr<RISCVISAInfo> &&ISAInfo) {
960   ISAInfo->updateImplication();
961   ISAInfo->updateCombination();
962   ISAInfo->updateFLen();
963   ISAInfo->updateMinVLen();
964   ISAInfo->updateMaxELen();
965 
966   if (Error Result = ISAInfo->checkDependency())
967     return std::move(Result);
968   return std::move(ISAInfo);
969 }
970 
971 StringRef RISCVISAInfo::computeDefaultABI() const {
972   if (XLen == 32) {
973     if (hasExtension("d"))
974       return "ilp32d";
975     if (hasExtension("e"))
976       return "ilp32e";
977     return "ilp32";
978   } else if (XLen == 64) {
979     if (hasExtension("d"))
980       return "lp64d";
981     return "lp64";
982   }
983   llvm_unreachable("Invalid XLEN");
984 }
985