LLVM 17.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 <optional>
20#include <string>
21#include <vector>
22
23using namespace llvm;
24
25namespace {
26/// Represents the major and version number components of a RISC-V extension
27struct RISCVExtensionVersion {
28 unsigned Major;
29 unsigned Minor;
30};
31
32struct RISCVSupportedExtension {
33 const char *Name;
34 /// Supported version.
35 RISCVExtensionVersion Version;
36};
37
38} // end anonymous namespace
39
40static constexpr StringLiteral AllStdExts = "mafdqlcbkjtpvnh";
41
42static const char *RISCVGImplications[] = {
43 "i", "m", "a", "f", "d", "zicsr", "zifencei"
44};
45
46static const RISCVSupportedExtension SupportedExtensions[] = {
47 {"i", RISCVExtensionVersion{2, 1}},
48 {"e", RISCVExtensionVersion{2, 0}},
49 {"m", RISCVExtensionVersion{2, 0}},
50 {"a", RISCVExtensionVersion{2, 1}},
51 {"f", RISCVExtensionVersion{2, 2}},
52 {"d", RISCVExtensionVersion{2, 2}},
53 {"c", RISCVExtensionVersion{2, 0}},
54
55 {"h", RISCVExtensionVersion{1, 0}},
56
57 {"zihintpause", RISCVExtensionVersion{2, 0}},
58
59 {"zfhmin", RISCVExtensionVersion{1, 0}},
60 {"zfh", RISCVExtensionVersion{1, 0}},
61
62 {"zfinx", RISCVExtensionVersion{1, 0}},
63 {"zdinx", RISCVExtensionVersion{1, 0}},
64 {"zhinxmin", RISCVExtensionVersion{1, 0}},
65 {"zhinx", RISCVExtensionVersion{1, 0}},
66
67 {"zba", RISCVExtensionVersion{1, 0}},
68 {"zbb", RISCVExtensionVersion{1, 0}},
69 {"zbc", RISCVExtensionVersion{1, 0}},
70 {"zbs", RISCVExtensionVersion{1, 0}},
71
72 {"zbkb", RISCVExtensionVersion{1, 0}},
73 {"zbkc", RISCVExtensionVersion{1, 0}},
74 {"zbkx", RISCVExtensionVersion{1, 0}},
75 {"zknd", RISCVExtensionVersion{1, 0}},
76 {"zkne", RISCVExtensionVersion{1, 0}},
77 {"zknh", RISCVExtensionVersion{1, 0}},
78 {"zksed", RISCVExtensionVersion{1, 0}},
79 {"zksh", RISCVExtensionVersion{1, 0}},
80 {"zkr", RISCVExtensionVersion{1, 0}},
81 {"zkn", RISCVExtensionVersion{1, 0}},
82 {"zks", RISCVExtensionVersion{1, 0}},
83 {"zkt", RISCVExtensionVersion{1, 0}},
84 {"zk", RISCVExtensionVersion{1, 0}},
85
86 {"zmmul", RISCVExtensionVersion{1, 0}},
87
88 {"v", RISCVExtensionVersion{1, 0}},
89 {"zvl32b", RISCVExtensionVersion{1, 0}},
90 {"zvl64b", RISCVExtensionVersion{1, 0}},
91 {"zvl128b", RISCVExtensionVersion{1, 0}},
92 {"zvl256b", RISCVExtensionVersion{1, 0}},
93 {"zvl512b", RISCVExtensionVersion{1, 0}},
94 {"zvl1024b", RISCVExtensionVersion{1, 0}},
95 {"zvl2048b", RISCVExtensionVersion{1, 0}},
96 {"zvl4096b", RISCVExtensionVersion{1, 0}},
97 {"zvl8192b", RISCVExtensionVersion{1, 0}},
98 {"zvl16384b", RISCVExtensionVersion{1, 0}},
99 {"zvl32768b", RISCVExtensionVersion{1, 0}},
100 {"zvl65536b", RISCVExtensionVersion{1, 0}},
101 {"zve32x", RISCVExtensionVersion{1, 0}},
102 {"zve32f", RISCVExtensionVersion{1, 0}},
103 {"zve64x", RISCVExtensionVersion{1, 0}},
104 {"zve64f", RISCVExtensionVersion{1, 0}},
105 {"zve64d", RISCVExtensionVersion{1, 0}},
106
107 {"zicbom", RISCVExtensionVersion{1, 0}},
108 {"zicboz", RISCVExtensionVersion{1, 0}},
109 {"zicbop", RISCVExtensionVersion{1, 0}},
110 {"zicsr", RISCVExtensionVersion{2, 0}},
111 {"zifencei", RISCVExtensionVersion{2, 0}},
112
113 {"zawrs", RISCVExtensionVersion{1, 0}},
114
115 {"svnapot", RISCVExtensionVersion{1, 0}},
116 {"svpbmt", RISCVExtensionVersion{1, 0}},
117 {"svinval", RISCVExtensionVersion{1, 0}},
118
119 // vendor-defined ('X') extensions
120 {"xtheadba", RISCVExtensionVersion{1, 0}},
121 {"xtheadbb", RISCVExtensionVersion{1, 0}},
122 {"xtheadbs", RISCVExtensionVersion{1, 0}},
123 {"xtheadcmo", RISCVExtensionVersion{1, 0}},
124 {"xtheadcondmov", RISCVExtensionVersion{1, 0}},
125 {"xtheadfmemidx", RISCVExtensionVersion{1, 0}},
126 {"xtheadmac", RISCVExtensionVersion{1, 0}},
127 {"xtheadmemidx", RISCVExtensionVersion{1, 0}},
128 {"xtheadmempair", RISCVExtensionVersion{1, 0}},
129 {"xtheadsync", RISCVExtensionVersion{1, 0}},
130 {"xtheadvdot", RISCVExtensionVersion{1, 0}},
131 {"xventanacondops", RISCVExtensionVersion{1, 0}},
132};
133
134static const RISCVSupportedExtension SupportedExperimentalExtensions[] = {
135 {"zihintntl", RISCVExtensionVersion{0, 2}},
136
137 {"zca", RISCVExtensionVersion{1, 0}},
138 {"zcb", RISCVExtensionVersion{1, 0}},
139 {"zcd", RISCVExtensionVersion{1, 0}},
140 {"zcf", RISCVExtensionVersion{1, 0}},
141 {"zfa", RISCVExtensionVersion{0, 1}},
142 {"zicond", RISCVExtensionVersion{1, 0}},
143 {"zvfh", RISCVExtensionVersion{0, 1}},
144 {"ztso", RISCVExtensionVersion{0, 1}},
145
146 // vector crypto
147 {"zvkb", RISCVExtensionVersion{0, 3}},
148 {"zvkg", RISCVExtensionVersion{0, 3}},
149 {"zvkn", RISCVExtensionVersion{0, 3}},
150 {"zvknha", RISCVExtensionVersion{0, 3}},
151 {"zvknhb", RISCVExtensionVersion{0, 3}},
152 {"zvkned", RISCVExtensionVersion{0, 3}},
153 {"zvks", RISCVExtensionVersion{0, 3}},
154 {"zvksed", RISCVExtensionVersion{0, 3}},
155 {"zvksh", RISCVExtensionVersion{0, 3}},
156};
157
159 return Ext.consume_front("experimental-");
160}
161
162// This function finds the first character that doesn't belong to a version
163// (e.g. zba1p0 is extension 'zba' of version '1p0'). So the function will
164// consume [0-9]*p[0-9]* starting from the backward. An extension name will not
165// end with a digit or the letter 'p', so this function will parse correctly.
166// NOTE: This function is NOT able to take empty strings or strings that only
167// have version numbers and no extension name. It assumes the extension name
168// will be at least more than one character.
170 assert(!Ext.empty() &&
171 "Already guarded by if-statement in ::parseArchString");
172
173 int Pos = Ext.size() - 1;
174 while (Pos > 0 && isDigit(Ext[Pos]))
175 Pos--;
176 if (Pos > 0 && Ext[Pos] == 'p' && isDigit(Ext[Pos - 1])) {
177 Pos--;
178 while (Pos > 0 && isDigit(Ext[Pos]))
179 Pos--;
180 }
181 return Pos;
182}
183
184namespace {
185struct FindByName {
186 FindByName(StringRef Ext) : Ext(Ext){};
188 bool operator()(const RISCVSupportedExtension &ExtInfo) {
189 return ExtInfo.Name == Ext;
190 }
191};
192} // namespace
193
194static std::optional<RISCVExtensionVersion>
196 // Find default version of an extension.
197 // TODO: We might set default version based on profile or ISA spec.
198 for (auto &ExtInfo : {ArrayRef(SupportedExtensions),
200 auto ExtensionInfoIterator = llvm::find_if(ExtInfo, FindByName(ExtName));
201
202 if (ExtensionInfoIterator == ExtInfo.end()) {
203 continue;
204 }
205 return ExtensionInfoIterator->Version;
206 }
207 return std::nullopt;
208}
209
210void RISCVISAInfo::addExtension(StringRef ExtName, unsigned MajorVersion,
211 unsigned MinorVersion) {
213 Ext.MajorVersion = MajorVersion;
214 Ext.MinorVersion = MinorVersion;
215 Exts[ExtName.str()] = Ext;
216}
217
219 if (Ext.startswith("sx"))
220 return "non-standard supervisor-level extension";
221 if (Ext.startswith("s"))
222 return "standard supervisor-level extension";
223 if (Ext.startswith("x"))
224 return "non-standard user-level extension";
225 if (Ext.startswith("z"))
226 return "standard user-level extension";
227 return StringRef();
228}
229
231 if (Ext.startswith("sx"))
232 return "sx";
233 if (Ext.startswith("s"))
234 return "s";
235 if (Ext.startswith("x"))
236 return "x";
237 if (Ext.startswith("z"))
238 return "z";
239 return StringRef();
240}
241
242static std::optional<RISCVExtensionVersion>
244 auto ExtIterator =
246 if (ExtIterator == std::end(SupportedExperimentalExtensions))
247 return std::nullopt;
248
249 return ExtIterator->Version;
250}
251
253 bool IsExperimental = stripExperimentalPrefix(Ext);
254
255 if (IsExperimental)
256 return llvm::any_of(SupportedExperimentalExtensions, FindByName(Ext));
257 else
258 return llvm::any_of(SupportedExtensions, FindByName(Ext));
259}
260
262 return llvm::any_of(SupportedExtensions, FindByName(Ext)) ||
264}
265
266bool RISCVISAInfo::isSupportedExtension(StringRef Ext, unsigned MajorVersion,
267 unsigned MinorVersion) {
268 auto FindByNameAndVersion = [=](const RISCVSupportedExtension &ExtInfo) {
269 return ExtInfo.Name == Ext && (MajorVersion == ExtInfo.Version.Major) &&
270 (MinorVersion == ExtInfo.Version.Minor);
271 };
272 return llvm::any_of(SupportedExtensions, FindByNameAndVersion) ||
273 llvm::any_of(SupportedExperimentalExtensions, FindByNameAndVersion);
274}
275
278
279 if (!isSupportedExtension(Ext))
280 return false;
281
282 return Exts.count(Ext.str()) != 0;
283}
284
285// We rank extensions in the following order:
286// -Single letter extensions in canonical order.
287// -Unknown single letter extensions in alphabetical order.
288// -Multi-letter extensions starting with 's' in alphabetical order.
289// -Multi-letter extensions starting with 'z' sorted by canonical order of
290// the second letter then sorted alphabetically.
291// -X extensions in alphabetical order.
292// These flags are used to indicate the category. The first 6 bits store the
293// single letter extension rank for single letter and multi-letter extensions
294// starting with 'z'.
299};
300
301// Get the rank for single-letter extension, lower value meaning higher
302// priority.
303static unsigned singleLetterExtensionRank(char Ext) {
304 assert(Ext >= 'a' && Ext <= 'z');
305 switch (Ext) {
306 case 'i':
307 return 0;
308 case 'e':
309 return 1;
310 }
311
312 size_t Pos = AllStdExts.find(Ext);
313 if (Pos != StringRef::npos)
314 return Pos + 2; // Skip 'e' and 'i' from above.
315
316 // If we got an unknown extension letter, then give it an alphabetical
317 // order, but after all known standard extensions.
318 return 2 + AllStdExts.size() + (Ext - 'a');
319}
320
321// Get the rank for multi-letter extension, lower value meaning higher
322// priority/order in canonical order.
323static unsigned getExtensionRank(const std::string &ExtName) {
324 assert(ExtName.size() >= 1);
325 switch (ExtName[0]) {
326 case 's':
327 return RF_S_EXTENSION;
328 case 'z':
329 assert(ExtName.size() >= 2);
330 // `z` extension must be sorted by canonical order of second letter.
331 // e.g. zmx has higher rank than zax.
332 return RF_Z_EXTENSION | singleLetterExtensionRank(ExtName[1]);
333 case 'x':
334 return RF_X_EXTENSION;
335 default:
336 assert(ExtName.size() == 1);
337 return singleLetterExtensionRank(ExtName[0]);
338 }
339}
340
341// Compare function for extension.
342// Only compare the extension name, ignore version comparison.
343bool RISCVISAInfo::compareExtension(const std::string &LHS,
344 const std::string &RHS) {
345 unsigned LHSRank = getExtensionRank(LHS);
346 unsigned RHSRank = getExtensionRank(RHS);
347
348 // If the ranks differ, pick the lower rank.
349 if (LHSRank != RHSRank)
350 return LHSRank < RHSRank;
351
352 // If the rank is same, it must be sorted by lexicographic order.
353 return LHS < RHS;
354}
355
357 std::vector<StringRef> &Features,
358 llvm::function_ref<StringRef(const Twine &)> StrAlloc,
359 bool AddAllExtensions) const {
360 for (auto const &Ext : Exts) {
361 StringRef ExtName = Ext.first;
362
363 if (ExtName == "i")
364 continue;
365
366 if (isExperimentalExtension(ExtName)) {
367 Features.push_back(StrAlloc("+experimental-" + ExtName));
368 } else {
369 Features.push_back(StrAlloc("+" + ExtName));
370 }
371 }
372 if (AddAllExtensions) {
373 for (const RISCVSupportedExtension &Ext : SupportedExtensions) {
374 if (Exts.count(Ext.Name))
375 continue;
376 Features.push_back(StrAlloc(Twine("-") + Ext.Name));
377 }
378
379 for (const RISCVSupportedExtension &Ext : SupportedExperimentalExtensions) {
380 if (Exts.count(Ext.Name))
381 continue;
382 Features.push_back(StrAlloc(Twine("-experimental-") + Ext.Name));
383 }
384 }
385}
386
387// Extensions may have a version number, and may be separated by
388// an underscore '_' e.g.: rv32i2_m2.
389// Version number is divided into major and minor version numbers,
390// separated by a 'p'. If the minor version is 0 then 'p0' can be
391// omitted from the version string. E.g., rv32i2p0, rv32i2, rv32i2p1.
392static Error getExtensionVersion(StringRef Ext, StringRef In, unsigned &Major,
393 unsigned &Minor, unsigned &ConsumeLength,
394 bool EnableExperimentalExtension,
395 bool ExperimentalExtensionVersionCheck) {
396 StringRef MajorStr, MinorStr;
397 Major = 0;
398 Minor = 0;
399 ConsumeLength = 0;
400 MajorStr = In.take_while(isDigit);
401 In = In.substr(MajorStr.size());
402
403 if (!MajorStr.empty() && In.consume_front("p")) {
404 MinorStr = In.take_while(isDigit);
405 In = In.substr(MajorStr.size() + MinorStr.size() - 1);
406
407 // Expected 'p' to be followed by minor version number.
408 if (MinorStr.empty()) {
409 return createStringError(
411 "minor version number missing after 'p' for extension '" + Ext + "'");
412 }
413 }
414
415 if (!MajorStr.empty() && MajorStr.getAsInteger(10, Major))
416 return createStringError(
418 "Failed to parse major version number for extension '" + Ext + "'");
419
420 if (!MinorStr.empty() && MinorStr.getAsInteger(10, Minor))
421 return createStringError(
423 "Failed to parse minor version number for extension '" + Ext + "'");
424
425 ConsumeLength = MajorStr.size();
426
427 if (!MinorStr.empty())
428 ConsumeLength += MinorStr.size() + 1 /*'p'*/;
429
430 // Expected multi-character extension with version number to have no
431 // subsequent characters (i.e. must either end string or be followed by
432 // an underscore).
433 if (Ext.size() > 1 && In.size()) {
434 std::string Error =
435 "multi-character extensions must be separated by underscores";
437 }
438
439 // If experimental extension, require use of current version number number
440 if (auto ExperimentalExtension = isExperimentalExtension(Ext)) {
441 if (!EnableExperimentalExtension) {
442 std::string Error = "requires '-menable-experimental-extensions' for "
443 "experimental extension '" +
444 Ext.str() + "'";
446 }
447
448 if (ExperimentalExtensionVersionCheck &&
449 (MajorStr.empty() && MinorStr.empty())) {
450 std::string Error =
451 "experimental extension requires explicit version number `" +
452 Ext.str() + "`";
454 }
455
456 auto SupportedVers = *ExperimentalExtension;
457 if (ExperimentalExtensionVersionCheck &&
458 (Major != SupportedVers.Major || Minor != SupportedVers.Minor)) {
459 std::string Error = "unsupported version number " + MajorStr.str();
460 if (!MinorStr.empty())
461 Error += "." + MinorStr.str();
462 Error += " for experimental extension '" + Ext.str() +
463 "' (this compiler supports " + utostr(SupportedVers.Major) +
464 "." + utostr(SupportedVers.Minor) + ")";
466 }
467 return Error::success();
468 }
469
470 // Exception rule for `g`, we don't have clear version scheme for that on
471 // ISA spec.
472 if (Ext == "g")
473 return Error::success();
474
475 if (MajorStr.empty() && MinorStr.empty()) {
476 if (auto DefaultVersion = findDefaultVersion(Ext)) {
477 Major = DefaultVersion->Major;
478 Minor = DefaultVersion->Minor;
479 }
480 // No matter found or not, return success, assume other place will
481 // verify.
482 return Error::success();
483 }
484
485 if (RISCVISAInfo::isSupportedExtension(Ext, Major, Minor))
486 return Error::success();
487
488 std::string Error = "unsupported version number " + std::string(MajorStr);
489 if (!MinorStr.empty())
490 Error += "." + MinorStr.str();
491 Error += " for extension '" + Ext.str() + "'";
493}
494
497 const std::vector<std::string> &Features) {
498 assert(XLen == 32 || XLen == 64);
499 std::unique_ptr<RISCVISAInfo> ISAInfo(new RISCVISAInfo(XLen));
500
501 for (auto &Feature : Features) {
502 StringRef ExtName = Feature;
503 bool Experimental = false;
504 assert(ExtName.size() > 1 && (ExtName[0] == '+' || ExtName[0] == '-'));
505 bool Add = ExtName[0] == '+';
506 ExtName = ExtName.drop_front(1); // Drop '+' or '-'
507 Experimental = stripExperimentalPrefix(ExtName);
508 auto ExtensionInfos = Experimental
511 auto ExtensionInfoIterator =
512 llvm::find_if(ExtensionInfos, FindByName(ExtName));
513
514 // Not all features is related to ISA extension, like `relax` or
515 // `save-restore`, skip those feature.
516 if (ExtensionInfoIterator == ExtensionInfos.end())
517 continue;
518
519 if (Add)
520 ISAInfo->addExtension(ExtName, ExtensionInfoIterator->Version.Major,
521 ExtensionInfoIterator->Version.Minor);
522 else
523 ISAInfo->Exts.erase(ExtName.str());
524 }
525
526 return RISCVISAInfo::postProcessAndChecking(std::move(ISAInfo));
527}
528
531 if (llvm::any_of(Arch, isupper)) {
533 "string must be lowercase");
534 }
535 // Must start with a valid base ISA name.
536 unsigned XLen;
537 if (Arch.startswith("rv32i") || Arch.startswith("rv32e"))
538 XLen = 32;
539 else if (Arch.startswith("rv64i") || Arch.startswith("rv64e"))
540 XLen = 64;
541 else
543 "arch string must begin with valid base ISA");
544 std::unique_ptr<RISCVISAInfo> ISAInfo(new RISCVISAInfo(XLen));
545 // Discard rv32/rv64 prefix.
546 Arch = Arch.substr(4);
547
548 // Each extension is of the form ${name}${major_version}p${minor_version}
549 // and separated by _. Split by _ and then extract the name and version
550 // information for each extension.
552 Arch.split(Split, '_');
553 for (StringRef Ext : Split) {
554 StringRef Prefix, MinorVersionStr;
555 std::tie(Prefix, MinorVersionStr) = Ext.rsplit('p');
556 if (MinorVersionStr.empty())
558 "extension lacks version in expected format");
559 unsigned MajorVersion, MinorVersion;
560 if (MinorVersionStr.getAsInteger(10, MinorVersion))
562 "failed to parse minor version number");
563
564 // Split Prefix into the extension name and the major version number
565 // (the trailing digits of Prefix).
566 int TrailingDigits = 0;
567 StringRef ExtName = Prefix;
568 while (!ExtName.empty()) {
569 if (!isDigit(ExtName.back()))
570 break;
571 ExtName = ExtName.drop_back(1);
572 TrailingDigits++;
573 }
574 if (!TrailingDigits)
576 "extension lacks version in expected format");
577
578 StringRef MajorVersionStr = Prefix.take_back(TrailingDigits);
579 if (MajorVersionStr.getAsInteger(10, MajorVersion))
581 "failed to parse major version number");
582 ISAInfo->addExtension(ExtName, MajorVersion, MinorVersion);
583 }
584 ISAInfo->updateFLen();
585 ISAInfo->updateMinVLen();
586 ISAInfo->updateMaxELen();
587 return std::move(ISAInfo);
588}
589
591RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension,
592 bool ExperimentalExtensionVersionCheck,
593 bool IgnoreUnknown) {
594 // RISC-V ISA strings must be lowercase.
595 if (llvm::any_of(Arch, isupper)) {
597 "string must be lowercase");
598 }
599
600 bool HasRV64 = Arch.startswith("rv64");
601 // ISA string must begin with rv32 or rv64.
602 if (!(Arch.startswith("rv32") || HasRV64) || (Arch.size() < 5)) {
603 return createStringError(
605 "string must begin with rv32{i,e,g} or rv64{i,e,g}");
606 }
607
608 unsigned XLen = HasRV64 ? 64 : 32;
609 std::unique_ptr<RISCVISAInfo> ISAInfo(new RISCVISAInfo(XLen));
610
611 // The canonical order specified in ISA manual.
612 // Ref: Table 22.1 in RISC-V User-Level ISA V2.2
613 StringRef StdExts = AllStdExts;
614 char Baseline = Arch[4];
615
616 // First letter should be 'e', 'i' or 'g'.
617 switch (Baseline) {
618 default:
620 "first letter should be 'e', 'i' or 'g'");
621 case 'e':
622 case 'i':
623 break;
624 case 'g':
625 // g expands to extensions in RISCVGImplications.
626 if (Arch.size() > 5 && isDigit(Arch[5]))
628 "version not supported for 'g'");
629 StdExts = StdExts.drop_front(4);
630 break;
631 }
632
633 if (Arch.back() == '_')
635 "extension name missing after separator '_'");
636
637 // Skip rvxxx
638 StringRef Exts = Arch.substr(5);
639
640 // Remove multi-letter standard extensions, non-standard extensions and
641 // supervisor-level extensions. They have 'z', 'x', 's', 'sx' prefixes.
642 // Parse them at the end.
643 // Find the very first occurrence of 's', 'x' or 'z'.
644 StringRef OtherExts;
645 size_t Pos = Exts.find_first_of("zsx");
646 if (Pos != StringRef::npos) {
647 OtherExts = Exts.substr(Pos);
648 Exts = Exts.substr(0, Pos);
649 }
650
651 unsigned Major, Minor, ConsumeLength;
652 if (Baseline == 'g') {
653 // Versions for g are disallowed, and this was checked for previously.
654 ConsumeLength = 0;
655
656 // No matter which version is given to `g`, we always set imafd to default
657 // version since the we don't have clear version scheme for that on
658 // ISA spec.
659 for (const auto *Ext : RISCVGImplications) {
660 if (auto Version = findDefaultVersion(Ext))
661 ISAInfo->addExtension(Ext, Version->Major, Version->Minor);
662 else
663 llvm_unreachable("Default extension version not found?");
664 }
665 } else {
666 // Baseline is `i` or `e`
667 if (auto E = getExtensionVersion(
668 StringRef(&Baseline, 1), Exts, Major, Minor, ConsumeLength,
669 EnableExperimentalExtension, ExperimentalExtensionVersionCheck)) {
670 if (!IgnoreUnknown)
671 return std::move(E);
672 // If IgnoreUnknown, then ignore an unrecognised version of the baseline
673 // ISA and just use the default supported version.
674 consumeError(std::move(E));
675 auto Version = findDefaultVersion(StringRef(&Baseline, 1));
676 Major = Version->Major;
677 Minor = Version->Minor;
678 }
679
680 ISAInfo->addExtension(StringRef(&Baseline, 1), Major, Minor);
681 }
682
683 // Consume the base ISA version number and any '_' between rvxxx and the
684 // first extension
685 Exts = Exts.drop_front(ConsumeLength);
686 Exts.consume_front("_");
687
688 // TODO: Use version number when setting target features
689
690 auto StdExtsItr = StdExts.begin();
691 auto StdExtsEnd = StdExts.end();
692 auto GoToNextExt = [](StringRef::iterator &I, unsigned ConsumeLength) {
693 I += 1 + ConsumeLength;
694 if (*I == '_')
695 ++I;
696 };
697 for (auto I = Exts.begin(), E = Exts.end(); I != E;) {
698 char C = *I;
699
700 // Check ISA extensions are specified in the canonical order.
701 while (StdExtsItr != StdExtsEnd && *StdExtsItr != C)
702 ++StdExtsItr;
703
704 if (StdExtsItr == StdExtsEnd) {
705 // Either c contains a valid extension but it was not given in
706 // canonical order or it is an invalid extension.
707 if (StdExts.contains(C)) {
708 return createStringError(
710 "standard user-level extension not given in canonical order '%c'",
711 C);
712 }
713
715 "invalid standard user-level extension '%c'", C);
716 }
717
718 // Move to next char to prevent repeated letter.
719 ++StdExtsItr;
720
721 StringRef Next;
722 unsigned Major, Minor, ConsumeLength;
723 if (std::next(I) != E)
724 Next = StringRef(std::next(I), E - std::next(I));
725 if (auto E = getExtensionVersion(StringRef(&C, 1), Next, Major, Minor,
726 ConsumeLength, EnableExperimentalExtension,
727 ExperimentalExtensionVersionCheck)) {
728 if (IgnoreUnknown) {
729 consumeError(std::move(E));
730 GoToNextExt(I, ConsumeLength);
731 continue;
732 }
733 return std::move(E);
734 }
735
736 // The order is OK, then push it into features.
737 // TODO: Use version number when setting target features
738 // Currently LLVM supports only "mafdcvh".
739 if (!isSupportedExtension(StringRef(&C, 1))) {
740 if (IgnoreUnknown) {
741 GoToNextExt(I, ConsumeLength);
742 continue;
743 }
745 "unsupported standard user-level extension '%c'",
746 C);
747 }
748 ISAInfo->addExtension(StringRef(&C, 1), Major, Minor);
749
750 // Consume full extension name and version, including any optional '_'
751 // between this extension and the next
752 GoToNextExt(I, ConsumeLength);
753 }
754
755 // Handle other types of extensions other than the standard
756 // general purpose and standard user-level extensions.
757 // Parse the ISA string containing non-standard user-level
758 // extensions, standard supervisor-level extensions and
759 // non-standard supervisor-level extensions.
760 // These extensions start with 'z', 'x', 's', 'sx' prefixes, follow a
761 // canonical order, might have a version number (major, minor)
762 // and are separated by a single underscore '_'.
763 // Set the hardware features for the extensions that are supported.
764
765 // Multi-letter extensions are seperated by a single underscore
766 // as described in RISC-V User-Level ISA V2.2.
768 OtherExts.split(Split, '_');
769
771 std::array<StringRef, 4> Prefix{"z", "x", "s", "sx"};
772 auto I = Prefix.begin();
773 auto E = Prefix.end();
774 if (Split.size() > 1 || Split[0] != "") {
775 for (StringRef Ext : Split) {
776 if (Ext.empty())
778 "extension name missing after separator '_'");
779
782 auto Pos = findFirstNonVersionCharacter(Ext) + 1;
783 StringRef Name(Ext.substr(0, Pos));
784 StringRef Vers(Ext.substr(Pos));
785
786 if (Type.empty()) {
787 if (IgnoreUnknown)
788 continue;
790 "invalid extension prefix '" + Ext + "'");
791 }
792
793 // Check ISA extensions are specified in the canonical order.
794 while (I != E && *I != Type)
795 ++I;
796
797 if (I == E) {
798 if (IgnoreUnknown)
799 continue;
801 "%s not given in canonical order '%s'",
802 Desc.str().c_str(), Ext.str().c_str());
803 }
804
805 if (!IgnoreUnknown && Name.size() == Type.size()) {
807 "%s name missing after '%s'",
808 Desc.str().c_str(), Type.str().c_str());
809 }
810
811 unsigned Major, Minor, ConsumeLength;
812 if (auto E = getExtensionVersion(Name, Vers, Major, Minor, ConsumeLength,
813 EnableExperimentalExtension,
814 ExperimentalExtensionVersionCheck)) {
815 if (IgnoreUnknown) {
816 consumeError(std::move(E));
817 continue;
818 }
819 return std::move(E);
820 }
821
822 // Check if duplicated extension.
823 if (!IgnoreUnknown && llvm::is_contained(AllExts, Name)) {
824 return createStringError(errc::invalid_argument, "duplicated %s '%s'",
825 Desc.str().c_str(), Name.str().c_str());
826 }
827
828 if (IgnoreUnknown && !isSupportedExtension(Name))
829 continue;
830
831 ISAInfo->addExtension(Name, Major, Minor);
832 // Extension format is correct, keep parsing the extensions.
833 // TODO: Save Type, Name, Major, Minor to avoid parsing them later.
834 AllExts.push_back(Name);
835 }
836 }
837
838 for (auto Ext : AllExts) {
839 if (!isSupportedExtension(Ext)) {
841 return createStringError(errc::invalid_argument, "unsupported %s '%s'",
842 Desc.str().c_str(), Ext.str().c_str());
843 }
844 }
845
846 return RISCVISAInfo::postProcessAndChecking(std::move(ISAInfo));
847}
848
849Error RISCVISAInfo::checkDependency() {
850 bool HasD = Exts.count("d") != 0;
851 bool HasF = Exts.count("f") != 0;
852 bool HasZfinx = Exts.count("zfinx") != 0;
853 bool HasZdinx = Exts.count("zdinx") != 0;
854 bool HasVector = Exts.count("zve32x") != 0;
855 bool HasZve32f = Exts.count("zve32f") != 0;
856 bool HasZve64d = Exts.count("zve64d") != 0;
857 bool HasZvl = MinVLen != 0;
858
859 if (HasF && HasZfinx)
861 "'f' and 'zfinx' extensions are incompatible");
862
863 if (HasZve32f && !HasF && !HasZfinx)
864 return createStringError(
866 "'zve32f' requires 'f' or 'zfinx' extension to also be specified");
867
868 if (HasZve64d && !HasD && !HasZdinx)
869 return createStringError(
871 "'zve64d' requires 'd' or 'zdinx' extension to also be specified");
872
873 if (Exts.count("zvfh") && !Exts.count("zfh") && !Exts.count("zfhmin") &&
874 !Exts.count("zhinx") && !Exts.count("zhinxmin"))
875 return createStringError(
877 "'zvfh' requires 'zfh', 'zfhmin', 'zhinx' or 'zhinxmin' extension to "
878 "also be specified");
879
880 if (HasZvl && !HasVector)
881 return createStringError(
883 "'zvl*b' requires 'v' or 'zve*' extension to also be specified");
884
885 if ((Exts.count("zvkb") || Exts.count("zvkg") || Exts.count("zvkn") ||
886 Exts.count("zvknha") || Exts.count("zvkned") || Exts.count("zvks") ||
887 Exts.count("zvksed") || Exts.count("zvksh")) &&
888 !HasVector)
889 return createStringError(
891 "'zvk*' requires 'v' or 'zve*' extension to also be specified");
892
893 if (Exts.count("zvknhb") && !Exts.count("zve64x"))
894 return createStringError(
896 "'zvknhb' requires 'v' or 'zve64*' extension to also be specified");
897
898 // Additional dependency checks.
899 // TODO: The 'q' extension requires rv64.
900 // TODO: It is illegal to specify 'e' extensions with 'f' and 'd'.
901
902 return Error::success();
903}
904
905static const char *ImpliedExtsF[] = {"zicsr"};
906static const char *ImpliedExtsD[] = {"f"};
907static const char *ImpliedExtsV[] = {"zvl128b", "zve64d", "f", "d"};
908static const char *ImpliedExtsZfhmin[] = {"f"};
909static const char *ImpliedExtsZfh[] = {"f"};
910static const char *ImpliedExtsZfinx[] = {"zicsr"};
911static const char *ImpliedExtsZdinx[] = {"zfinx"};
912static const char *ImpliedExtsZhinxmin[] = {"zfinx"};
913static const char *ImpliedExtsZhinx[] = {"zfinx"};
914static const char *ImpliedExtsZve64d[] = {"zve64f"};
915static const char *ImpliedExtsZve64f[] = {"zve64x", "zve32f"};
916static const char *ImpliedExtsZve64x[] = {"zve32x", "zvl64b"};
917static const char *ImpliedExtsZve32f[] = {"zve32x"};
918static const char *ImpliedExtsZve32x[] = {"zvl32b", "zicsr"};
919static const char *ImpliedExtsZvl65536b[] = {"zvl32768b"};
920static const char *ImpliedExtsZvl32768b[] = {"zvl16384b"};
921static const char *ImpliedExtsZvl16384b[] = {"zvl8192b"};
922static const char *ImpliedExtsZvl8192b[] = {"zvl4096b"};
923static const char *ImpliedExtsZvl4096b[] = {"zvl2048b"};
924static const char *ImpliedExtsZvl2048b[] = {"zvl1024b"};
925static const char *ImpliedExtsZvl1024b[] = {"zvl512b"};
926static const char *ImpliedExtsZvl512b[] = {"zvl256b"};
927static const char *ImpliedExtsZvl256b[] = {"zvl128b"};
928static const char *ImpliedExtsZvl128b[] = {"zvl64b"};
929static const char *ImpliedExtsZvl64b[] = {"zvl32b"};
930static const char *ImpliedExtsZk[] = {"zkn", "zkt", "zkr"};
931static const char *ImpliedExtsZkn[] = {"zbkb", "zbkc", "zbkx",
932 "zkne", "zknd", "zknh"};
933static const char *ImpliedExtsZks[] = {"zbkb", "zbkc", "zbkx", "zksed", "zksh"};
934static const char *ImpliedExtsZvfh[] = {"zve32f"};
935static const char *ImpliedExtsZvkn[] = {"zvkned", "zvknhb", "zvkb"};
936static const char *ImpliedExtsZvknhb[] = {"zvknha"};
937static const char *ImpliedExtsZvks[] = {"zvksed", "zvksh", "zvkb"};
938static const char *ImpliedExtsXTHeadVdot[] = {"v"};
939static const char *ImpliedExtsZcb[] = {"zca"};
940static const char *ImpliedExtsZfa[] = {"f"};
941
945
946 bool operator<(const ImpliedExtsEntry &Other) const {
947 return Name < Other.Name;
948 }
949
950 bool operator<(StringRef Other) const { return Name < Other; }
951};
952
953// Note: The table needs to be sorted by name.
954static constexpr ImpliedExtsEntry ImpliedExts[] = {
955 {{"d"}, {ImpliedExtsD}},
956 {{"f"}, {ImpliedExtsF}},
957 {{"v"}, {ImpliedExtsV}},
958 {{"xtheadvdot"}, {ImpliedExtsXTHeadVdot}},
959 {{"zcb"}, {ImpliedExtsZcb}},
960 {{"zdinx"}, {ImpliedExtsZdinx}},
961 {{"zfa"}, {ImpliedExtsZfa}},
962 {{"zfh"}, {ImpliedExtsZfh}},
963 {{"zfhmin"}, {ImpliedExtsZfhmin}},
964 {{"zfinx"}, {ImpliedExtsZfinx}},
965 {{"zhinx"}, {ImpliedExtsZhinx}},
966 {{"zhinxmin"}, {ImpliedExtsZhinxmin}},
967 {{"zk"}, {ImpliedExtsZk}},
968 {{"zkn"}, {ImpliedExtsZkn}},
969 {{"zks"}, {ImpliedExtsZks}},
970 {{"zve32f"}, {ImpliedExtsZve32f}},
971 {{"zve32x"}, {ImpliedExtsZve32x}},
972 {{"zve64d"}, {ImpliedExtsZve64d}},
973 {{"zve64f"}, {ImpliedExtsZve64f}},
974 {{"zve64x"}, {ImpliedExtsZve64x}},
975 {{"zvfh"}, {ImpliedExtsZvfh}},
976 {{"zvkn"}, {ImpliedExtsZvkn}},
977 {{"zvknhb"}, {ImpliedExtsZvknhb}},
978 {{"zvks"}, {ImpliedExtsZvks}},
979 {{"zvl1024b"}, {ImpliedExtsZvl1024b}},
980 {{"zvl128b"}, {ImpliedExtsZvl128b}},
981 {{"zvl16384b"}, {ImpliedExtsZvl16384b}},
982 {{"zvl2048b"}, {ImpliedExtsZvl2048b}},
983 {{"zvl256b"}, {ImpliedExtsZvl256b}},
984 {{"zvl32768b"}, {ImpliedExtsZvl32768b}},
985 {{"zvl4096b"}, {ImpliedExtsZvl4096b}},
986 {{"zvl512b"}, {ImpliedExtsZvl512b}},
987 {{"zvl64b"}, {ImpliedExtsZvl64b}},
988 {{"zvl65536b"}, {ImpliedExtsZvl65536b}},
989 {{"zvl8192b"}, {ImpliedExtsZvl8192b}},
990};
991
992void RISCVISAInfo::updateImplication() {
993 bool HasE = Exts.count("e") != 0;
994 bool HasI = Exts.count("i") != 0;
995
996 // If not in e extension and i extension does not exist, i extension is
997 // implied
998 if (!HasE && !HasI) {
999 auto Version = findDefaultVersion("i");
1000 addExtension("i", Version->Major, Version->Minor);
1001 }
1002
1003 assert(llvm::is_sorted(ImpliedExts) && "Table not sorted by Name");
1004
1005 // This loop may execute over 1 iteration since implication can be layered
1006 // Exits loop if no more implication is applied
1008 for (auto const &Ext : Exts)
1009 WorkList.insert(Ext.first);
1010
1011 while (!WorkList.empty()) {
1012 StringRef ExtName = WorkList.pop_back_val();
1013 auto I = llvm::lower_bound(ImpliedExts, ExtName);
1014 if (I != std::end(ImpliedExts) && I->Name == ExtName) {
1015 for (const char *ImpliedExt : I->Exts) {
1016 if (WorkList.count(ImpliedExt))
1017 continue;
1018 if (Exts.count(ImpliedExt))
1019 continue;
1020 auto Version = findDefaultVersion(ImpliedExt);
1021 addExtension(ImpliedExt, Version->Major, Version->Minor);
1022 WorkList.insert(ImpliedExt);
1023 }
1024 }
1025 }
1026}
1027
1031};
1032
1034 {{"zk"}, {ImpliedExtsZk}},
1035 {{"zkn"}, {ImpliedExtsZkn}},
1036 {{"zks"}, {ImpliedExtsZks}},
1037};
1038
1039void RISCVISAInfo::updateCombination() {
1040 bool IsNewCombine = false;
1041 do {
1042 IsNewCombine = false;
1043 for (CombinedExtsEntry CombineIntoExt : CombineIntoExts) {
1044 auto CombineExt = CombineIntoExt.CombineExt;
1045 auto RequiredExts = CombineIntoExt.RequiredExts;
1046 if (hasExtension(CombineExt))
1047 continue;
1048 bool IsAllRequiredFeatureExist = true;
1049 for (const char *Ext : RequiredExts)
1050 IsAllRequiredFeatureExist &= hasExtension(Ext);
1051 if (IsAllRequiredFeatureExist) {
1052 auto Version = findDefaultVersion(CombineExt);
1053 addExtension(CombineExt, Version->Major, Version->Minor);
1054 IsNewCombine = true;
1055 }
1056 }
1057 } while (IsNewCombine);
1058}
1059
1060void RISCVISAInfo::updateFLen() {
1061 FLen = 0;
1062 // TODO: Handle q extension.
1063 if (Exts.count("d"))
1064 FLen = 64;
1065 else if (Exts.count("f"))
1066 FLen = 32;
1067}
1068
1069void RISCVISAInfo::updateMinVLen() {
1070 for (auto const &Ext : Exts) {
1071 StringRef ExtName = Ext.first;
1072 bool IsZvlExt = ExtName.consume_front("zvl") && ExtName.consume_back("b");
1073 if (IsZvlExt) {
1074 unsigned ZvlLen;
1075 if (!ExtName.getAsInteger(10, ZvlLen))
1076 MinVLen = std::max(MinVLen, ZvlLen);
1077 }
1078 }
1079}
1080
1081void RISCVISAInfo::updateMaxELen() {
1082 // handles EEW restriction by sub-extension zve
1083 for (auto const &Ext : Exts) {
1084 StringRef ExtName = Ext.first;
1085 bool IsZveExt = ExtName.consume_front("zve");
1086 if (IsZveExt) {
1087 if (ExtName.back() == 'f')
1088 MaxELenFp = std::max(MaxELenFp, 32u);
1089 if (ExtName.back() == 'd')
1090 MaxELenFp = std::max(MaxELenFp, 64u);
1091 ExtName = ExtName.drop_back();
1092 unsigned ZveELen;
1093 ExtName.getAsInteger(10, ZveELen);
1094 MaxELen = std::max(MaxELen, ZveELen);
1095 }
1096 }
1097}
1098
1099std::string RISCVISAInfo::toString() const {
1100 std::string Buffer;
1101 raw_string_ostream Arch(Buffer);
1102
1103 Arch << "rv" << XLen;
1104
1105 ListSeparator LS("_");
1106 for (auto const &Ext : Exts) {
1107 StringRef ExtName = Ext.first;
1108 auto ExtInfo = Ext.second;
1109 Arch << LS << ExtName;
1110 Arch << ExtInfo.MajorVersion << "p" << ExtInfo.MinorVersion;
1111 }
1112
1113 return Arch.str();
1114}
1115
1116std::vector<std::string> RISCVISAInfo::toFeatureVector() const {
1117 std::vector<std::string> FeatureVector;
1118 for (auto const &Ext : Exts) {
1119 std::string ExtName = Ext.first;
1120 if (ExtName == "i") // i is not recognized in clang -cc1
1121 continue;
1122 if (!isSupportedExtension(ExtName))
1123 continue;
1124 std::string Feature = isExperimentalExtension(ExtName)
1125 ? "+experimental-" + ExtName
1126 : "+" + ExtName;
1127 FeatureVector.push_back(Feature);
1128 }
1129 return FeatureVector;
1130}
1131
1133RISCVISAInfo::postProcessAndChecking(std::unique_ptr<RISCVISAInfo> &&ISAInfo) {
1134 ISAInfo->updateImplication();
1135 ISAInfo->updateCombination();
1136 ISAInfo->updateFLen();
1137 ISAInfo->updateMinVLen();
1138 ISAInfo->updateMaxELen();
1139
1140 if (Error Result = ISAInfo->checkDependency())
1141 return std::move(Result);
1142 return std::move(ISAInfo);
1143}
1144
1146 if (XLen == 32) {
1147 if (hasExtension("d"))
1148 return "ilp32d";
1149 if (hasExtension("e"))
1150 return "ilp32e";
1151 return "ilp32";
1152 } else if (XLen == 64) {
1153 if (hasExtension("d"))
1154 return "lp64d";
1155 if (hasExtension("e"))
1156 return "lp64e";
1157 return "lp64";
1158 }
1159 llvm_unreachable("Invalid XLEN");
1160}
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
std::string Name
std::optional< std::vector< StOtherPiece > > Other
Definition: ELFYAML.cpp:1260
#define I(x, y, z)
Definition: MD5.cpp:58
static const char * ImpliedExtsZvl8192b[]
static const char * ImpliedExtsZks[]
static const char * ImpliedExtsZcb[]
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 const char * ImpliedExtsZvl1024b[]
static const char * ImpliedExtsZhinx[]
static constexpr CombinedExtsEntry CombineIntoExts[]
static const char * ImpliedExtsZvks[]
static const char * ImpliedExtsZve64x[]
static const char * ImpliedExtsZk[]
static const RISCVSupportedExtension SupportedExperimentalExtensions[]
static const char * ImpliedExtsZvl256b[]
static StringRef getExtensionType(StringRef Ext)
static const char * ImpliedExtsZfhmin[]
static std::optional< RISCVExtensionVersion > isExperimentalExtension(StringRef Ext)
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 * ImpliedExtsZvl16384b[]
static const char * ImpliedExtsZvl128b[]
static constexpr StringLiteral AllStdExts
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[]
RankFlags
@ RF_S_EXTENSION
@ RF_Z_EXTENSION
@ RF_X_EXTENSION
static unsigned getExtensionRank(const std::string &ExtName)
static const char * ImpliedExtsZdinx[]
static unsigned singleLetterExtensionRank(char Ext)
static size_t findFirstNonVersionCharacter(StringRef Ext)
static const char * ImpliedExtsZhinxmin[]
static const char * RISCVGImplications[]
static const char * ImpliedExtsV[]
static const char * ImpliedExtsZve64d[]
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
Lightweight error class with error context and mandatory checking.
Definition: Error.h:156
static ErrorSuccess success()
Create a success value.
Definition: Error.h:330
Tagged union holding either a T or a Error.
Definition: Error.h:470
static bool isSupportedExtensionFeature(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
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.
size_type count(const key_type &key) const
Count the number of elements of a given key in the SetVector.
Definition: SetVector.h:219
bool insert(const value_type &X)
Insert a new element into the SetVector.
Definition: SetVector.h:152
bool empty() const
Determine if the SetVector is empty or not.
Definition: SetVector.h:83
value_type pop_back_val()
Definition: SetVector.h:236
A SetVector that performs no allocations if smaller than a certain size.
Definition: SetVector.h:312
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:840
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:687
bool consume_back(StringRef Suffix)
Returns true if this StringRef has the given suffix and removes that suffix.
Definition: StringRef.h:642
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
Definition: StringRef.h:468
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:558
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:596
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:422
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:622
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:375
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:295
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:603
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:1058
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1246
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:1826
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:1999
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:2038
@ Add
Sum of integers.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1846
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition: STLExtras.h:1976
void consumeError(Error Err)
Consume a Error without doing anything.
Definition: Error.h:1043
StringLiteral CombineExt
ArrayRef< const char * > RequiredExts
StringLiteral Name
ArrayRef< const char * > Exts
bool operator<(const ImpliedExtsEntry &Other) const
bool operator<(StringRef Other) const