[RISCV] Fix mgather -> riscv.masked.strided.load combine not extending indices (...
[llvm-project.git] / llvm / lib / Support / RISCVISAInfo.cpp
blobdb2e4ca92ae40a7803c3cecfffaaa49145c6f550
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 //===----------------------------------------------------------------------===//
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"
18 #include <array>
19 #include <atomic>
20 #include <optional>
21 #include <string>
22 #include <vector>
24 using namespace llvm;
26 namespace {
28 struct RISCVSupportedExtension {
29 const char *Name;
30 /// Supported version.
31 RISCVISAInfo::ExtensionVersion Version;
33 bool operator<(const RISCVSupportedExtension &RHS) const {
34 return StringRef(Name) < StringRef(RHS.Name);
38 } // end anonymous namespace
40 static constexpr StringLiteral AllStdExts = "mafdqlcbkjtpvnh";
42 static const char *RISCVGImplications[] = {
43 "i", "m", "a", "f", "d", "zicsr", "zifencei"
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}},
57 {"smaia", {1, 0}},
58 {"smepmp", {1, 0}},
59 {"ssaia", {1, 0}},
60 {"svinval", {1, 0}},
61 {"svnapot", {1, 0}},
62 {"svpbmt", {1, 0}},
64 {"v", {1, 0}},
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}},
92 {"za128rs", {1, 0}},
93 {"za64rs", {1, 0}},
94 {"zawrs", {1, 0}},
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}},
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}},
112 {"zdinx", {1, 0}},
114 {"zfa", {1, 0}},
115 {"zfh", {1, 0}},
116 {"zfhmin", {1, 0}},
117 {"zfinx", {1, 0}},
119 {"zhinx", {1, 0}},
120 {"zhinxmin", {1, 0}},
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}},
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}},
149 {"zmmul", {1, 0}},
151 {"zvbb", {1, 0}},
152 {"zvbc", {1, 0}},
154 {"zve32f", {1, 0}},
155 {"zve32x", {1, 0}},
156 {"zve64d", {1, 0}},
157 {"zve64f", {1, 0}},
158 {"zve64x", {1, 0}},
160 {"zvfh", {1, 0}},
161 {"zvfhmin", {1, 0}},
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}},
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}},
193 // NOTE: This table should be sorted alphabetically by extension name.
194 static const RISCVSupportedExtension SupportedExperimentalExtensions[] = {
195 {"zacas", {1, 0}},
197 {"zcmop", {0, 2}},
199 {"zfbfmin", {1, 0}},
201 {"zicfilp", {0, 4}},
202 {"zicfiss", {0, 4}},
204 {"zimop", {0, 1}},
206 {"ztso", {0, 1}},
208 {"zvfbfmin", {1, 0}},
209 {"zvfbfwma", {1, 0}},
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);
222 #endif
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";
233 void llvm::riscvExtensionsHelp(StringMap<StringRef> DescMap) {
235 outs() << "All available -march extensions for RISC-V\n\n";
236 PrintExtension("Name", "Version", (DescMap.empty() ? "" : "Description"));
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]);
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]);
257 outs() << "\nUse -march to specify the target's extension.\n"
258 "For example, clang -march=rv32i_v1p0\n";
261 static bool stripExperimentalPrefix(StringRef &Ext) {
262 return Ext.consume_front("experimental-");
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.
272 static size_t findLastNonVersionCharacter(StringRef Ext) {
273 assert(!Ext.empty() &&
274 "Already guarded by if-statement in ::parseArchString");
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--;
284 return Pos;
287 namespace {
288 struct LessExtName {
289 bool operator()(const RISCVSupportedExtension &LHS, StringRef RHS) {
290 return StringRef(LHS.Name) < RHS;
292 bool operator()(StringRef LHS, const RISCVSupportedExtension &RHS) {
293 return LHS < StringRef(RHS.Name);
296 } // namespace
298 static std::optional<RISCVISAInfo::ExtensionVersion>
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());
306 if (I == ExtInfo.end() || I->Name != ExtName)
307 continue;
309 return I->Version;
311 return std::nullopt;
314 void RISCVISAInfo::addExtension(StringRef ExtName,
315 RISCVISAInfo::ExtensionVersion Version) {
316 Exts[ExtName.str()] = Version;
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();
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();
339 static std::optional<RISCVISAInfo::ExtensionVersion>
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;
346 return I->Version;
349 bool RISCVISAInfo::isSupportedExtensionFeature(StringRef Ext) {
350 bool IsExperimental = stripExperimentalPrefix(Ext);
352 ArrayRef<RISCVSupportedExtension> ExtInfo =
353 IsExperimental ? ArrayRef(SupportedExperimentalExtensions)
354 : ArrayRef(SupportedExtensions);
356 auto I = llvm::lower_bound(ExtInfo, Ext, LessExtName());
357 return I != ExtInfo.end() && I->Name == Ext;
360 bool RISCVISAInfo::isSupportedExtension(StringRef Ext) {
361 verifyTables();
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;
370 return false;
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;
384 return false;
387 bool RISCVISAInfo::hasExtension(StringRef Ext) const {
388 stripExperimentalPrefix(Ext);
390 if (!isSupportedExtension(Ext))
391 return false;
393 return Exts.count(Ext.str()) != 0;
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,
413 // Get the rank for single-letter extension, lower value meaning higher
414 // priority.
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;
424 size_t Pos = AllStdExts.find(Ext);
425 if (Pos != StringRef::npos)
426 return Pos + 2; // Skip 'e' and 'i' from above.
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');
433 // Get the rank for multi-letter extension, lower value meaning higher
434 // priority/order in canonical order.
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]);
453 // Compare function for extension.
454 // Only compare the extension name, ignore version comparison.
455 bool RISCVISAInfo::compareExtension(const std::string &LHS,
456 const std::string &RHS) {
457 unsigned LHSRank = getExtensionRank(LHS);
458 unsigned RHSRank = getExtensionRank(RHS);
460 // If the ranks differ, pick the lower rank.
461 if (LHSRank != RHSRank)
462 return LHSRank < RHSRank;
464 // If the rank is same, it must be sorted by lexicographic order.
465 return LHS < RHS;
468 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;
480 if (isExperimentalExtension(ExtName)) {
481 Features.push_back((llvm::Twine("+experimental-") + ExtName).str());
482 } else {
483 Features.push_back((llvm::Twine("+") + ExtName).str());
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());
493 for (const RISCVSupportedExtension &Ext : SupportedExperimentalExtensions) {
494 if (Exts.count(Ext.Name))
495 continue;
496 Features.push_back((llvm::Twine("-experimental-") + Ext.Name).str());
499 return Features;
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.
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());
518 if (!MajorStr.empty() && In.consume_front("p")) {
519 MinorStr = In.take_while(isDigit);
520 In = In.substr(MajorStr.size() + MinorStr.size() - 1);
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 + "'");
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 + "'");
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 + "'");
540 ConsumeLength = MajorStr.size();
542 if (!MinorStr.empty())
543 ConsumeLength += MinorStr.size() + 1 /*'p'*/;
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);
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);
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);
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);
582 return Error::success();
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();
590 if (MajorStr.empty() && MinorStr.empty()) {
591 if (auto DefaultVersion = findDefaultVersion(Ext)) {
592 Major = DefaultVersion->Major;
593 Minor = DefaultVersion->Minor;
595 // No matter found or not, return success, assume other place will
596 // verify.
597 return Error::success();
600 if (RISCVISAInfo::isSupportedExtension(Ext, Major, Minor))
601 return Error::success();
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);
610 llvm::Expected<std::unique_ptr<RISCVISAInfo>>
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));
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());
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;
635 if (Add)
636 ISAInfo->addExtension(ExtName, ExtensionInfoIterator->Version);
637 else
638 ISAInfo->Exts.erase(ExtName.str());
641 return RISCVISAInfo::postProcessAndChecking(std::move(ISAInfo));
644 llvm::Expected<std::unique_ptr<RISCVISAInfo>>
645 RISCVISAInfo::parseNormalizedArchString(StringRef Arch) {
646 if (llvm::any_of(Arch, isupper)) {
647 return createStringError(errc::invalid_argument,
648 "string must be lowercase");
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);
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");
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++;
689 if (!TrailingDigits)
690 return createStringError(errc::invalid_argument,
691 "extension lacks version in expected format");
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});
699 ISAInfo->updateFLen();
700 ISAInfo->updateMinVLen();
701 ISAInfo->updateMaxELen();
702 return std::move(ISAInfo);
705 llvm::Expected<std::unique_ptr<RISCVISAInfo>>
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");
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}");
723 unsigned XLen = HasRV64 ? 64 : 32;
724 std::unique_ptr<RISCVISAInfo> ISAInfo(new RISCVISAInfo(XLen));
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];
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;
748 if (Arch.back() == '_')
749 return createStringError(errc::invalid_argument,
750 "extension name missing after separator '_'");
752 // Skip rvxxx
753 StringRef Exts = Arch.substr(5);
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);
766 unsigned Major, Minor, ConsumeLength;
767 if (Baseline == 'g') {
768 // Versions for g are disallowed, and this was checked for previously.
769 ConsumeLength = 0;
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?");
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;
795 ISAInfo->addExtension(StringRef(&Baseline, 1), {Major, Minor});
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("_");
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;
811 for (auto I = Exts.begin(), E = Exts.end(); I != E;) {
812 char C = *I;
814 // Check ISA extensions are specified in the canonical order.
815 while (StdExtsItr != StdExtsEnd && *StdExtsItr != C)
816 ++StdExtsItr;
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'",
828 return createStringError(errc::invalid_argument,
829 "invalid standard user-level extension '%c'", C);
832 // Move to next char to prevent repeated letter.
833 ++StdExtsItr;
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;
847 return std::move(E);
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;
857 return createStringError(errc::invalid_argument,
858 "unsupported standard user-level extension '%c'",
861 ISAInfo->addExtension(StringRef(&C, 1), {Major, Minor});
863 // Consume full extension name and version, including any optional '_'
864 // between this extension and the next
865 GoToNextExt(I, ConsumeLength, Exts.end());
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.
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, '_');
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 '_'");
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));
896 if (Type.empty()) {
897 if (IgnoreUnknown)
898 continue;
899 return createStringError(errc::invalid_argument,
900 "invalid extension prefix '" + Ext + "'");
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());
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;
917 return std::move(E);
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());
926 if (IgnoreUnknown && !isSupportedExtension(Name))
927 continue;
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);
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());
944 return RISCVISAInfo::postProcessAndChecking(std::move(ISAInfo));
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;
955 if (HasF && HasZfinx)
956 return createStringError(errc::invalid_argument,
957 "'f' and 'zfinx' extensions are incompatible");
959 if (HasZvl && !HasVector)
960 return createStringError(
961 errc::invalid_argument,
962 "'zvl*b' requires 'v' or 'zve*' extension to also be specified");
964 if (Exts.count("zvbb") && !HasVector)
965 return createStringError(
966 errc::invalid_argument,
967 "'zvbb' requires 'v' or 'zve*' extension to also be specified");
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");
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");
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");
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");
994 if (XLen != 32 && Exts.count("zcf"))
995 return createStringError(errc::invalid_argument,
996 "'zcf' is only supported for 'rv32'");
998 return Error::success();
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"};
1062 struct ImpliedExtsEntry {
1063 StringLiteral Name;
1064 ArrayRef<const char *> Exts;
1066 bool operator<(const ImpliedExtsEntry &Other) const {
1067 return Name < Other.Name;
1070 bool operator<(StringRef Other) const { return Name < Other; }
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}},
1136 void RISCVISAInfo::updateImplication() {
1137 bool HasE = Exts.count("e") != 0;
1138 bool HasI = Exts.count("i") != 0;
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());
1147 assert(llvm::is_sorted(ImpliedExts) && "Table not sorted by Name");
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);
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);
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());
1179 struct CombinedExtsEntry {
1180 StringLiteral CombineExt;
1181 ArrayRef<const char *> RequiredExts;
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}},
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;
1214 } while (IsNewCombine);
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;
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);
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);
1256 std::string RISCVISAInfo::toString() const {
1257 std::string Buffer;
1258 raw_string_ostream Arch(Buffer);
1260 Arch << "rv" << XLen;
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;
1270 return Arch.str();
1273 llvm::Expected<std::unique_ptr<RISCVISAInfo>>
1274 RISCVISAInfo::postProcessAndChecking(std::unique_ptr<RISCVISAInfo> &&ISAInfo) {
1275 ISAInfo->updateImplication();
1276 ISAInfo->updateCombination();
1277 ISAInfo->updateFLen();
1278 ISAInfo->updateMinVLen();
1279 ISAInfo->updateMaxELen();
1281 if (Error Result = ISAInfo->checkDependency())
1282 return std::move(Result);
1283 return std::move(ISAInfo);
1286 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";
1304 llvm_unreachable("Invalid XLEN");
1307 bool RISCVISAInfo::isSupportedExtensionWithVersion(StringRef Ext) {
1308 if (Ext.empty())
1309 return false;
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;
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;
1324 return true;
1327 std::string RISCVISAInfo::getTargetFeatureForExtension(StringRef Ext) {
1328 if (Ext.empty())
1329 return std::string();
1331 auto Pos = findLastNonVersionCharacter(Ext) + 1;
1332 StringRef Name = Ext.substr(0, Pos);
1334 if (Pos != Ext.size() && !isSupportedExtensionWithVersion(Ext))
1335 return std::string();
1337 if (!isSupportedExtension(Name))
1338 return std::string();
1340 return isExperimentalExtension(Name) ? "experimental-" + Name.str()
1341 : Name.str();