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