xref: /freebsd/contrib/llvm-project/llvm/lib/TargetParser/RISCVISAInfo.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1 //===-- RISCVISAInfo.cpp - RISC-V Arch String Parser ----------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "llvm/TargetParser/RISCVISAInfo.h"
10 #include "llvm/ADT/STLExtras.h"
11 #include "llvm/ADT/StringExtras.h"
12 #include "llvm/ADT/StringRef.h"
13 #include "llvm/Support/Errc.h"
14 #include "llvm/Support/Error.h"
15 #include "llvm/Support/raw_ostream.h"
16 
17 #include <array>
18 #include <atomic>
19 #include <optional>
20 #include <string>
21 #include <vector>
22 
23 using namespace llvm;
24 
25 namespace {
26 
27 struct RISCVSupportedExtension {
28   const char *Name;
29   /// Supported version.
30   RISCVISAUtils::ExtensionVersion Version;
31 
operator <__anond3db02a30111::RISCVSupportedExtension32   bool operator<(const RISCVSupportedExtension &RHS) const {
33     return StringRef(Name) < StringRef(RHS.Name);
34   }
35 };
36 
37 struct RISCVProfile {
38   StringLiteral Name;
39   StringLiteral MArch;
40 
operator <__anond3db02a30111::RISCVProfile41   bool operator<(const RISCVProfile &RHS) const {
42     return StringRef(Name) < StringRef(RHS.Name);
43   }
44 };
45 
46 } // end anonymous namespace
47 
48 static const char *RISCVGImplications[] = {
49   "i", "m", "a", "f", "d", "zicsr", "zifencei"
50 };
51 
52 #define GET_SUPPORTED_EXTENSIONS
53 #include "llvm/TargetParser/RISCVTargetParserDef.inc"
54 
55 #define GET_SUPPORTED_PROFILES
56 #include "llvm/TargetParser/RISCVTargetParserDef.inc"
57 
verifyTables()58 static void verifyTables() {
59 #ifndef NDEBUG
60   static std::atomic<bool> TableChecked(false);
61   if (!TableChecked.load(std::memory_order_relaxed)) {
62     assert(llvm::is_sorted(SupportedExtensions) &&
63            "Extensions are not sorted by name");
64     assert(llvm::is_sorted(SupportedExperimentalExtensions) &&
65            "Experimental extensions are not sorted by name");
66     assert(llvm::is_sorted(SupportedProfiles) &&
67            "Profiles are not sorted by name");
68     assert(llvm::is_sorted(SupportedExperimentalProfiles) &&
69            "Experimental profiles are not sorted by name");
70     TableChecked.store(true, std::memory_order_relaxed);
71   }
72 #endif
73 }
74 
PrintExtension(StringRef Name,StringRef Version,StringRef Description)75 static void PrintExtension(StringRef Name, StringRef Version,
76                            StringRef Description) {
77   outs().indent(4);
78   unsigned VersionWidth = Description.empty() ? 0 : 10;
79   outs() << left_justify(Name, 21) << left_justify(Version, VersionWidth)
80          << Description << "\n";
81 }
82 
printSupportedExtensions(StringMap<StringRef> & DescMap)83 void RISCVISAInfo::printSupportedExtensions(StringMap<StringRef> &DescMap) {
84   outs() << "All available -march extensions for RISC-V\n\n";
85   PrintExtension("Name", "Version", (DescMap.empty() ? "" : "Description"));
86 
87   RISCVISAUtils::OrderedExtensionMap ExtMap;
88   for (const auto &E : SupportedExtensions)
89     ExtMap[E.Name] = {E.Version.Major, E.Version.Minor};
90   for (const auto &E : ExtMap) {
91     std::string Version =
92         std::to_string(E.second.Major) + "." + std::to_string(E.second.Minor);
93     PrintExtension(E.first, Version, DescMap[E.first]);
94   }
95 
96   outs() << "\nExperimental extensions\n";
97   ExtMap.clear();
98   for (const auto &E : SupportedExperimentalExtensions)
99     ExtMap[E.Name] = {E.Version.Major, E.Version.Minor};
100   for (const auto &E : ExtMap) {
101     std::string Version =
102         std::to_string(E.second.Major) + "." + std::to_string(E.second.Minor);
103     PrintExtension(E.first, Version, DescMap["experimental-" + E.first]);
104   }
105 
106   outs() << "\nSupported Profiles\n";
107   for (const auto &P : SupportedProfiles)
108     outs().indent(4) << P.Name << "\n";
109 
110   outs() << "\nExperimental Profiles\n";
111   for (const auto &P : SupportedExperimentalProfiles)
112     outs().indent(4) << P.Name << "\n";
113 
114   outs() << "\nUse -march to specify the target's extension.\n"
115             "For example, clang -march=rv32i_v1p0\n";
116 }
117 
printEnabledExtensions(bool IsRV64,std::set<StringRef> & EnabledFeatureNames,StringMap<StringRef> & DescMap)118 void RISCVISAInfo::printEnabledExtensions(
119     bool IsRV64, std::set<StringRef> &EnabledFeatureNames,
120     StringMap<StringRef> &DescMap) {
121   outs() << "Extensions enabled for the given RISC-V target\n\n";
122   PrintExtension("Name", "Version", (DescMap.empty() ? "" : "Description"));
123 
124   RISCVISAUtils::OrderedExtensionMap FullExtMap;
125   RISCVISAUtils::OrderedExtensionMap ExtMap;
126   for (const auto &E : SupportedExtensions)
127     if (EnabledFeatureNames.count(E.Name) != 0) {
128       FullExtMap[E.Name] = {E.Version.Major, E.Version.Minor};
129       ExtMap[E.Name] = {E.Version.Major, E.Version.Minor};
130     }
131   for (const auto &E : ExtMap) {
132     std::string Version =
133         std::to_string(E.second.Major) + "." + std::to_string(E.second.Minor);
134     PrintExtension(E.first, Version, DescMap[E.first]);
135   }
136 
137   outs() << "\nExperimental extensions\n";
138   ExtMap.clear();
139   for (const auto &E : SupportedExperimentalExtensions) {
140     StringRef Name(E.Name);
141     if (EnabledFeatureNames.count("experimental-" + Name.str()) != 0) {
142       FullExtMap[E.Name] = {E.Version.Major, E.Version.Minor};
143       ExtMap[E.Name] = {E.Version.Major, E.Version.Minor};
144     }
145   }
146   for (const auto &E : ExtMap) {
147     std::string Version =
148         std::to_string(E.second.Major) + "." + std::to_string(E.second.Minor);
149     PrintExtension(E.first, Version, DescMap["experimental-" + E.first]);
150   }
151 
152   unsigned XLen = IsRV64 ? 64 : 32;
153   if (auto ISAString = RISCVISAInfo::createFromExtMap(XLen, FullExtMap))
154     outs() << "\nISA String: " << ISAString.get()->toString() << "\n";
155 }
156 
stripExperimentalPrefix(StringRef & Ext)157 static bool stripExperimentalPrefix(StringRef &Ext) {
158   return Ext.consume_front("experimental-");
159 }
160 
161 // This function finds the last character that doesn't belong to a version
162 // (e.g. zba1p0 is extension 'zba' of version '1p0'). So the function will
163 // consume [0-9]*p[0-9]* starting from the backward. An extension name will not
164 // end with a digit or the letter 'p', so this function will parse correctly.
165 // NOTE: This function is NOT able to take empty strings or strings that only
166 // have version numbers and no extension name. It assumes the extension name
167 // will be at least more than one character.
findLastNonVersionCharacter(StringRef Ext)168 static size_t findLastNonVersionCharacter(StringRef Ext) {
169   assert(!Ext.empty() &&
170          "Already guarded by if-statement in ::parseArchString");
171 
172   int Pos = Ext.size() - 1;
173   while (Pos > 0 && isDigit(Ext[Pos]))
174     Pos--;
175   if (Pos > 0 && Ext[Pos] == 'p' && isDigit(Ext[Pos - 1])) {
176     Pos--;
177     while (Pos > 0 && isDigit(Ext[Pos]))
178       Pos--;
179   }
180   return Pos;
181 }
182 
183 namespace {
184 struct LessExtName {
operator ()__anond3db02a30211::LessExtName185   bool operator()(const RISCVSupportedExtension &LHS, StringRef RHS) {
186     return StringRef(LHS.Name) < RHS;
187   }
operator ()__anond3db02a30211::LessExtName188   bool operator()(StringRef LHS, const RISCVSupportedExtension &RHS) {
189     return LHS < StringRef(RHS.Name);
190   }
191 };
192 } // namespace
193 
194 static std::optional<RISCVISAUtils::ExtensionVersion>
findDefaultVersion(StringRef ExtName)195 findDefaultVersion(StringRef ExtName) {
196   // Find default version of an extension.
197   // TODO: We might set default version based on profile or ISA spec.
198   for (auto &ExtInfo : {ArrayRef(SupportedExtensions),
199                         ArrayRef(SupportedExperimentalExtensions)}) {
200     auto I = llvm::lower_bound(ExtInfo, ExtName, LessExtName());
201 
202     if (I == ExtInfo.end() || I->Name != ExtName)
203       continue;
204 
205     return I->Version;
206   }
207   return std::nullopt;
208 }
209 
getExtensionTypeDesc(StringRef Ext)210 static StringRef getExtensionTypeDesc(StringRef Ext) {
211   if (Ext.starts_with('s'))
212     return "standard supervisor-level extension";
213   if (Ext.starts_with('x'))
214     return "non-standard user-level extension";
215   if (Ext.starts_with('z'))
216     return "standard user-level extension";
217   return StringRef();
218 }
219 
getExtensionType(StringRef Ext)220 static StringRef getExtensionType(StringRef Ext) {
221   if (Ext.starts_with('s'))
222     return "s";
223   if (Ext.starts_with('x'))
224     return "x";
225   if (Ext.starts_with('z'))
226     return "z";
227   return StringRef();
228 }
229 
230 static std::optional<RISCVISAUtils::ExtensionVersion>
isExperimentalExtension(StringRef Ext)231 isExperimentalExtension(StringRef Ext) {
232   auto I =
233       llvm::lower_bound(SupportedExperimentalExtensions, Ext, LessExtName());
234   if (I == std::end(SupportedExperimentalExtensions) || I->Name != Ext)
235     return std::nullopt;
236 
237   return I->Version;
238 }
239 
isSupportedExtensionFeature(StringRef Ext)240 bool RISCVISAInfo::isSupportedExtensionFeature(StringRef Ext) {
241   bool IsExperimental = stripExperimentalPrefix(Ext);
242 
243   ArrayRef<RISCVSupportedExtension> ExtInfo =
244       IsExperimental ? ArrayRef(SupportedExperimentalExtensions)
245                      : ArrayRef(SupportedExtensions);
246 
247   auto I = llvm::lower_bound(ExtInfo, Ext, LessExtName());
248   return I != ExtInfo.end() && I->Name == Ext;
249 }
250 
isSupportedExtension(StringRef Ext)251 bool RISCVISAInfo::isSupportedExtension(StringRef Ext) {
252   verifyTables();
253 
254   for (auto ExtInfo : {ArrayRef(SupportedExtensions),
255                        ArrayRef(SupportedExperimentalExtensions)}) {
256     auto I = llvm::lower_bound(ExtInfo, Ext, LessExtName());
257     if (I != ExtInfo.end() && I->Name == Ext)
258       return true;
259   }
260 
261   return false;
262 }
263 
isSupportedExtension(StringRef Ext,unsigned MajorVersion,unsigned MinorVersion)264 bool RISCVISAInfo::isSupportedExtension(StringRef Ext, unsigned MajorVersion,
265                                         unsigned MinorVersion) {
266   for (auto ExtInfo : {ArrayRef(SupportedExtensions),
267                        ArrayRef(SupportedExperimentalExtensions)}) {
268     auto Range =
269         std::equal_range(ExtInfo.begin(), ExtInfo.end(), Ext, LessExtName());
270     for (auto I = Range.first, E = Range.second; I != E; ++I)
271       if (I->Version.Major == MajorVersion && I->Version.Minor == MinorVersion)
272         return true;
273   }
274 
275   return false;
276 }
277 
hasExtension(StringRef Ext) const278 bool RISCVISAInfo::hasExtension(StringRef Ext) const {
279   stripExperimentalPrefix(Ext);
280 
281   if (!isSupportedExtension(Ext))
282     return false;
283 
284   return Exts.count(Ext.str()) != 0;
285 }
286 
toFeatures(bool AddAllExtensions,bool IgnoreUnknown) const287 std::vector<std::string> RISCVISAInfo::toFeatures(bool AddAllExtensions,
288                                                   bool IgnoreUnknown) const {
289   std::vector<std::string> Features;
290   for (const auto &[ExtName, _] : Exts) {
291     // i is a base instruction set, not an extension (see
292     // https://github.com/riscv/riscv-isa-manual/blob/main/src/naming.adoc#base-integer-isa)
293     // and is not recognized in clang -cc1
294     if (ExtName == "i")
295       continue;
296     if (IgnoreUnknown && !isSupportedExtension(ExtName))
297       continue;
298 
299     if (isExperimentalExtension(ExtName)) {
300       Features.push_back((llvm::Twine("+experimental-") + ExtName).str());
301     } else {
302       Features.push_back((llvm::Twine("+") + ExtName).str());
303     }
304   }
305   if (AddAllExtensions) {
306     for (const RISCVSupportedExtension &Ext : SupportedExtensions) {
307       if (Exts.count(Ext.Name))
308         continue;
309       Features.push_back((llvm::Twine("-") + Ext.Name).str());
310     }
311 
312     for (const RISCVSupportedExtension &Ext : SupportedExperimentalExtensions) {
313       if (Exts.count(Ext.Name))
314         continue;
315       Features.push_back((llvm::Twine("-experimental-") + Ext.Name).str());
316     }
317   }
318   return Features;
319 }
320 
getError(const Twine & Message)321 static Error getError(const Twine &Message) {
322   return createStringError(errc::invalid_argument, Message);
323 }
324 
getErrorForInvalidExt(StringRef ExtName)325 static Error getErrorForInvalidExt(StringRef ExtName) {
326   if (ExtName.size() == 1) {
327     return getError("unsupported standard user-level extension '" + ExtName +
328                     "'");
329   }
330   return getError("unsupported " + getExtensionTypeDesc(ExtName) + " '" +
331                   ExtName + "'");
332 }
333 
334 // Extensions may have a version number, and may be separated by
335 // an underscore '_' e.g.: rv32i2_m2.
336 // Version number is divided into major and minor version numbers,
337 // separated by a 'p'. If the minor version is 0 then 'p0' can be
338 // 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)339 static Error getExtensionVersion(StringRef Ext, StringRef In, unsigned &Major,
340                                  unsigned &Minor, unsigned &ConsumeLength,
341                                  bool EnableExperimentalExtension,
342                                  bool ExperimentalExtensionVersionCheck) {
343   StringRef MajorStr, MinorStr;
344   Major = 0;
345   Minor = 0;
346   ConsumeLength = 0;
347   MajorStr = In.take_while(isDigit);
348   In = In.substr(MajorStr.size());
349 
350   if (!MajorStr.empty() && In.consume_front("p")) {
351     MinorStr = In.take_while(isDigit);
352     In = In.substr(MajorStr.size() + MinorStr.size() - 1);
353 
354     // Expected 'p' to be followed by minor version number.
355     if (MinorStr.empty()) {
356       return getError("minor version number missing after 'p' for extension '" +
357                       Ext + "'");
358     }
359   }
360 
361   if (!MajorStr.empty() && MajorStr.getAsInteger(10, Major))
362     return getError("Failed to parse major version number for extension '" +
363                     Ext + "'");
364 
365   if (!MinorStr.empty() && MinorStr.getAsInteger(10, Minor))
366     return getError("Failed to parse minor version number for extension '" +
367                     Ext + "'");
368 
369   ConsumeLength = MajorStr.size();
370 
371   if (!MinorStr.empty())
372     ConsumeLength += MinorStr.size() + 1 /*'p'*/;
373 
374   // Expected multi-character extension with version number to have no
375   // subsequent characters (i.e. must either end string or be followed by
376   // an underscore).
377   if (Ext.size() > 1 && In.size())
378     return getError(
379         "multi-character extensions must be separated by underscores");
380 
381   // If experimental extension, require use of current version number
382   if (auto ExperimentalExtension = isExperimentalExtension(Ext)) {
383     if (!EnableExperimentalExtension)
384       return getError("requires '-menable-experimental-extensions' "
385                       "for experimental extension '" +
386                       Ext + "'");
387 
388     if (ExperimentalExtensionVersionCheck &&
389         (MajorStr.empty() && MinorStr.empty()))
390       return getError(
391           "experimental extension requires explicit version number `" + Ext +
392           "`");
393 
394     auto SupportedVers = *ExperimentalExtension;
395     if (ExperimentalExtensionVersionCheck &&
396         (Major != SupportedVers.Major || Minor != SupportedVers.Minor)) {
397       std::string Error = "unsupported version number " + MajorStr.str();
398       if (!MinorStr.empty())
399         Error += "." + MinorStr.str();
400       Error += " for experimental extension '" + Ext.str() +
401                "' (this compiler supports " + utostr(SupportedVers.Major) +
402                "." + utostr(SupportedVers.Minor) + ")";
403       return getError(Error);
404     }
405     return Error::success();
406   }
407 
408   // Exception rule for `g`, we don't have clear version scheme for that on
409   // ISA spec.
410   if (Ext == "g")
411     return Error::success();
412 
413   if (MajorStr.empty() && MinorStr.empty()) {
414     if (auto DefaultVersion = findDefaultVersion(Ext)) {
415       Major = DefaultVersion->Major;
416       Minor = DefaultVersion->Minor;
417     }
418     // No matter found or not, return success, assume other place will
419     // verify.
420     return Error::success();
421   }
422 
423   if (RISCVISAInfo::isSupportedExtension(Ext, Major, Minor))
424     return Error::success();
425 
426   if (!RISCVISAInfo::isSupportedExtension(Ext))
427     return getErrorForInvalidExt(Ext);
428 
429   std::string Error = "unsupported version number " + MajorStr.str();
430   if (!MinorStr.empty())
431     Error += "." + MinorStr.str();
432   Error += " for extension '" + Ext.str() + "'";
433   return getError(Error);
434 }
435 
436 llvm::Expected<std::unique_ptr<RISCVISAInfo>>
createFromExtMap(unsigned XLen,const RISCVISAUtils::OrderedExtensionMap & Exts)437 RISCVISAInfo::createFromExtMap(unsigned XLen,
438                                const RISCVISAUtils::OrderedExtensionMap &Exts) {
439   assert(XLen == 32 || XLen == 64);
440   std::unique_ptr<RISCVISAInfo> ISAInfo(new RISCVISAInfo(XLen));
441 
442   ISAInfo->Exts = Exts;
443 
444   return RISCVISAInfo::postProcessAndChecking(std::move(ISAInfo));
445 }
446 
447 llvm::Expected<std::unique_ptr<RISCVISAInfo>>
parseFeatures(unsigned XLen,const std::vector<std::string> & Features)448 RISCVISAInfo::parseFeatures(unsigned XLen,
449                             const std::vector<std::string> &Features) {
450   assert(XLen == 32 || XLen == 64);
451   std::unique_ptr<RISCVISAInfo> ISAInfo(new RISCVISAInfo(XLen));
452 
453   for (auto &Feature : Features) {
454     StringRef ExtName = Feature;
455     assert(ExtName.size() > 1 && (ExtName[0] == '+' || ExtName[0] == '-'));
456     bool Add = ExtName[0] == '+';
457     ExtName = ExtName.drop_front(1); // Drop '+' or '-'
458     bool Experimental = stripExperimentalPrefix(ExtName);
459     auto ExtensionInfos = Experimental
460                               ? ArrayRef(SupportedExperimentalExtensions)
461                               : ArrayRef(SupportedExtensions);
462     auto ExtensionInfoIterator =
463         llvm::lower_bound(ExtensionInfos, ExtName, LessExtName());
464 
465     // Not all features is related to ISA extension, like `relax` or
466     // `save-restore`, skip those feature.
467     if (ExtensionInfoIterator == ExtensionInfos.end() ||
468         ExtensionInfoIterator->Name != ExtName)
469       continue;
470 
471     if (Add)
472       ISAInfo->Exts[ExtName.str()] = ExtensionInfoIterator->Version;
473     else
474       ISAInfo->Exts.erase(ExtName.str());
475   }
476 
477   return RISCVISAInfo::postProcessAndChecking(std::move(ISAInfo));
478 }
479 
480 llvm::Expected<std::unique_ptr<RISCVISAInfo>>
parseNormalizedArchString(StringRef Arch)481 RISCVISAInfo::parseNormalizedArchString(StringRef Arch) {
482   // RISC-V ISA strings must be [a-z0-9_]
483   if (!llvm::all_of(
484           Arch, [](char C) { return isDigit(C) || isLower(C) || C == '_'; }))
485     return getError("string may only contain [a-z0-9_]");
486 
487   // Must start with a valid base ISA name.
488   unsigned XLen = 0;
489   if (Arch.consume_front("rv32"))
490     XLen = 32;
491   else if (Arch.consume_front("rv64"))
492     XLen = 64;
493 
494   if (XLen == 0 || Arch.empty() || (Arch[0] != 'i' && Arch[0] != 'e'))
495     return getError("arch string must begin with valid base ISA");
496 
497   std::unique_ptr<RISCVISAInfo> ISAInfo(new RISCVISAInfo(XLen));
498 
499   // Each extension is of the form ${name}${major_version}p${minor_version}
500   // and separated by _. Split by _ and then extract the name and version
501   // information for each extension.
502   while (!Arch.empty()) {
503     if (Arch[0] == '_') {
504       if (Arch.size() == 1 || Arch[1] == '_')
505         return getError("extension name missing after separator '_'");
506       Arch = Arch.drop_front();
507     }
508 
509     size_t Idx = Arch.find('_');
510     StringRef Ext = Arch.slice(0, Idx);
511     Arch = Arch.slice(Idx, StringRef::npos);
512 
513     StringRef Prefix, MinorVersionStr;
514     std::tie(Prefix, MinorVersionStr) = Ext.rsplit('p');
515     if (MinorVersionStr.empty())
516       return getError("extension lacks version in expected format");
517     unsigned MajorVersion, MinorVersion;
518     if (MinorVersionStr.getAsInteger(10, MinorVersion))
519       return getError("failed to parse minor version number");
520 
521     // Split Prefix into the extension name and the major version number
522     // (the trailing digits of Prefix).
523     size_t VersionStart = Prefix.size();
524     while (VersionStart != 0) {
525       if (!isDigit(Prefix[VersionStart - 1]))
526         break;
527       --VersionStart;
528     }
529     if (VersionStart == Prefix.size())
530       return getError("extension lacks version in expected format");
531 
532     if (VersionStart == 0)
533       return getError("missing extension name");
534 
535     StringRef ExtName = Prefix.slice(0, VersionStart);
536     StringRef MajorVersionStr = Prefix.slice(VersionStart, StringRef::npos);
537     if (MajorVersionStr.getAsInteger(10, MajorVersion))
538       return getError("failed to parse major version number");
539 
540     if ((ExtName[0] == 'z' || ExtName[0] == 's' || ExtName[0] == 'x') &&
541         (ExtName.size() == 1 || isDigit(ExtName[1])))
542       return getError("'" + Twine(ExtName[0]) +
543                       "' must be followed by a letter");
544 
545     if (!ISAInfo->Exts
546              .emplace(
547                  ExtName.str(),
548                  RISCVISAUtils::ExtensionVersion{MajorVersion, MinorVersion})
549              .second)
550       return getError("duplicate extension '" + ExtName + "'");
551   }
552   ISAInfo->updateImpliedLengths();
553   return std::move(ISAInfo);
554 }
555 
556 llvm::Expected<std::unique_ptr<RISCVISAInfo>>
parseArchString(StringRef Arch,bool EnableExperimentalExtension,bool ExperimentalExtensionVersionCheck)557 RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension,
558                               bool ExperimentalExtensionVersionCheck) {
559   // RISC-V ISA strings must be [a-z0-9_]
560   if (!llvm::all_of(
561           Arch, [](char C) { return isDigit(C) || isLower(C) || C == '_'; }))
562     return getError("string may only contain [a-z0-9_]");
563 
564   // ISA string must begin with rv32, rv64, or a profile.
565   unsigned XLen = 0;
566   if (Arch.consume_front("rv32")) {
567     XLen = 32;
568   } else if (Arch.consume_front("rv64")) {
569     XLen = 64;
570   } else {
571     // Try parsing as a profile.
572     auto ProfileCmp = [](StringRef Arch, const RISCVProfile &Profile) {
573       return Arch < Profile.Name;
574     };
575     auto I = llvm::upper_bound(SupportedProfiles, Arch, ProfileCmp);
576     bool FoundProfile = I != std::begin(SupportedProfiles) &&
577                         Arch.starts_with(std::prev(I)->Name);
578     if (!FoundProfile) {
579       I = llvm::upper_bound(SupportedExperimentalProfiles, Arch, ProfileCmp);
580       FoundProfile = (I != std::begin(SupportedExperimentalProfiles) &&
581                       Arch.starts_with(std::prev(I)->Name));
582       if (FoundProfile && !EnableExperimentalExtension) {
583         return getError("requires '-menable-experimental-extensions' "
584                         "for profile '" +
585                         std::prev(I)->Name + "'");
586       }
587     }
588     if (FoundProfile) {
589       --I;
590       std::string NewArch = I->MArch.str();
591       StringRef ArchWithoutProfile = Arch.drop_front(I->Name.size());
592       if (!ArchWithoutProfile.empty()) {
593         if (ArchWithoutProfile.front() != '_')
594           return getError("additional extensions must be after separator '_'");
595         NewArch += ArchWithoutProfile.str();
596       }
597       return parseArchString(NewArch, EnableExperimentalExtension,
598                              ExperimentalExtensionVersionCheck);
599     }
600   }
601 
602   if (XLen == 0 || Arch.empty())
603     return getError(
604         "string must begin with rv32{i,e,g}, rv64{i,e,g}, or a supported "
605         "profile name");
606 
607   std::unique_ptr<RISCVISAInfo> ISAInfo(new RISCVISAInfo(XLen));
608 
609   // The canonical order specified in ISA manual.
610   // Ref: Table 22.1 in RISC-V User-Level ISA V2.2
611   char Baseline = Arch.front();
612   // Skip the baseline.
613   Arch = Arch.drop_front();
614 
615   unsigned Major, Minor, ConsumeLength;
616 
617   // First letter should be 'e', 'i' or 'g'.
618   switch (Baseline) {
619   default:
620     return getError("first letter after \'rv" + Twine(XLen) +
621                     "\' should be 'e', 'i' or 'g'");
622   case 'e':
623   case 'i':
624     // Baseline is `i` or `e`
625     if (auto E = getExtensionVersion(
626             StringRef(&Baseline, 1), Arch, Major, Minor, ConsumeLength,
627             EnableExperimentalExtension, ExperimentalExtensionVersionCheck))
628       return std::move(E);
629 
630     ISAInfo->Exts[std::string(1, Baseline)] = {Major, Minor};
631     break;
632   case 'g':
633     // g expands to extensions in RISCVGImplications.
634     if (!Arch.empty() && isDigit(Arch.front()))
635       return getError("version not supported for 'g'");
636 
637     // Versions for g are disallowed, and this was checked for previously.
638     ConsumeLength = 0;
639 
640     // No matter which version is given to `g`, we always set imafd to default
641     // version since the we don't have clear version scheme for that on
642     // ISA spec.
643     for (const char *Ext : RISCVGImplications) {
644       auto Version = findDefaultVersion(Ext);
645       assert(Version && "Default extension version not found?");
646       // Postpone AddExtension until end of this function
647       ISAInfo->Exts[std::string(Ext)] = {Version->Major, Version->Minor};
648     }
649     break;
650   }
651 
652   // Consume the base ISA version number and any '_' between rvxxx and the
653   // first extension
654   Arch = Arch.drop_front(ConsumeLength);
655 
656   while (!Arch.empty()) {
657     if (Arch.front() == '_') {
658       if (Arch.size() == 1 || Arch[1] == '_')
659         return getError("extension name missing after separator '_'");
660       Arch = Arch.drop_front();
661     }
662 
663     size_t Idx = Arch.find('_');
664     StringRef Ext = Arch.slice(0, Idx);
665     Arch = Arch.slice(Idx, StringRef::npos);
666 
667     do {
668       StringRef Name, Vers, Desc;
669       if (RISCVISAUtils::AllStdExts.contains(Ext.front())) {
670         Name = Ext.take_front(1);
671         Ext = Ext.drop_front();
672         Vers = Ext;
673         Desc = "standard user-level extension";
674       } else if (Ext.front() == 'z' || Ext.front() == 's' ||
675                  Ext.front() == 'x') {
676         // Handle other types of extensions other than the standard
677         // general purpose and standard user-level extensions.
678         // Parse the ISA string containing non-standard user-level
679         // extensions, standard supervisor-level extensions and
680         // non-standard supervisor-level extensions.
681         // These extensions start with 'z', 's', 'x' prefixes, might have a
682         // version number (major, minor) and are separated by a single
683         // underscore '_'. We do not enforce a canonical order for them.
684         StringRef Type = getExtensionType(Ext);
685         Desc = getExtensionTypeDesc(Ext);
686         auto Pos = findLastNonVersionCharacter(Ext) + 1;
687         Name = Ext.substr(0, Pos);
688         Vers = Ext.substr(Pos);
689         Ext = StringRef();
690 
691         assert(!Type.empty() && "Empty type?");
692         if (Name.size() == Type.size())
693           return getError(Desc + " name missing after '" + Type + "'");
694       } else {
695         return getError("invalid standard user-level extension '" +
696                         Twine(Ext.front()) + "'");
697       }
698 
699       unsigned Major, Minor, ConsumeLength;
700       if (auto E = getExtensionVersion(Name, Vers, Major, Minor, ConsumeLength,
701                                        EnableExperimentalExtension,
702                                        ExperimentalExtensionVersionCheck))
703         return E;
704 
705       if (Name.size() == 1)
706         Ext = Ext.substr(ConsumeLength);
707 
708       if (!RISCVISAInfo::isSupportedExtension(Name))
709         return getErrorForInvalidExt(Name);
710 
711       // Insert and error for duplicates.
712       if (!ISAInfo->Exts
713                .emplace(Name.str(),
714                         RISCVISAUtils::ExtensionVersion{Major, Minor})
715                .second)
716         return getError("duplicated " + Desc + " '" + Name + "'");
717 
718     } while (!Ext.empty());
719   }
720 
721   return RISCVISAInfo::postProcessAndChecking(std::move(ISAInfo));
722 }
723 
checkDependency()724 Error RISCVISAInfo::checkDependency() {
725   bool HasE = Exts.count("e") != 0;
726   bool HasI = Exts.count("i") != 0;
727   bool HasC = Exts.count("c") != 0;
728   bool HasF = Exts.count("f") != 0;
729   bool HasD = Exts.count("d") != 0;
730   bool HasZfinx = Exts.count("zfinx") != 0;
731   bool HasVector = Exts.count("zve32x") != 0;
732   bool HasZvl = MinVLen != 0;
733   bool HasZcmt = Exts.count("zcmt") != 0;
734 
735   if (HasI && HasE)
736     return getError("'I' and 'E' extensions are incompatible");
737 
738   if (HasF && HasZfinx)
739     return getError("'f' and 'zfinx' extensions are incompatible");
740 
741   if (HasZvl && !HasVector)
742     return getError(
743         "'zvl*b' requires 'v' or 'zve*' extension to also be specified");
744 
745   if (Exts.count("zvbb") && !HasVector)
746     return getError(
747         "'zvbb' requires 'v' or 'zve*' extension to also be specified");
748 
749   if (Exts.count("zvbc") && !Exts.count("zve64x"))
750     return getError(
751         "'zvbc' requires 'v' or 'zve64*' extension to also be specified");
752 
753   if ((Exts.count("zvkb") || Exts.count("zvkg") || Exts.count("zvkned") ||
754        Exts.count("zvknha") || Exts.count("zvksed") || Exts.count("zvksh")) &&
755       !HasVector)
756     return getError(
757         "'zvk*' requires 'v' or 'zve*' extension to also be specified");
758 
759   if (Exts.count("zvknhb") && !Exts.count("zve64x"))
760     return getError(
761         "'zvknhb' requires 'v' or 'zve64*' extension to also be specified");
762 
763   if ((HasZcmt || Exts.count("zcmp")) && HasD && (HasC || Exts.count("zcd")))
764     return getError(Twine("'") + (HasZcmt ? "zcmt" : "zcmp") +
765                     "' extension is incompatible with '" +
766                     (HasC ? "c" : "zcd") +
767                     "' extension when 'd' extension is enabled");
768 
769   if (XLen != 32 && Exts.count("zcf"))
770     return getError("'zcf' is only supported for 'rv32'");
771 
772   if (Exts.count("zacas") && !(Exts.count("a") || Exts.count("zaamo")))
773     return getError(
774         "'zacas' requires 'a' or 'zaamo' extension to also be specified");
775 
776   if (Exts.count("zabha") && !(Exts.count("a") || Exts.count("zaamo")))
777     return getError(
778         "'zabha' requires 'a' or 'zaamo' extension to also be specified");
779 
780   if (Exts.count("xwchc") != 0) {
781     if (XLen != 32)
782       return getError("'Xwchc' is only supported for 'rv32'");
783 
784     if (HasD)
785       return getError("'D' and 'Xwchc' extensions are incompatible");
786 
787     if (Exts.count("zcb") != 0)
788       return getError("'Xwchc' and 'Zcb' extensions are incompatible");
789   }
790 
791   return Error::success();
792 }
793 
794 struct ImpliedExtsEntry {
795   StringLiteral Name;
796   const char *ImpliedExt;
797 
operator <ImpliedExtsEntry798   bool operator<(const ImpliedExtsEntry &Other) const {
799     return Name < Other.Name;
800   }
801 };
802 
operator <(const ImpliedExtsEntry & LHS,StringRef RHS)803 static bool operator<(const ImpliedExtsEntry &LHS, StringRef RHS) {
804   return LHS.Name < RHS;
805 }
806 
operator <(StringRef LHS,const ImpliedExtsEntry & RHS)807 static bool operator<(StringRef LHS, const ImpliedExtsEntry &RHS) {
808   return LHS < RHS.Name;
809 }
810 
811 #define GET_IMPLIED_EXTENSIONS
812 #include "llvm/TargetParser/RISCVTargetParserDef.inc"
813 
updateImplication()814 void RISCVISAInfo::updateImplication() {
815   bool HasE = Exts.count("e") != 0;
816   bool HasI = Exts.count("i") != 0;
817 
818   // If not in e extension and i extension does not exist, i extension is
819   // implied
820   if (!HasE && !HasI) {
821     auto Version = findDefaultVersion("i");
822     Exts["i"] = *Version;
823   }
824 
825   if (HasE && HasI)
826     Exts.erase("i");
827 
828   assert(llvm::is_sorted(ImpliedExts) && "Table not sorted by Name");
829 
830   // This loop may execute over 1 iteration since implication can be layered
831   // Exits loop if no more implication is applied
832   SmallVector<StringRef, 16> WorkList;
833   for (auto const &Ext : Exts)
834     WorkList.push_back(Ext.first);
835 
836   while (!WorkList.empty()) {
837     StringRef ExtName = WorkList.pop_back_val();
838     auto Range = std::equal_range(std::begin(ImpliedExts),
839                                   std::end(ImpliedExts), ExtName);
840     std::for_each(Range.first, Range.second,
841                   [&](const ImpliedExtsEntry &Implied) {
842                     const char *ImpliedExt = Implied.ImpliedExt;
843                     if (Exts.count(ImpliedExt))
844                       return;
845                     auto Version = findDefaultVersion(ImpliedExt);
846                     Exts[ImpliedExt] = *Version;
847                     WorkList.push_back(ImpliedExt);
848                   });
849   }
850 
851   // Add Zcf if Zce and F are enabled on RV32.
852   if (XLen == 32 && Exts.count("zce") && Exts.count("f") &&
853       !Exts.count("zcf")) {
854     auto Version = findDefaultVersion("zcf");
855     Exts["zcf"] = *Version;
856   }
857 }
858 
859 static constexpr StringLiteral CombineIntoExts[] = {
860     {"zk"},    {"zkn"},  {"zks"},   {"zvkn"},  {"zvknc"},
861     {"zvkng"}, {"zvks"}, {"zvksc"}, {"zvksg"},
862 };
863 
updateCombination()864 void RISCVISAInfo::updateCombination() {
865   bool MadeChange = false;
866   do {
867     MadeChange = false;
868     for (StringRef CombineExt : CombineIntoExts) {
869       if (Exts.count(CombineExt.str()))
870         continue;
871 
872       // Look up the extension in the ImpliesExt table to find everything it
873       // depends on.
874       auto Range = std::equal_range(std::begin(ImpliedExts),
875                                     std::end(ImpliedExts), CombineExt);
876       bool HasAllRequiredFeatures = std::all_of(
877           Range.first, Range.second, [&](const ImpliedExtsEntry &Implied) {
878             return Exts.count(Implied.ImpliedExt);
879           });
880       if (HasAllRequiredFeatures) {
881         auto Version = findDefaultVersion(CombineExt);
882         Exts[CombineExt.str()] = *Version;
883         MadeChange = true;
884       }
885     }
886   } while (MadeChange);
887 }
888 
updateImpliedLengths()889 void RISCVISAInfo::updateImpliedLengths() {
890   assert(FLen == 0 && MaxELenFp == 0 && MaxELen == 0 && MinVLen == 0 &&
891          "Expected lengths to be initialied to zero");
892 
893   // TODO: Handle q extension.
894   if (Exts.count("d"))
895     FLen = 64;
896   else if (Exts.count("f"))
897     FLen = 32;
898 
899   if (Exts.count("v")) {
900     MaxELenFp = std::max(MaxELenFp, 64u);
901     MaxELen = std::max(MaxELen, 64u);
902   }
903 
904   for (auto const &Ext : Exts) {
905     StringRef ExtName = Ext.first;
906     // Infer MaxELen and MaxELenFp from Zve(32/64)(x/f/d)
907     if (ExtName.consume_front("zve")) {
908       unsigned ZveELen;
909       if (ExtName.consumeInteger(10, ZveELen))
910         continue;
911 
912       if (ExtName == "f")
913         MaxELenFp = std::max(MaxELenFp, 32u);
914       else if (ExtName == "d")
915         MaxELenFp = std::max(MaxELenFp, 64u);
916       else if (ExtName != "x")
917         continue;
918 
919       MaxELen = std::max(MaxELen, ZveELen);
920       continue;
921     }
922 
923     // Infer MinVLen from zvl*b.
924     if (ExtName.consume_front("zvl")) {
925       unsigned ZvlLen;
926       if (ExtName.consumeInteger(10, ZvlLen))
927         continue;
928 
929       if (ExtName != "b")
930         continue;
931 
932       MinVLen = std::max(MinVLen, ZvlLen);
933       continue;
934     }
935   }
936 }
937 
toString() const938 std::string RISCVISAInfo::toString() const {
939   std::string Buffer;
940   raw_string_ostream Arch(Buffer);
941 
942   Arch << "rv" << XLen;
943 
944   ListSeparator LS("_");
945   for (auto const &Ext : Exts) {
946     StringRef ExtName = Ext.first;
947     auto ExtInfo = Ext.second;
948     Arch << LS << ExtName;
949     Arch << ExtInfo.Major << "p" << ExtInfo.Minor;
950   }
951 
952   return Arch.str();
953 }
954 
955 llvm::Expected<std::unique_ptr<RISCVISAInfo>>
postProcessAndChecking(std::unique_ptr<RISCVISAInfo> && ISAInfo)956 RISCVISAInfo::postProcessAndChecking(std::unique_ptr<RISCVISAInfo> &&ISAInfo) {
957   ISAInfo->updateImplication();
958   ISAInfo->updateCombination();
959   ISAInfo->updateImpliedLengths();
960 
961   if (Error Result = ISAInfo->checkDependency())
962     return std::move(Result);
963   return std::move(ISAInfo);
964 }
965 
computeDefaultABI() const966 StringRef RISCVISAInfo::computeDefaultABI() const {
967   if (XLen == 32) {
968     if (Exts.count("e"))
969       return "ilp32e";
970     if (Exts.count("d"))
971       return "ilp32d";
972     if (Exts.count("f"))
973       return "ilp32f";
974     return "ilp32";
975   } else if (XLen == 64) {
976     if (Exts.count("e"))
977       return "lp64e";
978     if (Exts.count("d"))
979       return "lp64d";
980     if (Exts.count("f"))
981       return "lp64f";
982     return "lp64";
983   }
984   llvm_unreachable("Invalid XLEN");
985 }
986 
isSupportedExtensionWithVersion(StringRef Ext)987 bool RISCVISAInfo::isSupportedExtensionWithVersion(StringRef Ext) {
988   if (Ext.empty())
989     return false;
990 
991   auto Pos = findLastNonVersionCharacter(Ext) + 1;
992   StringRef Name = Ext.substr(0, Pos);
993   StringRef Vers = Ext.substr(Pos);
994   if (Vers.empty())
995     return false;
996 
997   unsigned Major, Minor, ConsumeLength;
998   if (auto E = getExtensionVersion(Name, Vers, Major, Minor, ConsumeLength,
999                                    true, true)) {
1000     consumeError(std::move(E));
1001     return false;
1002   }
1003 
1004   return true;
1005 }
1006 
getTargetFeatureForExtension(StringRef Ext)1007 std::string RISCVISAInfo::getTargetFeatureForExtension(StringRef Ext) {
1008   if (Ext.empty())
1009     return std::string();
1010 
1011   auto Pos = findLastNonVersionCharacter(Ext) + 1;
1012   StringRef Name = Ext.substr(0, Pos);
1013 
1014   if (Pos != Ext.size() && !isSupportedExtensionWithVersion(Ext))
1015     return std::string();
1016 
1017   if (!isSupportedExtension(Name))
1018     return std::string();
1019 
1020   return isExperimentalExtension(Name) ? "experimental-" + Name.str()
1021                                        : Name.str();
1022 }
1023