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