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