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