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