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