1 //===-- RISCVISAInfo.cpp - RISC-V 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 <atomic>
20 #include <optional>
21 #include <string>
22 #include <vector>
23 
24 using namespace llvm;
25 
26 namespace {
27 
28 struct RISCVSupportedExtension {
29   const char *Name;
30   /// Supported version.
31   RISCVISAInfo::ExtensionVersion Version;
32 
operator <__anon6eab22b40111::RISCVSupportedExtension33   bool operator<(const RISCVSupportedExtension &RHS) const {
34     return StringRef(Name) < StringRef(RHS.Name);
35   }
36 };
37 
38 } // end anonymous namespace
39 
40 static constexpr StringLiteral AllStdExts = "mafdqlcbkjtpvnh";
41 
42 static const char *RISCVGImplications[] = {
43   "i", "m", "a", "f", "d", "zicsr", "zifencei"
44 };
45 
46 // NOTE: This table should be sorted alphabetically by extension name.
47 static const RISCVSupportedExtension SupportedExtensions[] = {
48     {"a", {2, 1}},
49     {"c", {2, 0}},
50     {"d", {2, 2}},
51     {"e", {2, 0}},
52     {"f", {2, 2}},
53     {"h", {1, 0}},
54     {"i", {2, 1}},
55     {"m", {2, 0}},
56 
57     {"smaia", {1, 0}},
58     {"smepmp", {1, 0}},
59     {"ssaia", {1, 0}},
60     {"svinval", {1, 0}},
61     {"svnapot", {1, 0}},
62     {"svpbmt", {1, 0}},
63 
64     {"v", {1, 0}},
65 
66     // vendor-defined ('X') extensions
67     {"xcvalu", {1, 0}},
68     {"xcvbi", {1, 0}},
69     {"xcvbitmanip", {1, 0}},
70     {"xcvelw", {1, 0}},
71     {"xcvmac", {1, 0}},
72     {"xcvmem", {1, 0}},
73     {"xcvsimd", {1, 0}},
74     {"xsfvcp", {1, 0}},
75     {"xsfvfnrclipxfqf", {1, 0}},
76     {"xsfvfwmaccqqq", {1, 0}},
77     {"xsfvqmaccdod", {1, 0}},
78     {"xsfvqmaccqoq", {1, 0}},
79     {"xtheadba", {1, 0}},
80     {"xtheadbb", {1, 0}},
81     {"xtheadbs", {1, 0}},
82     {"xtheadcmo", {1, 0}},
83     {"xtheadcondmov", {1, 0}},
84     {"xtheadfmemidx", {1, 0}},
85     {"xtheadmac", {1, 0}},
86     {"xtheadmemidx", {1, 0}},
87     {"xtheadmempair", {1, 0}},
88     {"xtheadsync", {1, 0}},
89     {"xtheadvdot", {1, 0}},
90     {"xventanacondops", {1, 0}},
91 
92     {"za128rs", {1, 0}},
93     {"za64rs", {1, 0}},
94     {"zawrs", {1, 0}},
95 
96     {"zba", {1, 0}},
97     {"zbb", {1, 0}},
98     {"zbc", {1, 0}},
99     {"zbkb", {1, 0}},
100     {"zbkc", {1, 0}},
101     {"zbkx", {1, 0}},
102     {"zbs", {1, 0}},
103 
104     {"zca", {1, 0}},
105     {"zcb", {1, 0}},
106     {"zcd", {1, 0}},
107     {"zce", {1, 0}},
108     {"zcf", {1, 0}},
109     {"zcmp", {1, 0}},
110     {"zcmt", {1, 0}},
111 
112     {"zdinx", {1, 0}},
113 
114     {"zfa", {1, 0}},
115     {"zfh", {1, 0}},
116     {"zfhmin", {1, 0}},
117     {"zfinx", {1, 0}},
118 
119     {"zhinx", {1, 0}},
120     {"zhinxmin", {1, 0}},
121 
122     {"zic64b", {1, 0}},
123     {"zicbom", {1, 0}},
124     {"zicbop", {1, 0}},
125     {"zicboz", {1, 0}},
126     {"ziccamoa", {1, 0}},
127     {"ziccif", {1, 0}},
128     {"zicclsm", {1, 0}},
129     {"ziccrse", {1, 0}},
130     {"zicntr", {2, 0}},
131     {"zicond", {1, 0}},
132     {"zicsr", {2, 0}},
133     {"zifencei", {2, 0}},
134     {"zihintntl", {1, 0}},
135     {"zihintpause", {2, 0}},
136     {"zihpm", {2, 0}},
137 
138     {"zk", {1, 0}},
139     {"zkn", {1, 0}},
140     {"zknd", {1, 0}},
141     {"zkne", {1, 0}},
142     {"zknh", {1, 0}},
143     {"zkr", {1, 0}},
144     {"zks", {1, 0}},
145     {"zksed", {1, 0}},
146     {"zksh", {1, 0}},
147     {"zkt", {1, 0}},
148 
149     {"zmmul", {1, 0}},
150 
151     {"zvbb", {1, 0}},
152     {"zvbc", {1, 0}},
153 
154     {"zve32f", {1, 0}},
155     {"zve32x", {1, 0}},
156     {"zve64d", {1, 0}},
157     {"zve64f", {1, 0}},
158     {"zve64x", {1, 0}},
159 
160     {"zvfh", {1, 0}},
161     {"zvfhmin", {1, 0}},
162 
163     // vector crypto
164     {"zvkb", {1, 0}},
165     {"zvkg", {1, 0}},
166     {"zvkn", {1, 0}},
167     {"zvknc", {1, 0}},
168     {"zvkned", {1, 0}},
169     {"zvkng", {1, 0}},
170     {"zvknha", {1, 0}},
171     {"zvknhb", {1, 0}},
172     {"zvks", {1, 0}},
173     {"zvksc", {1, 0}},
174     {"zvksed", {1, 0}},
175     {"zvksg", {1, 0}},
176     {"zvksh", {1, 0}},
177     {"zvkt", {1, 0}},
178 
179     {"zvl1024b", {1, 0}},
180     {"zvl128b", {1, 0}},
181     {"zvl16384b", {1, 0}},
182     {"zvl2048b", {1, 0}},
183     {"zvl256b", {1, 0}},
184     {"zvl32768b", {1, 0}},
185     {"zvl32b", {1, 0}},
186     {"zvl4096b", {1, 0}},
187     {"zvl512b", {1, 0}},
188     {"zvl64b", {1, 0}},
189     {"zvl65536b", {1, 0}},
190     {"zvl8192b", {1, 0}},
191 };
192 
193 // NOTE: This table should be sorted alphabetically by extension name.
194 static const RISCVSupportedExtension SupportedExperimentalExtensions[] = {
195     {"zacas", {1, 0}},
196 
197     {"zcmop", {0, 2}},
198 
199     {"zfbfmin", {1, 0}},
200 
201     {"zicfilp", {0, 4}},
202     {"zicfiss", {0, 4}},
203 
204     {"zimop", {0, 1}},
205 
206     {"ztso", {0, 1}},
207 
208     {"zvfbfmin", {1, 0}},
209     {"zvfbfwma", {1, 0}},
210 };
211 
verifyTables()212 static void verifyTables() {
213 #ifndef NDEBUG
214   static std::atomic<bool> TableChecked(false);
215   if (!TableChecked.load(std::memory_order_relaxed)) {
216     assert(llvm::is_sorted(SupportedExtensions) &&
217            "Extensions are not sorted by name");
218     assert(llvm::is_sorted(SupportedExperimentalExtensions) &&
219            "Experimental extensions are not sorted by name");
220     TableChecked.store(true, std::memory_order_relaxed);
221   }
222 #endif
223 }
224 
PrintExtension(StringRef Name,StringRef Version,StringRef Description)225 static void PrintExtension(StringRef Name, StringRef Version,
226                            StringRef Description) {
227   outs().indent(4);
228   unsigned VersionWidth = Description.empty() ? 0 : 10;
229   outs() << left_justify(Name, 20) << left_justify(Version, VersionWidth)
230          << Description << "\n";
231 }
232 
riscvExtensionsHelp(StringMap<StringRef> DescMap)233 void llvm::riscvExtensionsHelp(StringMap<StringRef> DescMap) {
234 
235   outs() << "All available -march extensions for RISC-V\n\n";
236   PrintExtension("Name", "Version", (DescMap.empty() ? "" : "Description"));
237 
238   RISCVISAInfo::OrderedExtensionMap ExtMap;
239   for (const auto &E : SupportedExtensions)
240     ExtMap[E.Name] = {E.Version.Major, E.Version.Minor};
241   for (const auto &E : ExtMap) {
242     std::string Version =
243         std::to_string(E.second.Major) + "." + std::to_string(E.second.Minor);
244     PrintExtension(E.first, Version, DescMap[E.first]);
245   }
246 
247   outs() << "\nExperimental extensions\n";
248   ExtMap.clear();
249   for (const auto &E : SupportedExperimentalExtensions)
250     ExtMap[E.Name] = {E.Version.Major, E.Version.Minor};
251   for (const auto &E : ExtMap) {
252     std::string Version =
253         std::to_string(E.second.Major) + "." + std::to_string(E.second.Minor);
254     PrintExtension(E.first, Version, DescMap["experimental-" + E.first]);
255   }
256 
257   outs() << "\nUse -march to specify the target's extension.\n"
258             "For example, clang -march=rv32i_v1p0\n";
259 }
260 
stripExperimentalPrefix(StringRef & Ext)261 static bool stripExperimentalPrefix(StringRef &Ext) {
262   return Ext.consume_front("experimental-");
263 }
264 
265 // This function finds the last character that doesn't belong to a version
266 // (e.g. zba1p0 is extension 'zba' of version '1p0'). So the function will
267 // consume [0-9]*p[0-9]* starting from the backward. An extension name will not
268 // end with a digit or the letter 'p', so this function will parse correctly.
269 // NOTE: This function is NOT able to take empty strings or strings that only
270 // have version numbers and no extension name. It assumes the extension name
271 // will be at least more than one character.
findLastNonVersionCharacter(StringRef Ext)272 static size_t findLastNonVersionCharacter(StringRef Ext) {
273   assert(!Ext.empty() &&
274          "Already guarded by if-statement in ::parseArchString");
275 
276   int Pos = Ext.size() - 1;
277   while (Pos > 0 && isDigit(Ext[Pos]))
278     Pos--;
279   if (Pos > 0 && Ext[Pos] == 'p' && isDigit(Ext[Pos - 1])) {
280     Pos--;
281     while (Pos > 0 && isDigit(Ext[Pos]))
282       Pos--;
283   }
284   return Pos;
285 }
286 
287 namespace {
288 struct LessExtName {
operator ()__anon6eab22b40211::LessExtName289   bool operator()(const RISCVSupportedExtension &LHS, StringRef RHS) {
290     return StringRef(LHS.Name) < RHS;
291   }
operator ()__anon6eab22b40211::LessExtName292   bool operator()(StringRef LHS, const RISCVSupportedExtension &RHS) {
293     return LHS < StringRef(RHS.Name);
294   }
295 };
296 } // namespace
297 
298 static std::optional<RISCVISAInfo::ExtensionVersion>
findDefaultVersion(StringRef ExtName)299 findDefaultVersion(StringRef ExtName) {
300   // Find default version of an extension.
301   // TODO: We might set default version based on profile or ISA spec.
302   for (auto &ExtInfo : {ArrayRef(SupportedExtensions),
303                         ArrayRef(SupportedExperimentalExtensions)}) {
304     auto I = llvm::lower_bound(ExtInfo, ExtName, LessExtName());
305 
306     if (I == ExtInfo.end() || I->Name != ExtName)
307       continue;
308 
309     return I->Version;
310   }
311   return std::nullopt;
312 }
313 
addExtension(StringRef ExtName,RISCVISAInfo::ExtensionVersion Version)314 void RISCVISAInfo::addExtension(StringRef ExtName,
315                                 RISCVISAInfo::ExtensionVersion Version) {
316   Exts[ExtName.str()] = Version;
317 }
318 
getExtensionTypeDesc(StringRef Ext)319 static StringRef getExtensionTypeDesc(StringRef Ext) {
320   if (Ext.starts_with("s"))
321     return "standard supervisor-level extension";
322   if (Ext.starts_with("x"))
323     return "non-standard user-level extension";
324   if (Ext.starts_with("z"))
325     return "standard user-level extension";
326   return StringRef();
327 }
328 
getExtensionType(StringRef Ext)329 static StringRef getExtensionType(StringRef Ext) {
330   if (Ext.starts_with("s"))
331     return "s";
332   if (Ext.starts_with("x"))
333     return "x";
334   if (Ext.starts_with("z"))
335     return "z";
336   return StringRef();
337 }
338 
339 static std::optional<RISCVISAInfo::ExtensionVersion>
isExperimentalExtension(StringRef Ext)340 isExperimentalExtension(StringRef Ext) {
341   auto I =
342       llvm::lower_bound(SupportedExperimentalExtensions, Ext, LessExtName());
343   if (I == std::end(SupportedExperimentalExtensions) || I->Name != Ext)
344     return std::nullopt;
345 
346   return I->Version;
347 }
348 
isSupportedExtensionFeature(StringRef Ext)349 bool RISCVISAInfo::isSupportedExtensionFeature(StringRef Ext) {
350   bool IsExperimental = stripExperimentalPrefix(Ext);
351 
352   ArrayRef<RISCVSupportedExtension> ExtInfo =
353       IsExperimental ? ArrayRef(SupportedExperimentalExtensions)
354                      : ArrayRef(SupportedExtensions);
355 
356   auto I = llvm::lower_bound(ExtInfo, Ext, LessExtName());
357   return I != ExtInfo.end() && I->Name == Ext;
358 }
359 
isSupportedExtension(StringRef Ext)360 bool RISCVISAInfo::isSupportedExtension(StringRef Ext) {
361   verifyTables();
362 
363   for (auto ExtInfo : {ArrayRef(SupportedExtensions),
364                        ArrayRef(SupportedExperimentalExtensions)}) {
365     auto I = llvm::lower_bound(ExtInfo, Ext, LessExtName());
366     if (I != ExtInfo.end() && I->Name == Ext)
367       return true;
368   }
369 
370   return false;
371 }
372 
isSupportedExtension(StringRef Ext,unsigned MajorVersion,unsigned MinorVersion)373 bool RISCVISAInfo::isSupportedExtension(StringRef Ext, unsigned MajorVersion,
374                                         unsigned MinorVersion) {
375   for (auto ExtInfo : {ArrayRef(SupportedExtensions),
376                        ArrayRef(SupportedExperimentalExtensions)}) {
377     auto Range =
378         std::equal_range(ExtInfo.begin(), ExtInfo.end(), Ext, LessExtName());
379     for (auto I = Range.first, E = Range.second; I != E; ++I)
380       if (I->Version.Major == MajorVersion && I->Version.Minor == MinorVersion)
381         return true;
382   }
383 
384   return false;
385 }
386 
hasExtension(StringRef Ext) const387 bool RISCVISAInfo::hasExtension(StringRef Ext) const {
388   stripExperimentalPrefix(Ext);
389 
390   if (!isSupportedExtension(Ext))
391     return false;
392 
393   return Exts.count(Ext.str()) != 0;
394 }
395 
396 // We rank extensions in the following order:
397 // -Single letter extensions in canonical order.
398 // -Unknown single letter extensions in alphabetical order.
399 // -Multi-letter extensions starting with 'z' sorted by canonical order of
400 //  the second letter then sorted alphabetically.
401 // -Multi-letter extensions starting with 's' in alphabetical order.
402 // -(TODO) Multi-letter extensions starting with 'zxm' in alphabetical order.
403 // -X extensions in alphabetical order.
404 // These flags are used to indicate the category. The first 6 bits store the
405 // single letter extension rank for single letter and multi-letter extensions
406 // starting with 'z'.
407 enum RankFlags {
408   RF_Z_EXTENSION = 1 << 6,
409   RF_S_EXTENSION = 1 << 7,
410   RF_X_EXTENSION = 1 << 8,
411 };
412 
413 // Get the rank for single-letter extension, lower value meaning higher
414 // priority.
singleLetterExtensionRank(char Ext)415 static unsigned singleLetterExtensionRank(char Ext) {
416   assert(Ext >= 'a' && Ext <= 'z');
417   switch (Ext) {
418   case 'i':
419     return 0;
420   case 'e':
421     return 1;
422   }
423 
424   size_t Pos = AllStdExts.find(Ext);
425   if (Pos != StringRef::npos)
426     return Pos + 2; // Skip 'e' and 'i' from above.
427 
428   // If we got an unknown extension letter, then give it an alphabetical
429   // order, but after all known standard extensions.
430   return 2 + AllStdExts.size() + (Ext - 'a');
431 }
432 
433 // Get the rank for multi-letter extension, lower value meaning higher
434 // priority/order in canonical order.
getExtensionRank(const std::string & ExtName)435 static unsigned getExtensionRank(const std::string &ExtName) {
436   assert(ExtName.size() >= 1);
437   switch (ExtName[0]) {
438   case 's':
439     return RF_S_EXTENSION;
440   case 'z':
441     assert(ExtName.size() >= 2);
442     // `z` extension must be sorted by canonical order of second letter.
443     // e.g. zmx has higher rank than zax.
444     return RF_Z_EXTENSION | singleLetterExtensionRank(ExtName[1]);
445   case 'x':
446     return RF_X_EXTENSION;
447   default:
448     assert(ExtName.size() == 1);
449     return singleLetterExtensionRank(ExtName[0]);
450   }
451 }
452 
453 // Compare function for extension.
454 // Only compare the extension name, ignore version comparison.
compareExtension(const std::string & LHS,const std::string & RHS)455 bool RISCVISAInfo::compareExtension(const std::string &LHS,
456                                     const std::string &RHS) {
457   unsigned LHSRank = getExtensionRank(LHS);
458   unsigned RHSRank = getExtensionRank(RHS);
459 
460   // If the ranks differ, pick the lower rank.
461   if (LHSRank != RHSRank)
462     return LHSRank < RHSRank;
463 
464   // If the rank is same, it must be sorted by lexicographic order.
465   return LHS < RHS;
466 }
467 
toFeatures(bool AddAllExtensions,bool IgnoreUnknown) const468 std::vector<std::string> RISCVISAInfo::toFeatures(bool AddAllExtensions,
469                                                   bool IgnoreUnknown) const {
470   std::vector<std::string> Features;
471   for (const auto &[ExtName, _] : Exts) {
472     // i is a base instruction set, not an extension (see
473     // https://github.com/riscv/riscv-isa-manual/blob/main/src/naming.adoc#base-integer-isa)
474     // and is not recognized in clang -cc1
475     if (ExtName == "i")
476       continue;
477     if (IgnoreUnknown && !isSupportedExtension(ExtName))
478       continue;
479 
480     if (isExperimentalExtension(ExtName)) {
481       Features.push_back((llvm::Twine("+experimental-") + ExtName).str());
482     } else {
483       Features.push_back((llvm::Twine("+") + ExtName).str());
484     }
485   }
486   if (AddAllExtensions) {
487     for (const RISCVSupportedExtension &Ext : SupportedExtensions) {
488       if (Exts.count(Ext.Name))
489         continue;
490       Features.push_back((llvm::Twine("-") + Ext.Name).str());
491     }
492 
493     for (const RISCVSupportedExtension &Ext : SupportedExperimentalExtensions) {
494       if (Exts.count(Ext.Name))
495         continue;
496       Features.push_back((llvm::Twine("-experimental-") + Ext.Name).str());
497     }
498   }
499   return Features;
500 }
501 
502 // Extensions may have a version number, and may be separated by
503 // an underscore '_' e.g.: rv32i2_m2.
504 // Version number is divided into major and minor version numbers,
505 // separated by a 'p'. If the minor version is 0 then 'p0' can be
506 // 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)507 static Error getExtensionVersion(StringRef Ext, StringRef In, unsigned &Major,
508                                  unsigned &Minor, unsigned &ConsumeLength,
509                                  bool EnableExperimentalExtension,
510                                  bool ExperimentalExtensionVersionCheck) {
511   StringRef MajorStr, MinorStr;
512   Major = 0;
513   Minor = 0;
514   ConsumeLength = 0;
515   MajorStr = In.take_while(isDigit);
516   In = In.substr(MajorStr.size());
517 
518   if (!MajorStr.empty() && In.consume_front("p")) {
519     MinorStr = In.take_while(isDigit);
520     In = In.substr(MajorStr.size() + MinorStr.size() - 1);
521 
522     // Expected 'p' to be followed by minor version number.
523     if (MinorStr.empty()) {
524       return createStringError(
525           errc::invalid_argument,
526           "minor version number missing after 'p' for extension '" + Ext + "'");
527     }
528   }
529 
530   if (!MajorStr.empty() && MajorStr.getAsInteger(10, Major))
531     return createStringError(
532         errc::invalid_argument,
533         "Failed to parse major version number for extension '" + Ext + "'");
534 
535   if (!MinorStr.empty() && MinorStr.getAsInteger(10, Minor))
536     return createStringError(
537         errc::invalid_argument,
538         "Failed to parse minor version number for extension '" + Ext + "'");
539 
540   ConsumeLength = MajorStr.size();
541 
542   if (!MinorStr.empty())
543     ConsumeLength += MinorStr.size() + 1 /*'p'*/;
544 
545   // Expected multi-character extension with version number to have no
546   // subsequent characters (i.e. must either end string or be followed by
547   // an underscore).
548   if (Ext.size() > 1 && In.size()) {
549     std::string Error =
550         "multi-character extensions must be separated by underscores";
551     return createStringError(errc::invalid_argument, Error);
552   }
553 
554   // If experimental extension, require use of current version number
555   if (auto ExperimentalExtension = isExperimentalExtension(Ext)) {
556     if (!EnableExperimentalExtension) {
557       std::string Error = "requires '-menable-experimental-extensions' for "
558                           "experimental extension '" +
559                           Ext.str() + "'";
560       return createStringError(errc::invalid_argument, Error);
561     }
562 
563     if (ExperimentalExtensionVersionCheck &&
564         (MajorStr.empty() && MinorStr.empty())) {
565       std::string Error =
566           "experimental extension requires explicit version number `" +
567           Ext.str() + "`";
568       return createStringError(errc::invalid_argument, Error);
569     }
570 
571     auto SupportedVers = *ExperimentalExtension;
572     if (ExperimentalExtensionVersionCheck &&
573         (Major != SupportedVers.Major || Minor != SupportedVers.Minor)) {
574       std::string Error = "unsupported version number " + MajorStr.str();
575       if (!MinorStr.empty())
576         Error += "." + MinorStr.str();
577       Error += " for experimental extension '" + Ext.str() +
578                "' (this compiler supports " + utostr(SupportedVers.Major) +
579                "." + utostr(SupportedVers.Minor) + ")";
580       return createStringError(errc::invalid_argument, Error);
581     }
582     return Error::success();
583   }
584 
585   // Exception rule for `g`, we don't have clear version scheme for that on
586   // ISA spec.
587   if (Ext == "g")
588     return Error::success();
589 
590   if (MajorStr.empty() && MinorStr.empty()) {
591     if (auto DefaultVersion = findDefaultVersion(Ext)) {
592       Major = DefaultVersion->Major;
593       Minor = DefaultVersion->Minor;
594     }
595     // No matter found or not, return success, assume other place will
596     // verify.
597     return Error::success();
598   }
599 
600   if (RISCVISAInfo::isSupportedExtension(Ext, Major, Minor))
601     return Error::success();
602 
603   std::string Error = "unsupported version number " + std::string(MajorStr);
604   if (!MinorStr.empty())
605     Error += "." + MinorStr.str();
606   Error += " for extension '" + Ext.str() + "'";
607   return createStringError(errc::invalid_argument, Error);
608 }
609 
610 llvm::Expected<std::unique_ptr<RISCVISAInfo>>
parseFeatures(unsigned XLen,const std::vector<std::string> & Features)611 RISCVISAInfo::parseFeatures(unsigned XLen,
612                             const std::vector<std::string> &Features) {
613   assert(XLen == 32 || XLen == 64);
614   std::unique_ptr<RISCVISAInfo> ISAInfo(new RISCVISAInfo(XLen));
615 
616   for (auto &Feature : Features) {
617     StringRef ExtName = Feature;
618     bool Experimental = false;
619     assert(ExtName.size() > 1 && (ExtName[0] == '+' || ExtName[0] == '-'));
620     bool Add = ExtName[0] == '+';
621     ExtName = ExtName.drop_front(1); // Drop '+' or '-'
622     Experimental = stripExperimentalPrefix(ExtName);
623     auto ExtensionInfos = Experimental
624                               ? ArrayRef(SupportedExperimentalExtensions)
625                               : ArrayRef(SupportedExtensions);
626     auto ExtensionInfoIterator =
627         llvm::lower_bound(ExtensionInfos, ExtName, LessExtName());
628 
629     // Not all features is related to ISA extension, like `relax` or
630     // `save-restore`, skip those feature.
631     if (ExtensionInfoIterator == ExtensionInfos.end() ||
632         ExtensionInfoIterator->Name != ExtName)
633       continue;
634 
635     if (Add)
636       ISAInfo->addExtension(ExtName, ExtensionInfoIterator->Version);
637     else
638       ISAInfo->Exts.erase(ExtName.str());
639   }
640 
641   return RISCVISAInfo::postProcessAndChecking(std::move(ISAInfo));
642 }
643 
644 llvm::Expected<std::unique_ptr<RISCVISAInfo>>
parseNormalizedArchString(StringRef Arch)645 RISCVISAInfo::parseNormalizedArchString(StringRef Arch) {
646   if (llvm::any_of(Arch, isupper)) {
647     return createStringError(errc::invalid_argument,
648                              "string must be lowercase");
649   }
650   // Must start with a valid base ISA name.
651   unsigned XLen;
652   if (Arch.starts_with("rv32i") || Arch.starts_with("rv32e"))
653     XLen = 32;
654   else if (Arch.starts_with("rv64i") || Arch.starts_with("rv64e"))
655     XLen = 64;
656   else
657     return createStringError(errc::invalid_argument,
658                              "arch string must begin with valid base ISA");
659   std::unique_ptr<RISCVISAInfo> ISAInfo(new RISCVISAInfo(XLen));
660   // Discard rv32/rv64 prefix.
661   Arch = Arch.substr(4);
662 
663   // Each extension is of the form ${name}${major_version}p${minor_version}
664   // and separated by _. Split by _ and then extract the name and version
665   // information for each extension.
666   SmallVector<StringRef, 8> Split;
667   Arch.split(Split, '_');
668   for (StringRef Ext : Split) {
669     StringRef Prefix, MinorVersionStr;
670     std::tie(Prefix, MinorVersionStr) = Ext.rsplit('p');
671     if (MinorVersionStr.empty())
672       return createStringError(errc::invalid_argument,
673                                "extension lacks version in expected format");
674     unsigned MajorVersion, MinorVersion;
675     if (MinorVersionStr.getAsInteger(10, MinorVersion))
676       return createStringError(errc::invalid_argument,
677                                "failed to parse minor version number");
678 
679     // Split Prefix into the extension name and the major version number
680     // (the trailing digits of Prefix).
681     int TrailingDigits = 0;
682     StringRef ExtName = Prefix;
683     while (!ExtName.empty()) {
684       if (!isDigit(ExtName.back()))
685         break;
686       ExtName = ExtName.drop_back(1);
687       TrailingDigits++;
688     }
689     if (!TrailingDigits)
690       return createStringError(errc::invalid_argument,
691                                "extension lacks version in expected format");
692 
693     StringRef MajorVersionStr = Prefix.take_back(TrailingDigits);
694     if (MajorVersionStr.getAsInteger(10, MajorVersion))
695       return createStringError(errc::invalid_argument,
696                                "failed to parse major version number");
697     ISAInfo->addExtension(ExtName, {MajorVersion, MinorVersion});
698   }
699   ISAInfo->updateFLen();
700   ISAInfo->updateMinVLen();
701   ISAInfo->updateMaxELen();
702   return std::move(ISAInfo);
703 }
704 
705 llvm::Expected<std::unique_ptr<RISCVISAInfo>>
parseArchString(StringRef Arch,bool EnableExperimentalExtension,bool ExperimentalExtensionVersionCheck,bool IgnoreUnknown)706 RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension,
707                               bool ExperimentalExtensionVersionCheck,
708                               bool IgnoreUnknown) {
709   // RISC-V ISA strings must be lowercase.
710   if (llvm::any_of(Arch, isupper)) {
711     return createStringError(errc::invalid_argument,
712                              "string must be lowercase");
713   }
714 
715   bool HasRV64 = Arch.starts_with("rv64");
716   // ISA string must begin with rv32 or rv64.
717   if (!(Arch.starts_with("rv32") || HasRV64) || (Arch.size() < 5)) {
718     return createStringError(
719         errc::invalid_argument,
720         "string must begin with rv32{i,e,g} or rv64{i,e,g}");
721   }
722 
723   unsigned XLen = HasRV64 ? 64 : 32;
724   std::unique_ptr<RISCVISAInfo> ISAInfo(new RISCVISAInfo(XLen));
725 
726   // The canonical order specified in ISA manual.
727   // Ref: Table 22.1 in RISC-V User-Level ISA V2.2
728   StringRef StdExts = AllStdExts;
729   char Baseline = Arch[4];
730 
731   // First letter should be 'e', 'i' or 'g'.
732   switch (Baseline) {
733   default:
734     return createStringError(errc::invalid_argument,
735                              "first letter should be 'e', 'i' or 'g'");
736   case 'e':
737   case 'i':
738     break;
739   case 'g':
740     // g expands to extensions in RISCVGImplications.
741     if (Arch.size() > 5 && isDigit(Arch[5]))
742       return createStringError(errc::invalid_argument,
743                                "version not supported for 'g'");
744     StdExts = StdExts.drop_front(4);
745     break;
746   }
747 
748   if (Arch.back() == '_')
749     return createStringError(errc::invalid_argument,
750                              "extension name missing after separator '_'");
751 
752   // Skip rvxxx
753   StringRef Exts = Arch.substr(5);
754 
755   // Remove multi-letter standard extensions, non-standard extensions and
756   // supervisor-level extensions. They have 'z', 'x', 's' prefixes.
757   // Parse them at the end.
758   // Find the very first occurrence of 's', 'x' or 'z'.
759   StringRef OtherExts;
760   size_t Pos = Exts.find_first_of("zsx");
761   if (Pos != StringRef::npos) {
762     OtherExts = Exts.substr(Pos);
763     Exts = Exts.substr(0, Pos);
764   }
765 
766   unsigned Major, Minor, ConsumeLength;
767   if (Baseline == 'g') {
768     // Versions for g are disallowed, and this was checked for previously.
769     ConsumeLength = 0;
770 
771     // No matter which version is given to `g`, we always set imafd to default
772     // version since the we don't have clear version scheme for that on
773     // ISA spec.
774     for (const auto *Ext : RISCVGImplications) {
775       if (auto Version = findDefaultVersion(Ext))
776         ISAInfo->addExtension(Ext, *Version);
777       else
778         llvm_unreachable("Default extension version not found?");
779     }
780   } else {
781     // Baseline is `i` or `e`
782     if (auto E = getExtensionVersion(
783             StringRef(&Baseline, 1), Exts, Major, Minor, ConsumeLength,
784             EnableExperimentalExtension, ExperimentalExtensionVersionCheck)) {
785       if (!IgnoreUnknown)
786         return std::move(E);
787       // If IgnoreUnknown, then ignore an unrecognised version of the baseline
788       // ISA and just use the default supported version.
789       consumeError(std::move(E));
790       auto Version = findDefaultVersion(StringRef(&Baseline, 1));
791       Major = Version->Major;
792       Minor = Version->Minor;
793     }
794 
795     ISAInfo->addExtension(StringRef(&Baseline, 1), {Major, Minor});
796   }
797 
798   // Consume the base ISA version number and any '_' between rvxxx and the
799   // first extension
800   Exts = Exts.drop_front(ConsumeLength);
801   Exts.consume_front("_");
802 
803   auto StdExtsItr = StdExts.begin();
804   auto StdExtsEnd = StdExts.end();
805   auto GoToNextExt = [](StringRef::iterator &I, unsigned ConsumeLength,
806                         StringRef::iterator E) {
807     I += 1 + ConsumeLength;
808     if (I != E && *I == '_')
809       ++I;
810   };
811   for (auto I = Exts.begin(), E = Exts.end(); I != E;) {
812     char C = *I;
813 
814     // Check ISA extensions are specified in the canonical order.
815     while (StdExtsItr != StdExtsEnd && *StdExtsItr != C)
816       ++StdExtsItr;
817 
818     if (StdExtsItr == StdExtsEnd) {
819       // Either c contains a valid extension but it was not given in
820       // canonical order or it is an invalid extension.
821       if (StdExts.contains(C)) {
822         return createStringError(
823             errc::invalid_argument,
824             "standard user-level extension not given in canonical order '%c'",
825             C);
826       }
827 
828       return createStringError(errc::invalid_argument,
829                                "invalid standard user-level extension '%c'", C);
830     }
831 
832     // Move to next char to prevent repeated letter.
833     ++StdExtsItr;
834 
835     StringRef Next;
836     unsigned Major, Minor, ConsumeLength;
837     if (std::next(I) != E)
838       Next = StringRef(std::next(I), E - std::next(I));
839     if (auto E = getExtensionVersion(StringRef(&C, 1), Next, Major, Minor,
840                                      ConsumeLength, EnableExperimentalExtension,
841                                      ExperimentalExtensionVersionCheck)) {
842       if (IgnoreUnknown) {
843         consumeError(std::move(E));
844         GoToNextExt(I, ConsumeLength, Exts.end());
845         continue;
846       }
847       return std::move(E);
848     }
849 
850     // The order is OK, then push it into features.
851     // Currently LLVM supports only "mafdcvh".
852     if (!isSupportedExtension(StringRef(&C, 1))) {
853       if (IgnoreUnknown) {
854         GoToNextExt(I, ConsumeLength, Exts.end());
855         continue;
856       }
857       return createStringError(errc::invalid_argument,
858                                "unsupported standard user-level extension '%c'",
859                                C);
860     }
861     ISAInfo->addExtension(StringRef(&C, 1), {Major, Minor});
862 
863     // Consume full extension name and version, including any optional '_'
864     // between this extension and the next
865     GoToNextExt(I, ConsumeLength, Exts.end());
866   }
867 
868   // Handle other types of extensions other than the standard
869   // general purpose and standard user-level extensions.
870   // Parse the ISA string containing non-standard user-level
871   // extensions, standard supervisor-level extensions and
872   // non-standard supervisor-level extensions.
873   // These extensions start with 'z', 's', 'x' prefixes, might have a version
874   // number (major, minor) and are separated by a single underscore '_'. We do
875   // not enforce a canonical order for them.
876   // Set the hardware features for the extensions that are supported.
877 
878   // Multi-letter extensions are seperated by a single underscore
879   // as described in RISC-V User-Level ISA V2.2.
880   SmallVector<StringRef, 8> Split;
881   OtherExts.split(Split, '_');
882 
883   SmallVector<StringRef, 8> AllExts;
884   if (Split.size() > 1 || Split[0] != "") {
885     for (StringRef Ext : Split) {
886       if (Ext.empty())
887         return createStringError(errc::invalid_argument,
888                                  "extension name missing after separator '_'");
889 
890       StringRef Type = getExtensionType(Ext);
891       StringRef Desc = getExtensionTypeDesc(Ext);
892       auto Pos = findLastNonVersionCharacter(Ext) + 1;
893       StringRef Name(Ext.substr(0, Pos));
894       StringRef Vers(Ext.substr(Pos));
895 
896       if (Type.empty()) {
897         if (IgnoreUnknown)
898           continue;
899         return createStringError(errc::invalid_argument,
900                                  "invalid extension prefix '" + Ext + "'");
901       }
902 
903       if (!IgnoreUnknown && Name.size() == Type.size()) {
904         return createStringError(errc::invalid_argument,
905                                  "%s name missing after '%s'",
906                                  Desc.str().c_str(), Type.str().c_str());
907       }
908 
909       unsigned Major, Minor, ConsumeLength;
910       if (auto E = getExtensionVersion(Name, Vers, Major, Minor, ConsumeLength,
911                                        EnableExperimentalExtension,
912                                        ExperimentalExtensionVersionCheck)) {
913         if (IgnoreUnknown) {
914           consumeError(std::move(E));
915           continue;
916         }
917         return std::move(E);
918       }
919 
920       // Check if duplicated extension.
921       if (!IgnoreUnknown && llvm::is_contained(AllExts, Name)) {
922         return createStringError(errc::invalid_argument, "duplicated %s '%s'",
923                                  Desc.str().c_str(), Name.str().c_str());
924       }
925 
926       if (IgnoreUnknown && !isSupportedExtension(Name))
927         continue;
928 
929       ISAInfo->addExtension(Name, {Major, Minor});
930       // Extension format is correct, keep parsing the extensions.
931       // TODO: Save Type, Name, Major, Minor to avoid parsing them later.
932       AllExts.push_back(Name);
933     }
934   }
935 
936   for (auto Ext : AllExts) {
937     if (!isSupportedExtension(Ext)) {
938       StringRef Desc = getExtensionTypeDesc(getExtensionType(Ext));
939       return createStringError(errc::invalid_argument, "unsupported %s '%s'",
940                                Desc.str().c_str(), Ext.str().c_str());
941     }
942   }
943 
944   return RISCVISAInfo::postProcessAndChecking(std::move(ISAInfo));
945 }
946 
checkDependency()947 Error RISCVISAInfo::checkDependency() {
948   bool HasC = Exts.count("c") != 0;
949   bool HasF = Exts.count("f") != 0;
950   bool HasZfinx = Exts.count("zfinx") != 0;
951   bool HasVector = Exts.count("zve32x") != 0;
952   bool HasZvl = MinVLen != 0;
953   bool HasZcmt = Exts.count("zcmt") != 0;
954 
955   if (HasF && HasZfinx)
956     return createStringError(errc::invalid_argument,
957                              "'f' and 'zfinx' extensions are incompatible");
958 
959   if (HasZvl && !HasVector)
960     return createStringError(
961         errc::invalid_argument,
962         "'zvl*b' requires 'v' or 'zve*' extension to also be specified");
963 
964   if (Exts.count("zvbb") && !HasVector)
965     return createStringError(
966         errc::invalid_argument,
967         "'zvbb' requires 'v' or 'zve*' extension to also be specified");
968 
969   if (Exts.count("zvbc") && !Exts.count("zve64x"))
970     return createStringError(
971         errc::invalid_argument,
972         "'zvbc' requires 'v' or 'zve64*' extension to also be specified");
973 
974   if ((Exts.count("zvkg") || Exts.count("zvkned") || Exts.count("zvknha") ||
975        Exts.count("zvksed") || Exts.count("zvksh")) &&
976       !HasVector)
977     return createStringError(
978         errc::invalid_argument,
979         "'zvk*' requires 'v' or 'zve*' extension to also be specified");
980 
981   if (Exts.count("zvknhb") && !Exts.count("zve64x"))
982     return createStringError(
983         errc::invalid_argument,
984         "'zvknhb' requires 'v' or 'zve64*' extension to also be specified");
985 
986   if ((HasZcmt || Exts.count("zcmp")) && Exts.count("d") &&
987       (HasC || Exts.count("zcd")))
988     return createStringError(
989         errc::invalid_argument,
990         Twine("'") + (HasZcmt ? "zcmt" : "zcmp") +
991         "' extension is incompatible with '" + (HasC ? "c" : "zcd") +
992         "' extension when 'd' extension is enabled");
993 
994   if (XLen != 32 && Exts.count("zcf"))
995     return createStringError(errc::invalid_argument,
996                              "'zcf' is only supported for 'rv32'");
997 
998   return Error::success();
999 }
1000 
1001 static const char *ImpliedExtsD[] = {"f"};
1002 static const char *ImpliedExtsF[] = {"zicsr"};
1003 static const char *ImpliedExtsV[] = {"zvl128b", "zve64d"};
1004 static const char *ImpliedExtsXTHeadVdot[] = {"v"};
1005 static const char *ImpliedExtsXSfvcp[] = {"zve32x"};
1006 static const char *ImpliedExtsXSfvfnrclipxfqf[] = {"zve32f"};
1007 static const char *ImpliedExtsXSfvfwmaccqqq[] = {"zvfbfmin"};
1008 static const char *ImpliedExtsXSfvqmaccdod[] = {"zve32x"};
1009 static const char *ImpliedExtsXSfvqmaccqoq[] = {"zve32x"};
1010 static const char *ImpliedExtsZacas[] = {"a"};
1011 static const char *ImpliedExtsZcb[] = {"zca"};
1012 static const char *ImpliedExtsZcd[] = {"d", "zca"};
1013 static const char *ImpliedExtsZce[] = {"zcb", "zcmp", "zcmt"};
1014 static const char *ImpliedExtsZcf[] = {"f", "zca"};
1015 static const char *ImpliedExtsZcmop[] = {"zca"};
1016 static const char *ImpliedExtsZcmp[] = {"zca"};
1017 static const char *ImpliedExtsZcmt[] = {"zca", "zicsr"};
1018 static const char *ImpliedExtsZdinx[] = {"zfinx"};
1019 static const char *ImpliedExtsZfa[] = {"f"};
1020 static const char *ImpliedExtsZfbfmin[] = {"f"};
1021 static const char *ImpliedExtsZfh[] = {"zfhmin"};
1022 static const char *ImpliedExtsZfhmin[] = {"f"};
1023 static const char *ImpliedExtsZfinx[] = {"zicsr"};
1024 static const char *ImpliedExtsZhinx[] = {"zhinxmin"};
1025 static const char *ImpliedExtsZhinxmin[] = {"zfinx"};
1026 static const char *ImpliedExtsZicntr[] = {"zicsr"};
1027 static const char *ImpliedExtsZicfiss[] = {"zicsr", "zimop"};
1028 static const char *ImpliedExtsZihpm[] = {"zicsr"};
1029 static const char *ImpliedExtsZk[] = {"zkn", "zkt", "zkr"};
1030 static const char *ImpliedExtsZkn[] = {"zbkb", "zbkc", "zbkx",
1031                                        "zkne", "zknd", "zknh"};
1032 static const char *ImpliedExtsZks[] = {"zbkb", "zbkc", "zbkx", "zksed", "zksh"};
1033 static const char *ImpliedExtsZvbb[] = {"zvkb"};
1034 static const char *ImpliedExtsZve32f[] = {"zve32x", "f"};
1035 static const char *ImpliedExtsZve32x[] = {"zvl32b", "zicsr"};
1036 static const char *ImpliedExtsZve64d[] = {"zve64f", "d"};
1037 static const char *ImpliedExtsZve64f[] = {"zve64x", "zve32f"};
1038 static const char *ImpliedExtsZve64x[] = {"zve32x", "zvl64b"};
1039 static const char *ImpliedExtsZvfbfmin[] = {"zve32f"};
1040 static const char *ImpliedExtsZvfbfwma[] = {"zvfbfmin", "zfbfmin"};
1041 static const char *ImpliedExtsZvfh[] = {"zvfhmin", "zfhmin"};
1042 static const char *ImpliedExtsZvfhmin[] = {"zve32f"};
1043 static const char *ImpliedExtsZvkn[] = {"zvkb", "zvkned", "zvknhb", "zvkt"};
1044 static const char *ImpliedExtsZvknc[] = {"zvbc", "zvkn"};
1045 static const char *ImpliedExtsZvkng[] = {"zvkg", "zvkn"};
1046 static const char *ImpliedExtsZvknhb[] = {"zve64x"};
1047 static const char *ImpliedExtsZvks[] = {"zvkb", "zvksed", "zvksh", "zvkt"};
1048 static const char *ImpliedExtsZvksc[] = {"zvbc", "zvks"};
1049 static const char *ImpliedExtsZvksg[] = {"zvkg", "zvks"};
1050 static const char *ImpliedExtsZvl1024b[] = {"zvl512b"};
1051 static const char *ImpliedExtsZvl128b[] = {"zvl64b"};
1052 static const char *ImpliedExtsZvl16384b[] = {"zvl8192b"};
1053 static const char *ImpliedExtsZvl2048b[] = {"zvl1024b"};
1054 static const char *ImpliedExtsZvl256b[] = {"zvl128b"};
1055 static const char *ImpliedExtsZvl32768b[] = {"zvl16384b"};
1056 static const char *ImpliedExtsZvl4096b[] = {"zvl2048b"};
1057 static const char *ImpliedExtsZvl512b[] = {"zvl256b"};
1058 static const char *ImpliedExtsZvl64b[] = {"zvl32b"};
1059 static const char *ImpliedExtsZvl65536b[] = {"zvl32768b"};
1060 static const char *ImpliedExtsZvl8192b[] = {"zvl4096b"};
1061 
1062 struct ImpliedExtsEntry {
1063   StringLiteral Name;
1064   ArrayRef<const char *> Exts;
1065 
operator <ImpliedExtsEntry1066   bool operator<(const ImpliedExtsEntry &Other) const {
1067     return Name < Other.Name;
1068   }
1069 
operator <ImpliedExtsEntry1070   bool operator<(StringRef Other) const { return Name < Other; }
1071 };
1072 
1073 // Note: The table needs to be sorted by name.
1074 static constexpr ImpliedExtsEntry ImpliedExts[] = {
1075     {{"d"}, {ImpliedExtsD}},
1076     {{"f"}, {ImpliedExtsF}},
1077     {{"v"}, {ImpliedExtsV}},
1078     {{"xsfvcp"}, {ImpliedExtsXSfvcp}},
1079     {{"xsfvfnrclipxfqf"}, {ImpliedExtsXSfvfnrclipxfqf}},
1080     {{"xsfvfwmaccqqq"}, {ImpliedExtsXSfvfwmaccqqq}},
1081     {{"xsfvqmaccdod"}, {ImpliedExtsXSfvqmaccdod}},
1082     {{"xsfvqmaccqoq"}, {ImpliedExtsXSfvqmaccqoq}},
1083     {{"xtheadvdot"}, {ImpliedExtsXTHeadVdot}},
1084     {{"zacas"}, {ImpliedExtsZacas}},
1085     {{"zcb"}, {ImpliedExtsZcb}},
1086     {{"zcd"}, {ImpliedExtsZcd}},
1087     {{"zce"}, {ImpliedExtsZce}},
1088     {{"zcf"}, {ImpliedExtsZcf}},
1089     {{"zcmop"}, {ImpliedExtsZcmop}},
1090     {{"zcmp"}, {ImpliedExtsZcmp}},
1091     {{"zcmt"}, {ImpliedExtsZcmt}},
1092     {{"zdinx"}, {ImpliedExtsZdinx}},
1093     {{"zfa"}, {ImpliedExtsZfa}},
1094     {{"zfbfmin"}, {ImpliedExtsZfbfmin}},
1095     {{"zfh"}, {ImpliedExtsZfh}},
1096     {{"zfhmin"}, {ImpliedExtsZfhmin}},
1097     {{"zfinx"}, {ImpliedExtsZfinx}},
1098     {{"zhinx"}, {ImpliedExtsZhinx}},
1099     {{"zhinxmin"}, {ImpliedExtsZhinxmin}},
1100     {{"zicfiss"}, {ImpliedExtsZicfiss}},
1101     {{"zicntr"}, {ImpliedExtsZicntr}},
1102     {{"zihpm"}, {ImpliedExtsZihpm}},
1103     {{"zk"}, {ImpliedExtsZk}},
1104     {{"zkn"}, {ImpliedExtsZkn}},
1105     {{"zks"}, {ImpliedExtsZks}},
1106     {{"zvbb"}, {ImpliedExtsZvbb}},
1107     {{"zve32f"}, {ImpliedExtsZve32f}},
1108     {{"zve32x"}, {ImpliedExtsZve32x}},
1109     {{"zve64d"}, {ImpliedExtsZve64d}},
1110     {{"zve64f"}, {ImpliedExtsZve64f}},
1111     {{"zve64x"}, {ImpliedExtsZve64x}},
1112     {{"zvfbfmin"}, {ImpliedExtsZvfbfmin}},
1113     {{"zvfbfwma"}, {ImpliedExtsZvfbfwma}},
1114     {{"zvfh"}, {ImpliedExtsZvfh}},
1115     {{"zvfhmin"}, {ImpliedExtsZvfhmin}},
1116     {{"zvkn"}, {ImpliedExtsZvkn}},
1117     {{"zvknc"}, {ImpliedExtsZvknc}},
1118     {{"zvkng"}, {ImpliedExtsZvkng}},
1119     {{"zvknhb"}, {ImpliedExtsZvknhb}},
1120     {{"zvks"}, {ImpliedExtsZvks}},
1121     {{"zvksc"}, {ImpliedExtsZvksc}},
1122     {{"zvksg"}, {ImpliedExtsZvksg}},
1123     {{"zvl1024b"}, {ImpliedExtsZvl1024b}},
1124     {{"zvl128b"}, {ImpliedExtsZvl128b}},
1125     {{"zvl16384b"}, {ImpliedExtsZvl16384b}},
1126     {{"zvl2048b"}, {ImpliedExtsZvl2048b}},
1127     {{"zvl256b"}, {ImpliedExtsZvl256b}},
1128     {{"zvl32768b"}, {ImpliedExtsZvl32768b}},
1129     {{"zvl4096b"}, {ImpliedExtsZvl4096b}},
1130     {{"zvl512b"}, {ImpliedExtsZvl512b}},
1131     {{"zvl64b"}, {ImpliedExtsZvl64b}},
1132     {{"zvl65536b"}, {ImpliedExtsZvl65536b}},
1133     {{"zvl8192b"}, {ImpliedExtsZvl8192b}},
1134 };
1135 
updateImplication()1136 void RISCVISAInfo::updateImplication() {
1137   bool HasE = Exts.count("e") != 0;
1138   bool HasI = Exts.count("i") != 0;
1139 
1140   // If not in e extension and i extension does not exist, i extension is
1141   // implied
1142   if (!HasE && !HasI) {
1143     auto Version = findDefaultVersion("i");
1144     addExtension("i", Version.value());
1145   }
1146 
1147   assert(llvm::is_sorted(ImpliedExts) && "Table not sorted by Name");
1148 
1149   // This loop may execute over 1 iteration since implication can be layered
1150   // Exits loop if no more implication is applied
1151   SmallSetVector<StringRef, 16> WorkList;
1152   for (auto const &Ext : Exts)
1153     WorkList.insert(Ext.first);
1154 
1155   while (!WorkList.empty()) {
1156     StringRef ExtName = WorkList.pop_back_val();
1157     auto I = llvm::lower_bound(ImpliedExts, ExtName);
1158     if (I != std::end(ImpliedExts) && I->Name == ExtName) {
1159       for (const char *ImpliedExt : I->Exts) {
1160         if (WorkList.count(ImpliedExt))
1161           continue;
1162         if (Exts.count(ImpliedExt))
1163           continue;
1164         auto Version = findDefaultVersion(ImpliedExt);
1165         addExtension(ImpliedExt, Version.value());
1166         WorkList.insert(ImpliedExt);
1167       }
1168     }
1169   }
1170 
1171   // Add Zcf if Zce and F are enabled on RV32.
1172   if (XLen == 32 && Exts.count("zce") && Exts.count("f") &&
1173       !Exts.count("zcf")) {
1174     auto Version = findDefaultVersion("zcf");
1175     addExtension("zcf", Version.value());
1176   }
1177 }
1178 
1179 struct CombinedExtsEntry {
1180   StringLiteral CombineExt;
1181   ArrayRef<const char *> RequiredExts;
1182 };
1183 
1184 static constexpr CombinedExtsEntry CombineIntoExts[] = {
1185     {{"zk"}, {ImpliedExtsZk}},
1186     {{"zkn"}, {ImpliedExtsZkn}},
1187     {{"zks"}, {ImpliedExtsZks}},
1188     {{"zvkn"}, {ImpliedExtsZvkn}},
1189     {{"zvknc"}, {ImpliedExtsZvknc}},
1190     {{"zvkng"}, {ImpliedExtsZvkng}},
1191     {{"zvks"}, {ImpliedExtsZvks}},
1192     {{"zvksc"}, {ImpliedExtsZvksc}},
1193     {{"zvksg"}, {ImpliedExtsZvksg}},
1194 };
1195 
updateCombination()1196 void RISCVISAInfo::updateCombination() {
1197   bool IsNewCombine = false;
1198   do {
1199     IsNewCombine = false;
1200     for (CombinedExtsEntry CombineIntoExt : CombineIntoExts) {
1201       auto CombineExt = CombineIntoExt.CombineExt;
1202       auto RequiredExts = CombineIntoExt.RequiredExts;
1203       if (hasExtension(CombineExt))
1204         continue;
1205       bool IsAllRequiredFeatureExist = true;
1206       for (const char *Ext : RequiredExts)
1207         IsAllRequiredFeatureExist &= hasExtension(Ext);
1208       if (IsAllRequiredFeatureExist) {
1209         auto Version = findDefaultVersion(CombineExt);
1210         addExtension(CombineExt, Version.value());
1211         IsNewCombine = true;
1212       }
1213     }
1214   } while (IsNewCombine);
1215 }
1216 
updateFLen()1217 void RISCVISAInfo::updateFLen() {
1218   FLen = 0;
1219   // TODO: Handle q extension.
1220   if (Exts.count("d"))
1221     FLen = 64;
1222   else if (Exts.count("f"))
1223     FLen = 32;
1224 }
1225 
updateMinVLen()1226 void RISCVISAInfo::updateMinVLen() {
1227   for (auto const &Ext : Exts) {
1228     StringRef ExtName = Ext.first;
1229     bool IsZvlExt = ExtName.consume_front("zvl") && ExtName.consume_back("b");
1230     if (IsZvlExt) {
1231       unsigned ZvlLen;
1232       if (!ExtName.getAsInteger(10, ZvlLen))
1233         MinVLen = std::max(MinVLen, ZvlLen);
1234     }
1235   }
1236 }
1237 
updateMaxELen()1238 void RISCVISAInfo::updateMaxELen() {
1239   // handles EEW restriction by sub-extension zve
1240   for (auto const &Ext : Exts) {
1241     StringRef ExtName = Ext.first;
1242     bool IsZveExt = ExtName.consume_front("zve");
1243     if (IsZveExt) {
1244       if (ExtName.back() == 'f')
1245         MaxELenFp = std::max(MaxELenFp, 32u);
1246       if (ExtName.back() == 'd')
1247         MaxELenFp = std::max(MaxELenFp, 64u);
1248       ExtName = ExtName.drop_back();
1249       unsigned ZveELen;
1250       ExtName.getAsInteger(10, ZveELen);
1251       MaxELen = std::max(MaxELen, ZveELen);
1252     }
1253   }
1254 }
1255 
toString() const1256 std::string RISCVISAInfo::toString() const {
1257   std::string Buffer;
1258   raw_string_ostream Arch(Buffer);
1259 
1260   Arch << "rv" << XLen;
1261 
1262   ListSeparator LS("_");
1263   for (auto const &Ext : Exts) {
1264     StringRef ExtName = Ext.first;
1265     auto ExtInfo = Ext.second;
1266     Arch << LS << ExtName;
1267     Arch << ExtInfo.Major << "p" << ExtInfo.Minor;
1268   }
1269 
1270   return Arch.str();
1271 }
1272 
1273 llvm::Expected<std::unique_ptr<RISCVISAInfo>>
postProcessAndChecking(std::unique_ptr<RISCVISAInfo> && ISAInfo)1274 RISCVISAInfo::postProcessAndChecking(std::unique_ptr<RISCVISAInfo> &&ISAInfo) {
1275   ISAInfo->updateImplication();
1276   ISAInfo->updateCombination();
1277   ISAInfo->updateFLen();
1278   ISAInfo->updateMinVLen();
1279   ISAInfo->updateMaxELen();
1280 
1281   if (Error Result = ISAInfo->checkDependency())
1282     return std::move(Result);
1283   return std::move(ISAInfo);
1284 }
1285 
computeDefaultABI() const1286 StringRef RISCVISAInfo::computeDefaultABI() const {
1287   if (XLen == 32) {
1288     if (hasExtension("e"))
1289       return "ilp32e";
1290     if (hasExtension("d"))
1291       return "ilp32d";
1292     if (hasExtension("f"))
1293       return "ilp32f";
1294     return "ilp32";
1295   } else if (XLen == 64) {
1296     if (hasExtension("e"))
1297       return "lp64e";
1298     if (hasExtension("d"))
1299       return "lp64d";
1300     if (hasExtension("f"))
1301       return "lp64f";
1302     return "lp64";
1303   }
1304   llvm_unreachable("Invalid XLEN");
1305 }
1306 
isSupportedExtensionWithVersion(StringRef Ext)1307 bool RISCVISAInfo::isSupportedExtensionWithVersion(StringRef Ext) {
1308   if (Ext.empty())
1309     return false;
1310 
1311   auto Pos = findLastNonVersionCharacter(Ext) + 1;
1312   StringRef Name = Ext.substr(0, Pos);
1313   StringRef Vers = Ext.substr(Pos);
1314   if (Vers.empty())
1315     return false;
1316 
1317   unsigned Major, Minor, ConsumeLength;
1318   if (auto E = getExtensionVersion(Name, Vers, Major, Minor, ConsumeLength,
1319                                    true, true)) {
1320     consumeError(std::move(E));
1321     return false;
1322   }
1323 
1324   return true;
1325 }
1326 
getTargetFeatureForExtension(StringRef Ext)1327 std::string RISCVISAInfo::getTargetFeatureForExtension(StringRef Ext) {
1328   if (Ext.empty())
1329     return std::string();
1330 
1331   auto Pos = findLastNonVersionCharacter(Ext) + 1;
1332   StringRef Name = Ext.substr(0, Pos);
1333 
1334   if (Pos != Ext.size() && !isSupportedExtensionWithVersion(Ext))
1335     return std::string();
1336 
1337   if (!isSupportedExtension(Name))
1338     return std::string();
1339 
1340   return isExperimentalExtension(Name) ? "experimental-" + Name.str()
1341                                        : Name.str();
1342 }
1343