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
214 outs() << "All available -march extensions for RISC-V\n\n";
215 outs() << '\t' << left_justify("Name", 20) << "Version\n";
216
218 for (const auto &E : SupportedExtensions)
219 ExtMap[E.Name] = {E.Version.Major, E.Version.Minor};
220 for (const auto &E : ExtMap)
221 outs() << format("\t%-20s%d.%d\n", E.first.c_str(), E.second.MajorVersion,
222 E.second.MinorVersion);
223
224 outs() << "\nExperimental extensions\n";
225 ExtMap.clear();
226 for (const auto &E : SupportedExperimentalExtensions)
227 ExtMap[E.Name] = {E.Version.Major, E.Version.Minor};
228 for (const auto &E : ExtMap)
229 outs() << format("\t%-20s%d.%d\n", E.first.c_str(), E.second.MajorVersion,
230 E.second.MinorVersion);
231
232 outs() << "\nUse -march to specify the target's extension.\n"
233 "For example, clang -march=rv32i_v1p0\n";
234}
235
237 return Ext.consume_front("experimental-");
238}
239
240// This function finds the last character that doesn't belong to a version
241// (e.g. zba1p0 is extension 'zba' of version '1p0'). So the function will
242// consume [0-9]*p[0-9]* starting from the backward. An extension name will not
243// end with a digit or the letter 'p', so this function will parse correctly.
244// NOTE: This function is NOT able to take empty strings or strings that only
245// have version numbers and no extension name. It assumes the extension name
246// will be at least more than one character.
248 assert(!Ext.empty() &&
249 "Already guarded by if-statement in ::parseArchString");
250
251 int Pos = Ext.size() - 1;
252 while (Pos > 0 && isDigit(Ext[Pos]))
253 Pos--;
254 if (Pos > 0 && Ext[Pos] == 'p' && isDigit(Ext[Pos - 1])) {
255 Pos--;
256 while (Pos > 0 && isDigit(Ext[Pos]))
257 Pos--;
258 }
259 return Pos;
260}
261
262namespace {
263struct LessExtName {
264 bool operator()(const RISCVSupportedExtension &LHS, StringRef RHS) {
265 return StringRef(LHS.Name) < RHS;
266 }
267 bool operator()(StringRef LHS, const RISCVSupportedExtension &RHS) {
268 return LHS < StringRef(RHS.Name);
269 }
270};
271} // namespace
272
273static std::optional<RISCVExtensionVersion>
275 // Find default version of an extension.
276 // TODO: We might set default version based on profile or ISA spec.
277 for (auto &ExtInfo : {ArrayRef(SupportedExtensions),
279 auto I = llvm::lower_bound(ExtInfo, ExtName, LessExtName());
280
281 if (I == ExtInfo.end() || I->Name != ExtName)
282 continue;
283
284 return I->Version;
285 }
286 return std::nullopt;
287}
288
289void RISCVISAInfo::addExtension(StringRef ExtName, unsigned MajorVersion,
290 unsigned MinorVersion) {
292 Ext.MajorVersion = MajorVersion;
293 Ext.MinorVersion = MinorVersion;
294 Exts[ExtName.str()] = Ext;
295}
296
298 if (Ext.startswith("s"))
299 return "standard supervisor-level extension";
300 if (Ext.startswith("x"))
301 return "non-standard user-level extension";
302 if (Ext.startswith("z"))
303 return "standard user-level extension";
304 return StringRef();
305}
306
308 if (Ext.startswith("s"))
309 return "s";
310 if (Ext.startswith("x"))
311 return "x";
312 if (Ext.startswith("z"))
313 return "z";
314 return StringRef();
315}
316
317static std::optional<RISCVExtensionVersion>
319 auto I =
321 if (I == std::end(SupportedExperimentalExtensions) || I->Name != Ext)
322 return std::nullopt;
323
324 return I->Version;
325}
326
328 bool IsExperimental = stripExperimentalPrefix(Ext);
329
333
334 auto I = llvm::lower_bound(ExtInfo, Ext, LessExtName());
335 return I != ExtInfo.end() && I->Name == Ext;
336}
337
339 verifyTables();
340
341 for (auto ExtInfo : {ArrayRef(SupportedExtensions),
343 auto I = llvm::lower_bound(ExtInfo, Ext, LessExtName());
344 if (I != ExtInfo.end() && I->Name == Ext)
345 return true;
346 }
347
348 return false;
349}
350
351bool RISCVISAInfo::isSupportedExtension(StringRef Ext, unsigned MajorVersion,
352 unsigned MinorVersion) {
353 for (auto ExtInfo : {ArrayRef(SupportedExtensions),
355 auto Range =
356 std::equal_range(ExtInfo.begin(), ExtInfo.end(), Ext, LessExtName());
357 for (auto I = Range.first, E = Range.second; I != E; ++I)
358 if (I->Version.Major == MajorVersion && I->Version.Minor == MinorVersion)
359 return true;
360 }
361
362 return false;
363}
364
367
368 if (!isSupportedExtension(Ext))
369 return false;
370
371 return Exts.count(Ext.str()) != 0;
372}
373
374// We rank extensions in the following order:
375// -Single letter extensions in canonical order.
376// -Unknown single letter extensions in alphabetical order.
377// -Multi-letter extensions starting with 'z' sorted by canonical order of
378// the second letter then sorted alphabetically.
379// -Multi-letter extensions starting with 's' in alphabetical order.
380// -(TODO) Multi-letter extensions starting with 'zxm' in alphabetical order.
381// -X extensions in alphabetical order.
382// These flags are used to indicate the category. The first 6 bits store the
383// single letter extension rank for single letter and multi-letter extensions
384// starting with 'z'.
389};
390
391// Get the rank for single-letter extension, lower value meaning higher
392// priority.
393static unsigned singleLetterExtensionRank(char Ext) {
394 assert(Ext >= 'a' && Ext <= 'z');
395 switch (Ext) {
396 case 'i':
397 return 0;
398 case 'e':
399 return 1;
400 }
401
402 size_t Pos = AllStdExts.find(Ext);
403 if (Pos != StringRef::npos)
404 return Pos + 2; // Skip 'e' and 'i' from above.
405
406 // If we got an unknown extension letter, then give it an alphabetical
407 // order, but after all known standard extensions.
408 return 2 + AllStdExts.size() + (Ext - 'a');
409}
410
411// Get the rank for multi-letter extension, lower value meaning higher
412// priority/order in canonical order.
413static unsigned getExtensionRank(const std::string &ExtName) {
414 assert(ExtName.size() >= 1);
415 switch (ExtName[0]) {
416 case 's':
417 return RF_S_EXTENSION;
418 case 'z':
419 assert(ExtName.size() >= 2);
420 // `z` extension must be sorted by canonical order of second letter.
421 // e.g. zmx has higher rank than zax.
422 return RF_Z_EXTENSION | singleLetterExtensionRank(ExtName[1]);
423 case 'x':
424 return RF_X_EXTENSION;
425 default:
426 assert(ExtName.size() == 1);
427 return singleLetterExtensionRank(ExtName[0]);
428 }
429}
430
431// Compare function for extension.
432// Only compare the extension name, ignore version comparison.
433bool RISCVISAInfo::compareExtension(const std::string &LHS,
434 const std::string &RHS) {
435 unsigned LHSRank = getExtensionRank(LHS);
436 unsigned RHSRank = getExtensionRank(RHS);
437
438 // If the ranks differ, pick the lower rank.
439 if (LHSRank != RHSRank)
440 return LHSRank < RHSRank;
441
442 // If the rank is same, it must be sorted by lexicographic order.
443 return LHS < RHS;
444}
445
447 std::vector<StringRef> &Features,
448 llvm::function_ref<StringRef(const Twine &)> StrAlloc,
449 bool AddAllExtensions) const {
450 for (auto const &Ext : Exts) {
451 StringRef ExtName = Ext.first;
452
453 if (ExtName == "i")
454 continue;
455
456 if (isExperimentalExtension(ExtName)) {
457 Features.push_back(StrAlloc("+experimental-" + ExtName));
458 } else {
459 Features.push_back(StrAlloc("+" + ExtName));
460 }
461 }
462 if (AddAllExtensions) {
463 for (const RISCVSupportedExtension &Ext : SupportedExtensions) {
464 if (Exts.count(Ext.Name))
465 continue;
466 Features.push_back(StrAlloc(Twine("-") + Ext.Name));
467 }
468
469 for (const RISCVSupportedExtension &Ext : SupportedExperimentalExtensions) {
470 if (Exts.count(Ext.Name))
471 continue;
472 Features.push_back(StrAlloc(Twine("-experimental-") + Ext.Name));
473 }
474 }
475}
476
477// Extensions may have a version number, and may be separated by
478// an underscore '_' e.g.: rv32i2_m2.
479// Version number is divided into major and minor version numbers,
480// separated by a 'p'. If the minor version is 0 then 'p0' can be
481// omitted from the version string. E.g., rv32i2p0, rv32i2, rv32i2p1.
482static Error getExtensionVersion(StringRef Ext, StringRef In, unsigned &Major,
483 unsigned &Minor, unsigned &ConsumeLength,
484 bool EnableExperimentalExtension,
485 bool ExperimentalExtensionVersionCheck) {
486 StringRef MajorStr, MinorStr;
487 Major = 0;
488 Minor = 0;
489 ConsumeLength = 0;
490 MajorStr = In.take_while(isDigit);
491 In = In.substr(MajorStr.size());
492
493 if (!MajorStr.empty() && In.consume_front("p")) {
494 MinorStr = In.take_while(isDigit);
495 In = In.substr(MajorStr.size() + MinorStr.size() - 1);
496
497 // Expected 'p' to be followed by minor version number.
498 if (MinorStr.empty()) {
499 return createStringError(
501 "minor version number missing after 'p' for extension '" + Ext + "'");
502 }
503 }
504
505 if (!MajorStr.empty() && MajorStr.getAsInteger(10, Major))
506 return createStringError(
508 "Failed to parse major version number for extension '" + Ext + "'");
509
510 if (!MinorStr.empty() && MinorStr.getAsInteger(10, Minor))
511 return createStringError(
513 "Failed to parse minor version number for extension '" + Ext + "'");
514
515 ConsumeLength = MajorStr.size();
516
517 if (!MinorStr.empty())
518 ConsumeLength += MinorStr.size() + 1 /*'p'*/;
519
520 // Expected multi-character extension with version number to have no
521 // subsequent characters (i.e. must either end string or be followed by
522 // an underscore).
523 if (Ext.size() > 1 && In.size()) {
524 std::string Error =
525 "multi-character extensions must be separated by underscores";
527 }
528
529 // If experimental extension, require use of current version number
530 if (auto ExperimentalExtension = isExperimentalExtension(Ext)) {
531 if (!EnableExperimentalExtension) {
532 std::string Error = "requires '-menable-experimental-extensions' for "
533 "experimental extension '" +
534 Ext.str() + "'";
536 }
537
538 if (ExperimentalExtensionVersionCheck &&
539 (MajorStr.empty() && MinorStr.empty())) {
540 std::string Error =
541 "experimental extension requires explicit version number `" +
542 Ext.str() + "`";
544 }
545
546 auto SupportedVers = *ExperimentalExtension;
547 if (ExperimentalExtensionVersionCheck &&
548 (Major != SupportedVers.Major || Minor != SupportedVers.Minor)) {
549 std::string Error = "unsupported version number " + MajorStr.str();
550 if (!MinorStr.empty())
551 Error += "." + MinorStr.str();
552 Error += " for experimental extension '" + Ext.str() +
553 "' (this compiler supports " + utostr(SupportedVers.Major) +
554 "." + utostr(SupportedVers.Minor) + ")";
556 }
557 return Error::success();
558 }
559
560 // Exception rule for `g`, we don't have clear version scheme for that on
561 // ISA spec.
562 if (Ext == "g")
563 return Error::success();
564
565 if (MajorStr.empty() && MinorStr.empty()) {
566 if (auto DefaultVersion = findDefaultVersion(Ext)) {
567 Major = DefaultVersion->Major;
568 Minor = DefaultVersion->Minor;
569 }
570 // No matter found or not, return success, assume other place will
571 // verify.
572 return Error::success();
573 }
574
575 if (RISCVISAInfo::isSupportedExtension(Ext, Major, Minor))
576 return Error::success();
577
578 std::string Error = "unsupported version number " + std::string(MajorStr);
579 if (!MinorStr.empty())
580 Error += "." + MinorStr.str();
581 Error += " for extension '" + Ext.str() + "'";
583}
584
587 const std::vector<std::string> &Features) {
588 assert(XLen == 32 || XLen == 64);
589 std::unique_ptr<RISCVISAInfo> ISAInfo(new RISCVISAInfo(XLen));
590
591 for (auto &Feature : Features) {
592 StringRef ExtName = Feature;
593 bool Experimental = false;
594 assert(ExtName.size() > 1 && (ExtName[0] == '+' || ExtName[0] == '-'));
595 bool Add = ExtName[0] == '+';
596 ExtName = ExtName.drop_front(1); // Drop '+' or '-'
597 Experimental = stripExperimentalPrefix(ExtName);
598 auto ExtensionInfos = Experimental
601 auto ExtensionInfoIterator =
602 llvm::lower_bound(ExtensionInfos, ExtName, LessExtName());
603
604 // Not all features is related to ISA extension, like `relax` or
605 // `save-restore`, skip those feature.
606 if (ExtensionInfoIterator == ExtensionInfos.end() ||
607 ExtensionInfoIterator->Name != ExtName)
608 continue;
609
610 if (Add)
611 ISAInfo->addExtension(ExtName, ExtensionInfoIterator->Version.Major,
612 ExtensionInfoIterator->Version.Minor);
613 else
614 ISAInfo->Exts.erase(ExtName.str());
615 }
616
617 return RISCVISAInfo::postProcessAndChecking(std::move(ISAInfo));
618}
619
622 if (llvm::any_of(Arch, isupper)) {
624 "string must be lowercase");
625 }
626 // Must start with a valid base ISA name.
627 unsigned XLen;
628 if (Arch.startswith("rv32i") || Arch.startswith("rv32e"))
629 XLen = 32;
630 else if (Arch.startswith("rv64i") || Arch.startswith("rv64e"))
631 XLen = 64;
632 else
634 "arch string must begin with valid base ISA");
635 std::unique_ptr<RISCVISAInfo> ISAInfo(new RISCVISAInfo(XLen));
636 // Discard rv32/rv64 prefix.
637 Arch = Arch.substr(4);
638
639 // Each extension is of the form ${name}${major_version}p${minor_version}
640 // and separated by _. Split by _ and then extract the name and version
641 // information for each extension.
643 Arch.split(Split, '_');
644 for (StringRef Ext : Split) {
645 StringRef Prefix, MinorVersionStr;
646 std::tie(Prefix, MinorVersionStr) = Ext.rsplit('p');
647 if (MinorVersionStr.empty())
649 "extension lacks version in expected format");
650 unsigned MajorVersion, MinorVersion;
651 if (MinorVersionStr.getAsInteger(10, MinorVersion))
653 "failed to parse minor version number");
654
655 // Split Prefix into the extension name and the major version number
656 // (the trailing digits of Prefix).
657 int TrailingDigits = 0;
658 StringRef ExtName = Prefix;
659 while (!ExtName.empty()) {
660 if (!isDigit(ExtName.back()))
661 break;
662 ExtName = ExtName.drop_back(1);
663 TrailingDigits++;
664 }
665 if (!TrailingDigits)
667 "extension lacks version in expected format");
668
669 StringRef MajorVersionStr = Prefix.take_back(TrailingDigits);
670 if (MajorVersionStr.getAsInteger(10, MajorVersion))
672 "failed to parse major version number");
673 ISAInfo->addExtension(ExtName, MajorVersion, MinorVersion);
674 }
675 ISAInfo->updateFLen();
676 ISAInfo->updateMinVLen();
677 ISAInfo->updateMaxELen();
678 return std::move(ISAInfo);
679}
680
682RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension,
683 bool ExperimentalExtensionVersionCheck,
684 bool IgnoreUnknown) {
685 // RISC-V ISA strings must be lowercase.
686 if (llvm::any_of(Arch, isupper)) {
688 "string must be lowercase");
689 }
690
691 bool HasRV64 = Arch.startswith("rv64");
692 // ISA string must begin with rv32 or rv64.
693 if (!(Arch.startswith("rv32") || HasRV64) || (Arch.size() < 5)) {
694 return createStringError(
696 "string must begin with rv32{i,e,g} or rv64{i,e,g}");
697 }
698
699 unsigned XLen = HasRV64 ? 64 : 32;
700 std::unique_ptr<RISCVISAInfo> ISAInfo(new RISCVISAInfo(XLen));
701
702 // The canonical order specified in ISA manual.
703 // Ref: Table 22.1 in RISC-V User-Level ISA V2.2
704 StringRef StdExts = AllStdExts;
705 char Baseline = Arch[4];
706
707 // First letter should be 'e', 'i' or 'g'.
708 switch (Baseline) {
709 default:
711 "first letter should be 'e', 'i' or 'g'");
712 case 'e':
713 case 'i':
714 break;
715 case 'g':
716 // g expands to extensions in RISCVGImplications.
717 if (Arch.size() > 5 && isDigit(Arch[5]))
719 "version not supported for 'g'");
720 StdExts = StdExts.drop_front(4);
721 break;
722 }
723
724 if (Arch.back() == '_')
726 "extension name missing after separator '_'");
727
728 // Skip rvxxx
729 StringRef Exts = Arch.substr(5);
730
731 // Remove multi-letter standard extensions, non-standard extensions and
732 // supervisor-level extensions. They have 'z', 'x', 's' prefixes.
733 // Parse them at the end.
734 // Find the very first occurrence of 's', 'x' or 'z'.
735 StringRef OtherExts;
736 size_t Pos = Exts.find_first_of("zsx");
737 if (Pos != StringRef::npos) {
738 OtherExts = Exts.substr(Pos);
739 Exts = Exts.substr(0, Pos);
740 }
741
742 unsigned Major, Minor, ConsumeLength;
743 if (Baseline == 'g') {
744 // Versions for g are disallowed, and this was checked for previously.
745 ConsumeLength = 0;
746
747 // No matter which version is given to `g`, we always set imafd to default
748 // version since the we don't have clear version scheme for that on
749 // ISA spec.
750 for (const auto *Ext : RISCVGImplications) {
751 if (auto Version = findDefaultVersion(Ext))
752 ISAInfo->addExtension(Ext, Version->Major, Version->Minor);
753 else
754 llvm_unreachable("Default extension version not found?");
755 }
756 } else {
757 // Baseline is `i` or `e`
758 if (auto E = getExtensionVersion(
759 StringRef(&Baseline, 1), Exts, Major, Minor, ConsumeLength,
760 EnableExperimentalExtension, ExperimentalExtensionVersionCheck)) {
761 if (!IgnoreUnknown)
762 return std::move(E);
763 // If IgnoreUnknown, then ignore an unrecognised version of the baseline
764 // ISA and just use the default supported version.
765 consumeError(std::move(E));
766 auto Version = findDefaultVersion(StringRef(&Baseline, 1));
767 Major = Version->Major;
768 Minor = Version->Minor;
769 }
770
771 ISAInfo->addExtension(StringRef(&Baseline, 1), Major, Minor);
772 }
773
774 // Consume the base ISA version number and any '_' between rvxxx and the
775 // first extension
776 Exts = Exts.drop_front(ConsumeLength);
777 Exts.consume_front("_");
778
779 auto StdExtsItr = StdExts.begin();
780 auto StdExtsEnd = StdExts.end();
781 auto GoToNextExt = [](StringRef::iterator &I, unsigned ConsumeLength,
783 I += 1 + ConsumeLength;
784 if (I != E && *I == '_')
785 ++I;
786 };
787 for (auto I = Exts.begin(), E = Exts.end(); I != E;) {
788 char C = *I;
789
790 // Check ISA extensions are specified in the canonical order.
791 while (StdExtsItr != StdExtsEnd && *StdExtsItr != C)
792 ++StdExtsItr;
793
794 if (StdExtsItr == StdExtsEnd) {
795 // Either c contains a valid extension but it was not given in
796 // canonical order or it is an invalid extension.
797 if (StdExts.contains(C)) {
798 return createStringError(
800 "standard user-level extension not given in canonical order '%c'",
801 C);
802 }
803
805 "invalid standard user-level extension '%c'", C);
806 }
807
808 // Move to next char to prevent repeated letter.
809 ++StdExtsItr;
810
811 StringRef Next;
812 unsigned Major, Minor, ConsumeLength;
813 if (std::next(I) != E)
814 Next = StringRef(std::next(I), E - std::next(I));
815 if (auto E = getExtensionVersion(StringRef(&C, 1), Next, Major, Minor,
816 ConsumeLength, EnableExperimentalExtension,
817 ExperimentalExtensionVersionCheck)) {
818 if (IgnoreUnknown) {
819 consumeError(std::move(E));
820 GoToNextExt(I, ConsumeLength, Exts.end());
821 continue;
822 }
823 return std::move(E);
824 }
825
826 // The order is OK, then push it into features.
827 // Currently LLVM supports only "mafdcvh".
828 if (!isSupportedExtension(StringRef(&C, 1))) {
829 if (IgnoreUnknown) {
830 GoToNextExt(I, ConsumeLength, Exts.end());
831 continue;
832 }
834 "unsupported standard user-level extension '%c'",
835 C);
836 }
837 ISAInfo->addExtension(StringRef(&C, 1), Major, Minor);
838
839 // Consume full extension name and version, including any optional '_'
840 // between this extension and the next
841 GoToNextExt(I, ConsumeLength, Exts.end());
842 }
843
844 // Handle other types of extensions other than the standard
845 // general purpose and standard user-level extensions.
846 // Parse the ISA string containing non-standard user-level
847 // extensions, standard supervisor-level extensions and
848 // non-standard supervisor-level extensions.
849 // These extensions start with 'z', 's', 'x' prefixes, might have a version
850 // number (major, minor) and are separated by a single underscore '_'. We do
851 // not enforce a canonical order for them.
852 // Set the hardware features for the extensions that are supported.
853
854 // Multi-letter extensions are seperated by a single underscore
855 // as described in RISC-V User-Level ISA V2.2.
857 OtherExts.split(Split, '_');
858
860 if (Split.size() > 1 || Split[0] != "") {
861 for (StringRef Ext : Split) {
862 if (Ext.empty())
864 "extension name missing after separator '_'");
865
868 auto Pos = findLastNonVersionCharacter(Ext) + 1;
869 StringRef Name(Ext.substr(0, Pos));
870 StringRef Vers(Ext.substr(Pos));
871
872 if (Type.empty()) {
873 if (IgnoreUnknown)
874 continue;
876 "invalid extension prefix '" + Ext + "'");
877 }
878
879 if (!IgnoreUnknown && Name.size() == Type.size()) {
881 "%s name missing after '%s'",
882 Desc.str().c_str(), Type.str().c_str());
883 }
884
885 unsigned Major, Minor, ConsumeLength;
886 if (auto E = getExtensionVersion(Name, Vers, Major, Minor, ConsumeLength,
887 EnableExperimentalExtension,
888 ExperimentalExtensionVersionCheck)) {
889 if (IgnoreUnknown) {
890 consumeError(std::move(E));
891 continue;
892 }
893 return std::move(E);
894 }
895
896 // Check if duplicated extension.
897 if (!IgnoreUnknown && llvm::is_contained(AllExts, Name)) {
898 return createStringError(errc::invalid_argument, "duplicated %s '%s'",
899 Desc.str().c_str(), Name.str().c_str());
900 }
901
902 if (IgnoreUnknown && !isSupportedExtension(Name))
903 continue;
904
905 ISAInfo->addExtension(Name, Major, Minor);
906 // Extension format is correct, keep parsing the extensions.
907 // TODO: Save Type, Name, Major, Minor to avoid parsing them later.
908 AllExts.push_back(Name);
909 }
910 }
911
912 for (auto Ext : AllExts) {
913 if (!isSupportedExtension(Ext)) {
915 return createStringError(errc::invalid_argument, "unsupported %s '%s'",
916 Desc.str().c_str(), Ext.str().c_str());
917 }
918 }
919
920 return RISCVISAInfo::postProcessAndChecking(std::move(ISAInfo));
921}
922
923Error RISCVISAInfo::checkDependency() {
924 bool HasC = Exts.count("c") != 0;
925 bool HasF = Exts.count("f") != 0;
926 bool HasZfinx = Exts.count("zfinx") != 0;
927 bool HasVector = Exts.count("zve32x") != 0;
928 bool HasZvl = MinVLen != 0;
929 bool HasZcmt = Exts.count("zcmt") != 0;
930
931 if (HasF && HasZfinx)
933 "'f' and 'zfinx' extensions are incompatible");
934
935 if (HasZvl && !HasVector)
936 return createStringError(
938 "'zvl*b' requires 'v' or 'zve*' extension to also be specified");
939
940 if (Exts.count("zvbb") && !HasVector)
941 return createStringError(
943 "'zvbb' requires 'v' or 'zve*' extension to also be specified");
944
945 if (Exts.count("zvbc") && !Exts.count("zve64x"))
946 return createStringError(
948 "'zvbc' requires 'v' or 'zve64*' extension to also be specified");
949
950 if ((Exts.count("zvkg") || Exts.count("zvkned") || Exts.count("zvknha") ||
951 Exts.count("zvksed") || Exts.count("zvksh")) &&
952 !HasVector)
953 return createStringError(
955 "'zvk*' requires 'v' or 'zve*' extension to also be specified");
956
957 if (Exts.count("zvknhb") && !Exts.count("zve64x"))
958 return createStringError(
960 "'zvknhb' requires 'v' or 'zve64*' extension to also be specified");
961
962 if ((HasZcmt || Exts.count("zcmp")) && Exts.count("d") &&
963 (HasC || Exts.count("zcd")))
964 return createStringError(
966 Twine("'") + (HasZcmt ? "zcmt" : "zcmp") +
967 "' extension is incompatible with '" + (HasC ? "c" : "zcd") +
968 "' extension when 'd' extension is enabled");
969
970 if (XLen != 32 && Exts.count("zcf"))
972 "'zcf' is only supported for 'rv32'");
973
974 return Error::success();
975}
976
977static const char *ImpliedExtsD[] = {"f"};
978static const char *ImpliedExtsF[] = {"zicsr"};
979static const char *ImpliedExtsV[] = {"zvl128b", "zve64d"};
980static const char *ImpliedExtsXTHeadVdot[] = {"v"};
981static const char *ImpliedExtsXsfvcp[] = {"zve32x"};
982static const char *ImpliedExtsZacas[] = {"a"};
983static const char *ImpliedExtsZcb[] = {"zca"};
984static const char *ImpliedExtsZcd[] = {"d", "zca"};
985static const char *ImpliedExtsZce[] = {"zcb", "zcmp", "zcmt"};
986static const char *ImpliedExtsZcf[] = {"f", "zca"};
987static const char *ImpliedExtsZcmp[] = {"zca"};
988static const char *ImpliedExtsZcmt[] = {"zca"};
989static const char *ImpliedExtsZdinx[] = {"zfinx"};
990static const char *ImpliedExtsZfa[] = {"f"};
991static const char *ImpliedExtsZfbfmin[] = {"f"};
992static const char *ImpliedExtsZfh[] = {"f"};
993static const char *ImpliedExtsZfhmin[] = {"f"};
994static const char *ImpliedExtsZfinx[] = {"zicsr"};
995static const char *ImpliedExtsZhinx[] = {"zfinx"};
996static const char *ImpliedExtsZhinxmin[] = {"zfinx"};
997static const char *ImpliedExtsZicntr[] = {"zicsr"};
998static const char *ImpliedExtsZihpm[] = {"zicsr"};
999static const char *ImpliedExtsZk[] = {"zkn", "zkt", "zkr"};
1000static const char *ImpliedExtsZkn[] = {"zbkb", "zbkc", "zbkx",
1001 "zkne", "zknd", "zknh"};
1002static const char *ImpliedExtsZks[] = {"zbkb", "zbkc", "zbkx", "zksed", "zksh"};
1003static const char *ImpliedExtsZvbb[] = {"zvkb"};
1004static const char *ImpliedExtsZve32f[] = {"zve32x", "f"};
1005static const char *ImpliedExtsZve32x[] = {"zvl32b", "zicsr"};
1006static const char *ImpliedExtsZve64d[] = {"zve64f", "d"};
1007static const char *ImpliedExtsZve64f[] = {"zve64x", "zve32f"};
1008static const char *ImpliedExtsZve64x[] = {"zve32x", "zvl64b"};
1009static const char *ImpliedExtsZvfbfmin[] = {"zve32f", "zfbfmin"};
1010static const char *ImpliedExtsZvfbfwma[] = {"zvfbfmin"};
1011static const char *ImpliedExtsZvfh[] = {"zve32f", "zfhmin"};
1012static const char *ImpliedExtsZvfhmin[] = {"zve32f"};
1013static const char *ImpliedExtsZvkn[] = {"zvkb", "zvkned", "zvknhb", "zvkt"};
1014static const char *ImpliedExtsZvknc[] = {"zvbc", "zvkn"};
1015static const char *ImpliedExtsZvkng[] = {"zvkg", "zvkn"};
1016static const char *ImpliedExtsZvknhb[] = {"zvknha"};
1017static const char *ImpliedExtsZvks[] = {"zvkb", "zvksed", "zvksh", "zvkt"};
1018static const char *ImpliedExtsZvksc[] = {"zvbc", "zvks"};
1019static const char *ImpliedExtsZvksg[] = {"zvkg", "zvks"};
1020static const char *ImpliedExtsZvl1024b[] = {"zvl512b"};
1021static const char *ImpliedExtsZvl128b[] = {"zvl64b"};
1022static const char *ImpliedExtsZvl16384b[] = {"zvl8192b"};
1023static const char *ImpliedExtsZvl2048b[] = {"zvl1024b"};
1024static const char *ImpliedExtsZvl256b[] = {"zvl128b"};
1025static const char *ImpliedExtsZvl32768b[] = {"zvl16384b"};
1026static const char *ImpliedExtsZvl4096b[] = {"zvl2048b"};
1027static const char *ImpliedExtsZvl512b[] = {"zvl256b"};
1028static const char *ImpliedExtsZvl64b[] = {"zvl32b"};
1029static const char *ImpliedExtsZvl65536b[] = {"zvl32768b"};
1030static const char *ImpliedExtsZvl8192b[] = {"zvl4096b"};
1031
1035
1036 bool operator<(const ImpliedExtsEntry &Other) const {
1037 return Name < Other.Name;
1038 }
1039
1040 bool operator<(StringRef Other) const { return Name < Other; }
1041};
1042
1043// Note: The table needs to be sorted by name.
1044static constexpr ImpliedExtsEntry ImpliedExts[] = {
1045 {{"d"}, {ImpliedExtsD}},
1046 {{"f"}, {ImpliedExtsF}},
1047 {{"v"}, {ImpliedExtsV}},
1048 {{"xsfvcp"}, {ImpliedExtsXsfvcp}},
1049 {{"xtheadvdot"}, {ImpliedExtsXTHeadVdot}},
1050 {{"zacas"}, {ImpliedExtsZacas}},
1051 {{"zcb"}, {ImpliedExtsZcb}},
1052 {{"zcd"}, {ImpliedExtsZcd}},
1053 {{"zce"}, {ImpliedExtsZce}},
1054 {{"zcf"}, {ImpliedExtsZcf}},
1055 {{"zcmp"}, {ImpliedExtsZcmp}},
1056 {{"zcmt"}, {ImpliedExtsZcmt}},
1057 {{"zdinx"}, {ImpliedExtsZdinx}},
1058 {{"zfa"}, {ImpliedExtsZfa}},
1059 {{"zfbfmin"}, {ImpliedExtsZfbfmin}},
1060 {{"zfh"}, {ImpliedExtsZfh}},
1061 {{"zfhmin"}, {ImpliedExtsZfhmin}},
1062 {{"zfinx"}, {ImpliedExtsZfinx}},
1063 {{"zhinx"}, {ImpliedExtsZhinx}},
1064 {{"zhinxmin"}, {ImpliedExtsZhinxmin}},
1065 {{"zicntr"}, {ImpliedExtsZicntr}},
1066 {{"zihpm"}, {ImpliedExtsZihpm}},
1067 {{"zk"}, {ImpliedExtsZk}},
1068 {{"zkn"}, {ImpliedExtsZkn}},
1069 {{"zks"}, {ImpliedExtsZks}},
1070 {{"zvbb"}, {ImpliedExtsZvbb}},
1071 {{"zve32f"}, {ImpliedExtsZve32f}},
1072 {{"zve32x"}, {ImpliedExtsZve32x}},
1073 {{"zve64d"}, {ImpliedExtsZve64d}},
1074 {{"zve64f"}, {ImpliedExtsZve64f}},
1075 {{"zve64x"}, {ImpliedExtsZve64x}},
1076 {{"zvfbfmin"}, {ImpliedExtsZvfbfmin}},
1077 {{"zvfbfwma"}, {ImpliedExtsZvfbfwma}},
1078 {{"zvfh"}, {ImpliedExtsZvfh}},
1079 {{"zvfhmin"}, {ImpliedExtsZvfhmin}},
1080 {{"zvkn"}, {ImpliedExtsZvkn}},
1081 {{"zvknc"}, {ImpliedExtsZvknc}},
1082 {{"zvkng"}, {ImpliedExtsZvkng}},
1083 {{"zvknhb"}, {ImpliedExtsZvknhb}},
1084 {{"zvks"}, {ImpliedExtsZvks}},
1085 {{"zvksc"}, {ImpliedExtsZvksc}},
1086 {{"zvksg"}, {ImpliedExtsZvksg}},
1087 {{"zvl1024b"}, {ImpliedExtsZvl1024b}},
1088 {{"zvl128b"}, {ImpliedExtsZvl128b}},
1089 {{"zvl16384b"}, {ImpliedExtsZvl16384b}},
1090 {{"zvl2048b"}, {ImpliedExtsZvl2048b}},
1091 {{"zvl256b"}, {ImpliedExtsZvl256b}},
1092 {{"zvl32768b"}, {ImpliedExtsZvl32768b}},
1093 {{"zvl4096b"}, {ImpliedExtsZvl4096b}},
1094 {{"zvl512b"}, {ImpliedExtsZvl512b}},
1095 {{"zvl64b"}, {ImpliedExtsZvl64b}},
1096 {{"zvl65536b"}, {ImpliedExtsZvl65536b}},
1097 {{"zvl8192b"}, {ImpliedExtsZvl8192b}},
1098};
1099
1100void RISCVISAInfo::updateImplication() {
1101 bool HasE = Exts.count("e") != 0;
1102 bool HasI = Exts.count("i") != 0;
1103
1104 // If not in e extension and i extension does not exist, i extension is
1105 // implied
1106 if (!HasE && !HasI) {
1107 auto Version = findDefaultVersion("i");
1108 addExtension("i", Version->Major, Version->Minor);
1109 }
1110
1111 assert(llvm::is_sorted(ImpliedExts) && "Table not sorted by Name");
1112
1113 // This loop may execute over 1 iteration since implication can be layered
1114 // Exits loop if no more implication is applied
1116 for (auto const &Ext : Exts)
1117 WorkList.insert(Ext.first);
1118
1119 while (!WorkList.empty()) {
1120 StringRef ExtName = WorkList.pop_back_val();
1121 auto I = llvm::lower_bound(ImpliedExts, ExtName);
1122 if (I != std::end(ImpliedExts) && I->Name == ExtName) {
1123 for (const char *ImpliedExt : I->Exts) {
1124 if (WorkList.count(ImpliedExt))
1125 continue;
1126 if (Exts.count(ImpliedExt))
1127 continue;
1128 auto Version = findDefaultVersion(ImpliedExt);
1129 addExtension(ImpliedExt, Version->Major, Version->Minor);
1130 WorkList.insert(ImpliedExt);
1131 }
1132 }
1133 }
1134
1135 // Add Zcf if Zce and F are enabled on RV32.
1136 if (XLen == 32 && Exts.count("zce") && Exts.count("f") &&
1137 !Exts.count("zcf")) {
1138 auto Version = findDefaultVersion("zcf");
1139 addExtension("zcf", Version->Major, Version->Minor);
1140 }
1141}
1142
1146};
1147
1149 {{"zk"}, {ImpliedExtsZk}},
1150 {{"zkn"}, {ImpliedExtsZkn}},
1151 {{"zks"}, {ImpliedExtsZks}},
1152 {{"zvkn"}, {ImpliedExtsZvkn}},
1153 {{"zvknc"}, {ImpliedExtsZvknc}},
1154 {{"zvkng"}, {ImpliedExtsZvkng}},
1155 {{"zvks"}, {ImpliedExtsZvks}},
1156 {{"zvksc"}, {ImpliedExtsZvksc}},
1157 {{"zvksg"}, {ImpliedExtsZvksg}},
1158};
1159
1160void RISCVISAInfo::updateCombination() {
1161 bool IsNewCombine = false;
1162 do {
1163 IsNewCombine = false;
1164 for (CombinedExtsEntry CombineIntoExt : CombineIntoExts) {
1165 auto CombineExt = CombineIntoExt.CombineExt;
1166 auto RequiredExts = CombineIntoExt.RequiredExts;
1167 if (hasExtension(CombineExt))
1168 continue;
1169 bool IsAllRequiredFeatureExist = true;
1170 for (const char *Ext : RequiredExts)
1171 IsAllRequiredFeatureExist &= hasExtension(Ext);
1172 if (IsAllRequiredFeatureExist) {
1173 auto Version = findDefaultVersion(CombineExt);
1174 addExtension(CombineExt, Version->Major, Version->Minor);
1175 IsNewCombine = true;
1176 }
1177 }
1178 } while (IsNewCombine);
1179}
1180
1181void RISCVISAInfo::updateFLen() {
1182 FLen = 0;
1183 // TODO: Handle q extension.
1184 if (Exts.count("d"))
1185 FLen = 64;
1186 else if (Exts.count("f"))
1187 FLen = 32;
1188}
1189
1190void RISCVISAInfo::updateMinVLen() {
1191 for (auto const &Ext : Exts) {
1192 StringRef ExtName = Ext.first;
1193 bool IsZvlExt = ExtName.consume_front("zvl") && ExtName.consume_back("b");
1194 if (IsZvlExt) {
1195 unsigned ZvlLen;
1196 if (!ExtName.getAsInteger(10, ZvlLen))
1197 MinVLen = std::max(MinVLen, ZvlLen);
1198 }
1199 }
1200}
1201
1202void RISCVISAInfo::updateMaxELen() {
1203 // handles EEW restriction by sub-extension zve
1204 for (auto const &Ext : Exts) {
1205 StringRef ExtName = Ext.first;
1206 bool IsZveExt = ExtName.consume_front("zve");
1207 if (IsZveExt) {
1208 if (ExtName.back() == 'f')
1209 MaxELenFp = std::max(MaxELenFp, 32u);
1210 if (ExtName.back() == 'd')
1211 MaxELenFp = std::max(MaxELenFp, 64u);
1212 ExtName = ExtName.drop_back();
1213 unsigned ZveELen;
1214 ExtName.getAsInteger(10, ZveELen);
1215 MaxELen = std::max(MaxELen, ZveELen);
1216 }
1217 }
1218}
1219
1220std::string RISCVISAInfo::toString() const {
1221 std::string Buffer;
1222 raw_string_ostream Arch(Buffer);
1223
1224 Arch << "rv" << XLen;
1225
1226 ListSeparator LS("_");
1227 for (auto const &Ext : Exts) {
1228 StringRef ExtName = Ext.first;
1229 auto ExtInfo = Ext.second;
1230 Arch << LS << ExtName;
1231 Arch << ExtInfo.MajorVersion << "p" << ExtInfo.MinorVersion;
1232 }
1233
1234 return Arch.str();
1235}
1236
1237std::vector<std::string> RISCVISAInfo::toFeatureVector() const {
1238 std::vector<std::string> FeatureVector;
1239 for (auto const &Ext : Exts) {
1240 std::string ExtName = Ext.first;
1241 if (ExtName == "i") // i is not recognized in clang -cc1
1242 continue;
1243 if (!isSupportedExtension(ExtName))
1244 continue;
1245 std::string Feature = isExperimentalExtension(ExtName)
1246 ? "+experimental-" + ExtName
1247 : "+" + ExtName;
1248 FeatureVector.push_back(Feature);
1249 }
1250 return FeatureVector;
1251}
1252
1254RISCVISAInfo::postProcessAndChecking(std::unique_ptr<RISCVISAInfo> &&ISAInfo) {
1255 ISAInfo->updateImplication();
1256 ISAInfo->updateCombination();
1257 ISAInfo->updateFLen();
1258 ISAInfo->updateMinVLen();
1259 ISAInfo->updateMaxELen();
1260
1261 if (Error Result = ISAInfo->checkDependency())
1262 return std::move(Result);
1263 return std::move(ISAInfo);
1264}
1265
1267 if (XLen == 32) {
1268 if (hasExtension("d"))
1269 return "ilp32d";
1270 if (hasExtension("e"))
1271 return "ilp32e";
1272 return "ilp32";
1273 } else if (XLen == 64) {
1274 if (hasExtension("d"))
1275 return "lp64d";
1276 if (hasExtension("e"))
1277 return "lp64e";
1278 return "lp64";
1279 }
1280 llvm_unreachable("Invalid XLEN");
1281}
1282
1284 if (Ext.empty())
1285 return false;
1286
1287 auto Pos = findLastNonVersionCharacter(Ext) + 1;
1288 StringRef Name = Ext.substr(0, Pos);
1289 StringRef Vers = Ext.substr(Pos);
1290 if (Vers.empty())
1291 return false;
1292
1293 unsigned Major, Minor, ConsumeLength;
1294 if (auto E = getExtensionVersion(Name, Vers, Major, Minor, ConsumeLength,
1295 true, true)) {
1296 consumeError(std::move(E));
1297 return false;
1298 }
1299
1300 return true;
1301}
1302
1304 if (Ext.empty())
1305 return std::string();
1306
1307 auto Pos = findLastNonVersionCharacter(Ext) + 1;
1308 StringRef Name = Ext.substr(0, Pos);
1309
1310 if (Pos != Ext.size() && !isSupportedExtensionWithVersion(Ext))
1311 return std::string();
1312
1314 return std::string();
1315
1316 return isExperimentalExtension(Name) ? "experimental-" + Name.str()
1317 : Name.str();
1318}
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 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:154
static ErrorSuccess success()
Create a success value.
Definition: Error.h:328
Tagged union holding either a T or a Error.
Definition: Error.h:468
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:44
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
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:1037
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:1238
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
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:125
void riscvExtensionsHelp()
FormattedString left_justify(StringRef Str, unsigned Width)
left_justify - append spaces after string so total output is Width characters.
Definition: Format.h:146
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:1035
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.