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