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