LLVM 24.0.0git
RISCVISAInfo.cpp
Go to the documentation of this file.
1//===-- RISCVISAInfo.cpp - RISC-V Arch String Parser ----------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10#include "llvm/ADT/STLExtras.h"
12#include "llvm/ADT/StringRef.h"
13#include "llvm/Support/Errc.h"
14#include "llvm/Support/Error.h"
17
18#include <atomic>
19#include <optional>
20#include <string>
21#include <vector>
22
23using namespace llvm;
24
25namespace {
26
27struct RISCVSupportedExtension {
28 const char *Name;
29 /// Supported version.
30 RISCVISAUtils::ExtensionVersion Version;
31
32 bool operator<(const RISCVSupportedExtension &RHS) const {
33 return StringRef(Name) < StringRef(RHS.Name);
34 }
35};
36
37struct RISCVProfile {
38 StringLiteral Name;
39 StringLiteral MArch;
40
41 bool operator<(const RISCVProfile &RHS) const {
42 return StringRef(Name) < StringRef(RHS.Name);
43 }
44};
45
46} // end anonymous namespace
47
48static const char *RISCVGImplications[] = {"i", "m", "a", "f", "d"};
49static const char *RISCVGImplicationsZi[] = {"zicsr", "zifencei"};
50
51#define GET_SUPPORTED_EXTENSIONS
52#include "llvm/TargetParser/RISCVTargetParserDef.inc"
53
54#define GET_SUPPORTED_PROFILES
55#include "llvm/TargetParser/RISCVTargetParserDef.inc"
56
57static void verifyTables() {
58#ifndef NDEBUG
59 static std::atomic<bool> TableChecked(false);
60 if (!TableChecked.load(std::memory_order_relaxed)) {
61 assert(llvm::is_sorted(SupportedExtensions) &&
62 "Extensions are not sorted by name");
63 assert(llvm::is_sorted(SupportedExperimentalExtensions) &&
64 "Experimental extensions are not sorted by name");
65 assert(llvm::is_sorted(SupportedProfiles) &&
66 "Profiles are not sorted by name");
67 assert(llvm::is_sorted(SupportedExperimentalProfiles) &&
68 "Experimental profiles are not sorted by name");
69 TableChecked.store(true, std::memory_order_relaxed);
70 }
71#endif
72}
73
74static void PrintExtension(StringRef Name, StringRef Version,
75 StringRef Description) {
76 outs().indent(4);
77 unsigned VersionWidth = Description.empty() ? 0 : 10;
78 outs() << left_justify(Name, 21) << left_justify(Version, VersionWidth)
79 << Description << "\n";
80}
81
83 outs() << "All available -march extensions for RISC-V\n\n";
84 PrintExtension("Name", "Version", (DescMap.empty() ? "" : "Description"));
85
87 for (const auto &E : SupportedExtensions)
88 ExtMap[E.Name] = {E.Version.Major, E.Version.Minor};
89 for (const auto &E : ExtMap) {
90 std::string Version =
91 std::to_string(E.second.Major) + "." + std::to_string(E.second.Minor);
92 PrintExtension(E.first, Version, DescMap[E.first]);
93 }
94
95 outs() << "\nExperimental extensions\n";
96 ExtMap.clear();
97 for (const auto &E : SupportedExperimentalExtensions)
98 ExtMap[E.Name] = {E.Version.Major, E.Version.Minor};
99 for (const auto &E : ExtMap) {
100 std::string Version =
101 std::to_string(E.second.Major) + "." + std::to_string(E.second.Minor);
102 PrintExtension(E.first, Version, DescMap["experimental-" + E.first]);
103 }
104
105 outs() << "\nSupported Profiles\n";
106 for (const auto &P : SupportedProfiles)
107 outs().indent(4) << P.Name << "\n";
108
109 outs() << "\nExperimental Profiles\n";
110 for (const auto &P : SupportedExperimentalProfiles)
111 outs().indent(4) << P.Name << "\n";
112
113 outs() << "\nUse -march to specify the target's extension.\n"
114 "For example, clang -march=rv32i_v1p0\n";
115}
116
118 bool IsRV64, std::set<StringRef> &EnabledFeatureNames,
119 StringMap<StringRef> &DescMap) {
120 outs() << "Extensions enabled for the given RISC-V target\n\n";
121 PrintExtension("Name", "Version", (DescMap.empty() ? "" : "Description"));
122
125 for (const auto &E : SupportedExtensions)
126 if (EnabledFeatureNames.count(E.Name) != 0) {
127 FullExtMap[E.Name] = {E.Version.Major, E.Version.Minor};
128 ExtMap[E.Name] = {E.Version.Major, E.Version.Minor};
129 }
130 for (const auto &E : ExtMap) {
131 std::string Version =
132 std::to_string(E.second.Major) + "." + std::to_string(E.second.Minor);
133 PrintExtension(E.first, Version, DescMap[E.first]);
134 }
135
136 outs() << "\nExperimental extensions\n";
137 ExtMap.clear();
138 for (const auto &E : SupportedExperimentalExtensions) {
139 StringRef Name(E.Name);
140 if (EnabledFeatureNames.count("experimental-" + Name.str()) != 0) {
141 FullExtMap[E.Name] = {E.Version.Major, E.Version.Minor};
142 ExtMap[E.Name] = {E.Version.Major, E.Version.Minor};
143 }
144 }
145 for (const auto &E : ExtMap) {
146 std::string Version =
147 std::to_string(E.second.Major) + "." + std::to_string(E.second.Minor);
148 PrintExtension(E.first, Version, DescMap["experimental-" + E.first]);
149 }
150
151 unsigned XLen = IsRV64 ? 64 : 32;
152 if (auto ISAString = RISCVISAInfo::createFromExtMap(XLen, FullExtMap))
153 outs() << "\nISA String: " << ISAString.get()->toString() << "\n";
154}
155
157 return Ext.consume_front("experimental-");
158}
159
160// This function finds the last character that doesn't belong to a version
161// (e.g. zba1p0 is extension 'zba' of version '1p0'). So the function will
162// consume [0-9]*p[0-9]* starting from the backward. An extension name will not
163// end with a digit or the letter 'p', so this function will parse correctly.
164// NOTE: This function is NOT able to take empty strings or strings that only
165// have version numbers and no extension name. It assumes the extension name
166// will be at least more than one character.
168 assert(!Ext.empty() &&
169 "Already guarded by if-statement in ::parseArchString");
170
171 int Pos = Ext.size() - 1;
172 while (Pos > 0 && isDigit(Ext[Pos]))
173 Pos--;
174 if (Pos > 0 && Ext[Pos] == 'p' && isDigit(Ext[Pos - 1])) {
175 Pos--;
176 while (Pos > 0 && isDigit(Ext[Pos]))
177 Pos--;
178 }
179 return Pos;
180}
181
182namespace {
183struct LessExtName {
184 bool operator()(const RISCVSupportedExtension &LHS, StringRef RHS) {
185 return StringRef(LHS.Name) < RHS;
186 }
187 bool operator()(StringRef LHS, const RISCVSupportedExtension &RHS) {
188 return LHS < StringRef(RHS.Name);
189 }
190};
191} // namespace
192
193static std::optional<RISCVISAUtils::ExtensionVersion>
195 // Find default version of an extension.
196 // TODO: We might set default version based on profile or ISA spec.
197 for (auto &ExtInfo : {ArrayRef(SupportedExtensions),
198 ArrayRef(SupportedExperimentalExtensions)}) {
199 auto I = llvm::lower_bound(ExtInfo, ExtName, LessExtName());
200
201 if (I == ExtInfo.end() || I->Name != ExtName)
202 continue;
203
204 return I->Version;
205 }
206 return std::nullopt;
207}
208
210 if (Ext.starts_with('s'))
211 return "standard supervisor-level extension";
212 if (Ext.starts_with('x'))
213 return "non-standard user-level extension";
214 if (Ext.starts_with('z'))
215 return "standard user-level extension";
216 return StringRef();
217}
218
220 if (Ext.starts_with('s'))
221 return "s";
222 if (Ext.starts_with('x'))
223 return "x";
224 if (Ext.starts_with('z'))
225 return "z";
226 return StringRef();
227}
228
229static std::optional<RISCVISAUtils::ExtensionVersion>
231 auto I =
232 llvm::lower_bound(SupportedExperimentalExtensions, Ext, LessExtName());
233 if (I == std::end(SupportedExperimentalExtensions) || I->Name != Ext)
234 return std::nullopt;
235
236 return I->Version;
237}
238
240 bool IsExperimental = stripExperimentalPrefix(Ext);
241
243 IsExperimental ? ArrayRef(SupportedExperimentalExtensions)
244 : ArrayRef(SupportedExtensions);
245
246 auto I = llvm::lower_bound(ExtInfo, Ext, LessExtName());
247 return I != ExtInfo.end() && I->Name == Ext;
248}
249
251 verifyTables();
252
253 for (auto ExtInfo : {ArrayRef(SupportedExtensions),
254 ArrayRef(SupportedExperimentalExtensions)}) {
255 auto I = llvm::lower_bound(ExtInfo, Ext, LessExtName());
256 if (I != ExtInfo.end() && I->Name == Ext)
257 return true;
258 }
259
260 return false;
261}
262
263bool RISCVISAInfo::isSupportedExtension(StringRef Ext, unsigned MajorVersion,
264 unsigned MinorVersion) {
265 for (auto ExtInfo : {ArrayRef(SupportedExtensions),
266 ArrayRef(SupportedExperimentalExtensions)}) {
267 auto Range =
268 std::equal_range(ExtInfo.begin(), ExtInfo.end(), Ext, LessExtName());
269 for (auto I = Range.first, E = Range.second; I != E; ++I)
270 if (I->Version.Major == MajorVersion && I->Version.Minor == MinorVersion)
271 return true;
272 }
273
274 return false;
275}
276
279
280 if (!isSupportedExtension(Ext))
281 return false;
282
283 return Exts.count(Ext.str()) != 0;
284}
285
286std::vector<std::string> RISCVISAInfo::toFeatures(bool AddAllExtensions,
287 bool IgnoreUnknown) const {
288 std::vector<std::string> Features;
289 for (const auto &[ExtName, _] : Exts) {
290 if (IgnoreUnknown && !isSupportedExtension(ExtName))
291 continue;
292
293 if (isExperimentalExtension(ExtName)) {
294 Features.push_back((llvm::Twine("+experimental-") + ExtName).str());
295 } else {
296 Features.push_back((llvm::Twine("+") + ExtName).str());
297 }
298 }
299 if (AddAllExtensions) {
300 for (const RISCVSupportedExtension &Ext : SupportedExtensions) {
301 if (Exts.count(Ext.Name))
302 continue;
303 Features.push_back((llvm::Twine("-") + Ext.Name).str());
304 }
305
306 for (const RISCVSupportedExtension &Ext : SupportedExperimentalExtensions) {
307 if (Exts.count(Ext.Name))
308 continue;
309 Features.push_back((llvm::Twine("-experimental-") + Ext.Name).str());
310 }
311 }
312 return Features;
313}
314
315static Error getError(const Twine &Message) {
317}
318
320 if (ExtName.size() == 1) {
321 return getError("unsupported standard user-level extension '" + ExtName +
322 "'");
323 }
324 return getError("unsupported " + getExtensionTypeDesc(ExtName) + " '" +
325 ExtName + "'");
326}
327
328// Extensions may have a version number, and may be separated by
329// an underscore '_' e.g.: rv32i2_m2.
330// Version number is divided into major and minor version numbers,
331// separated by a 'p'. If the minor version is 0 then 'p0' can be
332// omitted from the version string. E.g., rv32i2p0, rv32i2, rv32i2p1.
333static Error getExtensionVersion(StringRef Ext, StringRef In, unsigned &Major,
334 unsigned &Minor, unsigned &ConsumeLength,
335 bool EnableExperimentalExtension,
336 bool ExperimentalExtensionVersionCheck) {
337 StringRef MajorStr, MinorStr;
338 Major = 0;
339 Minor = 0;
340 ConsumeLength = 0;
341 MajorStr = In.take_while(isDigit);
342 In = In.substr(MajorStr.size());
343
344 if (!MajorStr.empty() && In.consume_front("p")) {
345 MinorStr = In.take_while(isDigit);
346 In = In.substr(MajorStr.size() + MinorStr.size() - 1);
347
348 // Expected 'p' to be followed by minor version number.
349 if (MinorStr.empty()) {
350 return getError("minor version number missing after 'p' for extension '" +
351 Ext + "'");
352 }
353 }
354
355 if (!MajorStr.empty() && MajorStr.getAsInteger(10, Major))
356 return getError("Failed to parse major version number for extension '" +
357 Ext + "'");
358
359 if (!MinorStr.empty() && MinorStr.getAsInteger(10, Minor))
360 return getError("Failed to parse minor version number for extension '" +
361 Ext + "'");
362
363 ConsumeLength = MajorStr.size();
364
365 if (!MinorStr.empty())
366 ConsumeLength += MinorStr.size() + 1 /*'p'*/;
367
368 // Expected multi-character extension with version number to have no
369 // subsequent characters (i.e. must either end string or be followed by
370 // an underscore).
371 if (Ext.size() > 1 && In.size())
372 return getError(
373 "multi-character extensions must be separated by underscores");
374
375 // If experimental extension, require use of current version number
376 if (auto ExperimentalExtension = isExperimentalExtension(Ext)) {
377 if (!EnableExperimentalExtension)
378 return getError("requires '-menable-experimental-extensions' "
379 "for experimental extension '" +
380 Ext + "'");
381
382 if (ExperimentalExtensionVersionCheck &&
383 (MajorStr.empty() && MinorStr.empty()))
384 return getError(
385 "experimental extension requires explicit version number `" + Ext +
386 "`");
387
388 auto SupportedVers = *ExperimentalExtension;
389 if (ExperimentalExtensionVersionCheck &&
390 (Major != SupportedVers.Major || Minor != SupportedVers.Minor)) {
391 std::string Error = "unsupported version number " + MajorStr.str();
392 if (!MinorStr.empty())
393 Error += "." + MinorStr.str();
394 Error += " for experimental extension '" + Ext.str() +
395 "' (this compiler supports " + utostr(SupportedVers.Major) +
396 "." + utostr(SupportedVers.Minor) + ")";
397 return getError(Error);
398 }
399 return Error::success();
400 }
401
402 // Exception rule for `g`, we don't have clear version scheme for that on
403 // ISA spec.
404 if (Ext == "g")
405 return Error::success();
406
407 if (MajorStr.empty() && MinorStr.empty()) {
408 if (auto DefaultVersion = findDefaultVersion(Ext)) {
409 Major = DefaultVersion->Major;
410 Minor = DefaultVersion->Minor;
411 }
412 // No matter found or not, return success, assume other place will
413 // verify.
414 return Error::success();
415 }
416
417 if (RISCVISAInfo::isSupportedExtension(Ext, Major, Minor))
418 return Error::success();
419
421 return getErrorForInvalidExt(Ext);
422
423 std::string Error = "unsupported version number " + MajorStr.str();
424 if (!MinorStr.empty())
425 Error += "." + MinorStr.str();
426 Error += " for extension '" + Ext.str() + "'";
427 return getError(Error);
428}
429
433 assert(XLen == 32 || XLen == 64);
434 std::unique_ptr<RISCVISAInfo> ISAInfo(new RISCVISAInfo(XLen));
435
436 ISAInfo->Exts = Exts;
437
438 return RISCVISAInfo::postProcessAndChecking(std::move(ISAInfo));
439}
440
443 const std::vector<std::string> &Features) {
444 assert(XLen == 32 || XLen == 64);
445 std::unique_ptr<RISCVISAInfo> ISAInfo(new RISCVISAInfo(XLen));
446
447 for (StringRef ExtName : Features) {
448 assert(ExtName.size() > 1 && (ExtName[0] == '+' || ExtName[0] == '-'));
449 bool Add = ExtName[0] == '+';
450 ExtName = ExtName.drop_front(1); // Drop '+' or '-'
451 bool Experimental = stripExperimentalPrefix(ExtName);
452 auto ExtensionInfos = Experimental
453 ? ArrayRef(SupportedExperimentalExtensions)
454 : ArrayRef(SupportedExtensions);
455 auto ExtensionInfoIterator =
456 llvm::lower_bound(ExtensionInfos, ExtName, LessExtName());
457
458 // Not all features is related to ISA extension, like `relax` or
459 // `save-restore`, skip those feature.
460 if (ExtensionInfoIterator == ExtensionInfos.end() ||
461 ExtensionInfoIterator->Name != ExtName)
462 continue;
463
464 if (Add)
465 ISAInfo->Exts[ExtName.str()] = ExtensionInfoIterator->Version;
466 else
467 ISAInfo->Exts.erase(ExtName.str());
468 }
469
470 return RISCVISAInfo::postProcessAndChecking(std::move(ISAInfo));
471}
472
475 // RISC-V ISA strings must be [a-z0-9_]
476 if (!llvm::all_of(
477 Arch, [](char C) { return isDigit(C) || isLower(C) || C == '_'; }))
478 return getError("string may only contain [a-z0-9_]");
479
480 // Must start with a valid base ISA name.
481 unsigned XLen = 0;
482 if (Arch.consume_front("rv32"))
483 XLen = 32;
484 else if (Arch.consume_front("rv64"))
485 XLen = 64;
486
487 auto IsBaseISA = [](char C) { return C == 'i' || C == 'e' || C == 'y'; };
488 if (XLen == 0 || Arch.empty() || !IsBaseISA(Arch[0]))
489 return getError("arch string must begin with valid base ISA");
490 char BaseISA = Arch[0];
491
492 std::unique_ptr<RISCVISAInfo> ISAInfo(new RISCVISAInfo(XLen));
493
494 // Each extension is of the form ${name}${major_version}p${minor_version}
495 // and separated by _. Split by _ and then extract the name and version
496 // information for each extension.
497 while (!Arch.empty()) {
498 if (Arch[0] == '_') {
499 if (Arch.size() == 1 || Arch[1] == '_')
500 return getError("extension name missing after separator '_'");
501 Arch = Arch.drop_front();
502 }
503
504 size_t Idx = Arch.find('_');
505 StringRef Ext = Arch.slice(0, Idx);
506 Arch = Arch.substr(Idx);
507
508 StringRef Prefix, MinorVersionStr;
509 std::tie(Prefix, MinorVersionStr) = Ext.rsplit('p');
510 if (MinorVersionStr.empty())
511 return getError("extension lacks version in expected format");
512 unsigned MajorVersion, MinorVersion;
513 if (MinorVersionStr.getAsInteger(10, MinorVersion))
514 return getError("failed to parse minor version number");
515
516 // Split Prefix into the extension name and the major version number
517 // (the trailing digits of Prefix).
518 size_t VersionStart = Prefix.size();
519 while (VersionStart != 0) {
520 if (!isDigit(Prefix[VersionStart - 1]))
521 break;
522 --VersionStart;
523 }
524 if (VersionStart == Prefix.size())
525 return getError("extension lacks version in expected format");
526
527 if (VersionStart == 0)
528 return getError("missing extension name");
529
530 StringRef ExtName = Prefix.slice(0, VersionStart);
531 StringRef MajorVersionStr = Prefix.substr(VersionStart);
532 if (MajorVersionStr.getAsInteger(10, MajorVersion))
533 return getError("failed to parse major version number");
534
535 if (IsBaseISA(ExtName[0])) {
536 if (ExtName.size() > 1)
537 return getError("base ISA '" + Twine(ExtName[0]) +
538 "' is missing version number");
539 if (ExtName[0] != BaseISA)
540 return getError("conflicting base ISAs '" + Twine(BaseISA) + "' and '" +
541 ExtName + "'");
542 } else if (RISCVISAUtils::AllStdExts.contains(ExtName[0]) &&
543 ExtName.size() > 1) {
544 return getError("extension '" + Twine(ExtName[0]) +
545 "' is missing version number");
546 }
547
548 if ((ExtName[0] == 'z' || ExtName[0] == 's' || ExtName[0] == 'x') &&
549 (ExtName.size() == 1 || isDigit(ExtName[1])))
550 return getError("'" + Twine(ExtName[0]) +
551 "' must be followed by a letter");
552
553 if (!ISAInfo->Exts
554 .emplace(
555 ExtName.str(),
556 RISCVISAUtils::ExtensionVersion{MajorVersion, MinorVersion})
557 .second)
558 return getError("duplicate extension '" + ExtName + "'");
559 }
560 // Plain 'y' always implies 'i' (which is omitted in the normalized arch
561 // string). Y+E requires a long base name arch string.
562 if (BaseISA == 'y')
563 ISAInfo->Exts["i"] = *findDefaultVersion("i");
564 ISAInfo->updateImpliedLengths();
565 return std::move(ISAInfo);
566}
567
569RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension,
570 bool ExperimentalExtensionVersionCheck) {
571 // RISC-V ISA strings must be [a-z0-9_]
572 if (!llvm::all_of(
573 Arch, [](char C) { return isDigit(C) || isLower(C) || C == '_'; }))
574 return getError("string may only contain [a-z0-9_]");
575
576 // ISA string must begin with rv32, rv64, or a profile.
577 unsigned XLen = 0;
578 if (Arch.consume_front("rv32")) {
579 XLen = 32;
580 } else if (Arch.consume_front("rv64")) {
581 XLen = 64;
582 } else {
583 // Try parsing as a profile.
584 auto ProfileCmp = [](StringRef Arch, const RISCVProfile &Profile) {
585 return Arch < Profile.Name;
586 };
587 auto I = llvm::upper_bound(SupportedProfiles, Arch, ProfileCmp);
588 bool FoundProfile = I != std::begin(SupportedProfiles) &&
589 Arch.starts_with(std::prev(I)->Name);
590 if (!FoundProfile) {
591 I = llvm::upper_bound(SupportedExperimentalProfiles, Arch, ProfileCmp);
592 FoundProfile = (I != std::begin(SupportedExperimentalProfiles) &&
593 Arch.starts_with(std::prev(I)->Name));
594 if (FoundProfile && !EnableExperimentalExtension) {
595 return getError("requires '-menable-experimental-extensions' "
596 "for profile '" +
597 std::prev(I)->Name + "'");
598 }
599 }
600 if (FoundProfile) {
601 --I;
602 std::string NewArch = I->MArch.str();
603 StringRef ArchWithoutProfile = Arch.drop_front(I->Name.size());
604 if (!ArchWithoutProfile.empty()) {
605 if (ArchWithoutProfile.front() != '_')
606 return getError("additional extensions must be after separator '_'");
607 NewArch += ArchWithoutProfile.str();
608 }
609 return parseArchString(NewArch, EnableExperimentalExtension,
610 ExperimentalExtensionVersionCheck);
611 }
612 }
613
614 if (XLen == 0 || Arch.empty())
615 return getError(
616 "string must begin with rv32{i,e,g,y}, rv64{i,e,g,y}, or a supported "
617 "profile name");
618
619 std::unique_ptr<RISCVISAInfo> ISAInfo(new RISCVISAInfo(XLen));
620
621 // The canonical order specified in ISA manual.
622 // Ref: Table 22.1 in RISC-V User-Level ISA V2.2
623 char Baseline = Arch.front();
624 // Skip the baseline.
625 Arch = Arch.drop_front();
626
627 unsigned Major, Minor, ConsumeLength;
628
629 // First letter should be 'e', 'i', 'g' or 'y'.
630 switch (Baseline) {
631 default:
632 return getError("first letter after \'rv" + Twine(XLen) +
633 "\' should be 'e', 'i', 'g' or 'y'");
634 case 'e':
635 case 'i':
636 case 'y':
637 // Baseline is 'i', 'e', or 'y' (which implies 'i' in updateImplication).
638 // TODO: arch string syntax for RVE+RVY (and y in non-first position) will
639 // be included following conclusion of "long base name" syntax
640 // https://lists.riscv.org/g/tech-unprivileged/message/1134
641 if (auto E = getExtensionVersion(
642 StringRef(&Baseline, 1), Arch, Major, Minor, ConsumeLength,
643 EnableExperimentalExtension, ExperimentalExtensionVersionCheck))
644 return std::move(E);
645
646 ISAInfo->Exts[std::string(1, Baseline)] = {Major, Minor};
647 break;
648 case 'g':
649 // g expands to extensions in RISCVGImplications.
650 if (!Arch.empty() && isDigit(Arch.front()))
651 return getError("version not supported for 'g'");
652
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 char *Ext : RISCVGImplications) {
660 auto Version = findDefaultVersion(Ext);
661 assert(Version && "Default extension version not found?");
662 ISAInfo->Exts[std::string(Ext)] = {Version->Major, Version->Minor};
663 }
664 break;
665 }
666
667 // Consume the base ISA version number and any '_' between rvxxx and the
668 // first extension
669 Arch = Arch.drop_front(ConsumeLength);
670
671 while (!Arch.empty()) {
672 if (Arch.front() == '_') {
673 if (Arch.size() == 1 || Arch[1] == '_')
674 return getError("extension name missing after separator '_'");
675 Arch = Arch.drop_front();
676 }
677
678 size_t Idx = Arch.find('_');
679 StringRef Ext = Arch.slice(0, Idx);
680 Arch = Arch.substr(Idx);
681
682 do {
683 StringRef Name, Vers, Desc;
685 Name = Ext.take_front(1);
686 Ext = Ext.drop_front();
687 Vers = Ext;
688 Desc = "standard user-level extension";
689 } else if (Ext.front() == 'z' || Ext.front() == 's' ||
690 Ext.front() == 'x') {
691 // Handle other types of extensions other than the standard
692 // general purpose and standard user-level extensions.
693 // Parse the ISA string containing non-standard user-level
694 // extensions, standard supervisor-level extensions and
695 // non-standard supervisor-level extensions.
696 // These extensions start with 'z', 's', 'x' prefixes, might have a
697 // version number (major, minor) and are separated by a single
698 // underscore '_'. We do not enforce a canonical order for them.
701 auto Pos = findLastNonVersionCharacter(Ext) + 1;
702 Name = Ext.substr(0, Pos);
703 Vers = Ext.substr(Pos);
704 Ext = StringRef();
705
706 assert(!Type.empty() && "Empty type?");
707 if (Name.size() == Type.size())
708 return getError(Desc + " name missing after '" + Type + "'");
709 } else {
710 return getError("invalid standard user-level extension '" +
711 Twine(Ext.front()) + "'");
712 }
713
714 unsigned Major, Minor, ConsumeLength;
715 if (auto E = getExtensionVersion(Name, Vers, Major, Minor, ConsumeLength,
716 EnableExperimentalExtension,
717 ExperimentalExtensionVersionCheck))
718 return E;
719
720 if (Name.size() == 1)
721 Ext = Ext.substr(ConsumeLength);
722
724 return getErrorForInvalidExt(Name);
725
726 // Insert and error for duplicates.
727 if (!ISAInfo->Exts
728 .emplace(Name.str(),
730 .second)
731 return getError("duplicated " + Desc + " '" + Name + "'");
732
733 } while (!Ext.empty());
734 }
735
736 // We add Zicsr/Zifenci as final to allow duplicated "zicsr"/"zifencei" like
737 // "rv64g_zicsr_zifencei".
738 if (Baseline == 'g') {
739 for (const char *Ext : RISCVGImplicationsZi) {
740 if (ISAInfo->Exts.count(Ext))
741 continue;
742
743 auto Version = findDefaultVersion(Ext);
744 assert(Version && "Default extension version not found?");
745 ISAInfo->Exts[std::string(Ext)] = {Version->Major, Version->Minor};
746 }
747 }
748
749 return RISCVISAInfo::postProcessAndChecking(std::move(ISAInfo));
750}
751
753 return getError("'" + Ext1 + "' and '" + Ext2 +
754 "' extensions are incompatible");
755}
756
758 return getError("'" + Ext + "' is incompatible with " + Base + " base");
759}
760
762 return getError("'" + Ext + "' requires '" + ReqExt +
763 "' extension to also be specified");
764}
765
766Error RISCVISAInfo::checkDependency() {
767 bool HasE = Exts.count("e") != 0;
768 bool HasI = Exts.count("i") != 0;
769 bool HasF = Exts.count("f") != 0;
770 bool HasD = Exts.count("d") != 0;
771 bool HasZfinx = Exts.count("zfinx") != 0;
772 bool HasVector = Exts.count("zve32x") != 0;
773 bool HasZvl = MinVLen != 0;
774 bool HasZcmp = Exts.count("zcmp") != 0;
775 bool HasXqccmp = Exts.count("xqccmp") != 0;
776 bool HasZcmt = Exts.count("zcmt") != 0;
777 bool HasXqccmt = Exts.count("xqccmt") != 0;
778
779 static constexpr StringLiteral ZcdOverlaps[] = {
780 {"zcmt"}, {"zcmp"}, {"xqccmi"}, {"xqccmp"},
781 {"xqccmt"}, {"xqciac"}, {"xqcicm"},
782 };
783 static constexpr StringLiteral RV32Only[] = {
784 {"zcf"}, {"zclsd"}, {"zilsd"}, {"xwchc"}, {"xqccmi"},
785 {"xqci"}, {"xqcia"}, {"xqciac"}, {"xqcibi"}, {"xqcibm"},
786 {"xqcicli"}, {"xqcicm"}, {"xqcics"}, {"xqcicsr"}, {"xqciint"},
787 {"xqciio"}, {"xqcilb"}, {"xqcili"}, {"xqcilia"}, {"xqcilo"},
788 {"xqcilsm"}, {"xqcisim"}, {"xqcisls"}, {"xqcisync"},
789 };
790
791 if (HasI && HasE)
792 return getIncompatibleError("i", "e");
793
794 if (HasF && HasZfinx)
795 return getIncompatibleError("f", "zfinx");
796
797 if (HasZvl && !HasVector)
798 return getExtensionRequiresError("zvl*b", "v' or 'zve*");
799
800 if (Exts.count("xsfvfbfexp16e") &&
801 !(Exts.count("zvfbfmin") || Exts.count("zvfbfa")))
803 "'xsfvfbfexp16e' requires 'zvfbfmin' or "
804 "'zvfbfa' extension to also be specified");
805
806 if (Exts.count("zcd"))
807 for (auto Ext : ZcdOverlaps)
808 if (Exts.count(Ext.str()))
809 return getIncompatibleError(Ext, "zcd");
810
811 if (XLen != 32)
812 for (auto Ext : RV32Only)
813 if (Exts.count(Ext.str()))
814 return getError(Twine("'") + Ext + "' is only supported for 'rv32'");
815
816 if (Exts.count("xwchc") != 0) {
817 if (HasD)
818 return getIncompatibleError("d", "xwchc");
819
820 if (Exts.count("zcb") != 0)
821 return getIncompatibleError("xwchc", "zcb");
822 }
823
824 if (Exts.count("zclsd") != 0 && Exts.count("zcf") != 0)
825 return getIncompatibleError("zclsd", "zcf");
826
827 if (Exts.count("y") != 0) {
828 if (XLen == 32) {
829 // On RV32Y systems the zclsd/zcf encodings are used for y load/stores.
830 if (Exts.count("zclsd") != 0)
831 return getBaseIncompatibleError("zclsd", "rv32y");
832 if (Exts.count("zcf") != 0)
833 return getBaseIncompatibleError("zcf", "rv32y");
834 } else {
835 // On RV64Y systems the zcd encodings are used for y load/stores.
836 if (Exts.count("zcd") != 0)
837 return getBaseIncompatibleError("zcd", "rv64y");
838 for (auto Ext : ZcdOverlaps)
839 if (Exts.count(Ext.str()))
840 return getBaseIncompatibleError(Ext, "rv64y");
841 }
842 }
843
844 if (HasZcmp && HasXqccmp)
845 return getIncompatibleError("zcmp", "xqccmp");
846
847 if (HasZcmt && HasXqccmt)
848 return getIncompatibleError("zcmt", "xqccmt");
849
850 return Error::success();
851}
852
855 const char *ImpliedExt;
856
857 bool operator<(const ImpliedExtsEntry &Other) const {
858 return Name < Other.Name;
859 }
860};
861
863 return LHS.Name < RHS;
864}
865
867 return LHS < RHS.Name;
868}
869
870#define GET_IMPLIED_EXTENSIONS
871#include "llvm/TargetParser/RISCVTargetParserDef.inc"
872
873void RISCVISAInfo::updateImplication() {
874 assert(llvm::is_sorted(ImpliedExts) && "Table not sorted by Name");
875
876 // This loop may execute over 1 iteration since implication can be layered
877 // Exits loop if no more implication is applied
879 for (auto const &Ext : Exts)
880 WorkList.push_back(Ext.first);
881
882 while (!WorkList.empty()) {
883 StringRef ExtName = WorkList.pop_back_val();
884 auto Range = std::equal_range(std::begin(ImpliedExts),
885 std::end(ImpliedExts), ExtName);
886 for (const ImpliedExtsEntry &Implied : llvm::make_range(Range)) {
887 const char *ImpliedExt = Implied.ImpliedExt;
888 auto [It, Inserted] = Exts.try_emplace(ImpliedExt);
889 if (!Inserted)
890 continue;
891 auto Version = findDefaultVersion(ImpliedExt);
892 It->second = *Version;
893 WorkList.push_back(ImpliedExt);
894 }
895 }
896
897 // Add Zcd if C and D are enabled and we aren't targeting 64-bit RVY.
898 if (Exts.count("c") && Exts.count("d") && !Exts.count("zcd") &&
899 (XLen == 32 || !Exts.count("y"))) {
900 auto Version = findDefaultVersion("zcd");
901 Exts["zcd"] = *Version;
902 }
903
904 // Add Zcf if C and F are enabled on RV32 and Y is not enabled.
905 if (XLen == 32 && Exts.count("c") && Exts.count("f") && !Exts.count("zcf") &&
906 !Exts.count("y")) {
907 auto Version = findDefaultVersion("zcf");
908 Exts["zcf"] = *Version;
909 }
910
911 // Add Zcf if Zce and F are enabled on RV32 and Y is not enabled.
912 if (XLen == 32 && Exts.count("zce") && Exts.count("f") &&
913 !Exts.count("zcf") && !Exts.count("y")) {
914 auto Version = findDefaultVersion("zcf");
915 Exts["zcf"] = *Version;
916 }
917
918 // Add C if Zca is enabled and the conditions are met.
919 // This follows the RISC-V spec rules for MISA.C and matches GCC behavior
920 // (PR119122). The rule is:
921 // For RV32:
922 // - No F and no D: Zca alone implies C
923 // - F but no D: Zca + Zcf implies C
924 // - F and D: Zca + Zcf + Zcd implies C
925 // For RV64:
926 // - No D: Zca alone implies C
927 // - D: Zca + Zcd implies C
928 // For RV32Y (Zcf incompatible):
929 // - No D (but maybe F): Zca alone implies C
930 // - F and D: Zca + Zcd implies C
931 // For RV64Y (Zcf and Zcd incompatible):
932 // - Zca alone implies C
933 if (Exts.count("zca") && !Exts.count("c")) {
934 bool ShouldAddC = false;
935 if (XLen == 32) {
936 if (Exts.count("d"))
937 ShouldAddC =
938 Exts.count("zcd") && (Exts.count("y") || Exts.count("zcf"));
939 else if (Exts.count("f"))
940 ShouldAddC = Exts.count("y") || Exts.count("zcf");
941 else
942 ShouldAddC = true;
943 } else if (XLen == 64) {
944 if (Exts.count("d"))
945 ShouldAddC = Exts.count("y") || Exts.count("zcd");
946 else
947 ShouldAddC = true;
948 }
949 if (ShouldAddC) {
950 auto Version = findDefaultVersion("c");
951 Exts["c"] = *Version;
952 }
953 }
954
955 if (!Exts.count("zce") && Exts.count("zca") && Exts.count("zcb") &&
956 Exts.count("zcmp") && Exts.count("zcmt")) {
957 bool ShouldAddZce = false;
958 if (XLen == 32) {
959 ShouldAddZce = !Exts.count("f") || Exts.count("zcf") || Exts.count("y");
960 } else if (XLen == 64) {
961 // Zce is incompatible with RV64Y, only add it if Y is not enabled.
962 ShouldAddZce = !Exts.count("y");
963 }
964 if (ShouldAddZce)
965 Exts["zce"] = *findDefaultVersion("zce");
966 }
967
968 // Handle I/E after implications have been resolved, in case either
969 // of them was implied by another extension.
970 bool HasE = Exts.count("e") != 0;
971 bool HasI = Exts.count("i") != 0;
972
973 // If not in e extension and i extension does not exist, i extension is
974 // implied
975 if (!HasE && !HasI) {
976 auto Version = findDefaultVersion("i");
977 Exts["i"] = *Version;
978 }
979
980 if (HasE && HasI)
981 Exts.erase("i");
982}
983
984static constexpr StringLiteral CombineIntoExts[] = {
985 {"a"}, {"b"}, {"zk"}, {"zkn"}, {"zks"},
986 {"zvkn"}, {"zvknc"}, {"zvkng"}, {"zvks"}, {"zvksc"},
987 {"zvksg"}, {"xqci"}, {"xsfmm32a"},
988};
989
990void RISCVISAInfo::updateCombination() {
991 bool MadeChange = false;
992 do {
993 MadeChange = false;
994 for (StringRef CombineExt : CombineIntoExts) {
995 if (Exts.count(CombineExt.str()))
996 continue;
997
998 // Look up the extension in the ImpliesExt table to find everything it
999 // depends on.
1000 auto Range = std::equal_range(std::begin(ImpliedExts),
1001 std::end(ImpliedExts), CombineExt);
1002 bool HasAllRequiredFeatures = std::all_of(
1003 Range.first, Range.second, [&](const ImpliedExtsEntry &Implied) {
1004 return Exts.count(Implied.ImpliedExt);
1005 });
1006 if (HasAllRequiredFeatures) {
1007 auto Version = findDefaultVersion(CombineExt);
1008 Exts[CombineExt.str()] = *Version;
1009 MadeChange = true;
1010 }
1011 }
1012 } while (MadeChange);
1013}
1014
1015void RISCVISAInfo::updateImpliedLengths() {
1016 assert(FLen == 0 && MaxELenFp == 0 && MaxELen == 0 && MinVLen == 0 &&
1017 "Expected lengths to be initialied to zero");
1018
1019 if (Exts.count("q"))
1020 FLen = 128;
1021 else if (Exts.count("d"))
1022 FLen = 64;
1023 else if (Exts.count("f"))
1024 FLen = 32;
1025
1026 if (Exts.count("v")) {
1027 MaxELenFp = std::max(MaxELenFp, 64u);
1028 MaxELen = std::max(MaxELen, 64u);
1029 }
1030
1031 for (auto const &Ext : Exts) {
1032 StringRef ExtName = Ext.first;
1033 // Infer MaxELen and MaxELenFp from Zve(32/64)(x/f/d)
1034 if (ExtName.consume_front("zve")) {
1035 unsigned ZveELen;
1036 if (ExtName.consumeInteger(10, ZveELen))
1037 continue;
1038
1039 if (ExtName == "f")
1040 MaxELenFp = std::max(MaxELenFp, 32u);
1041 else if (ExtName == "d")
1042 MaxELenFp = std::max(MaxELenFp, 64u);
1043 else if (ExtName != "x")
1044 continue;
1045
1046 MaxELen = std::max(MaxELen, ZveELen);
1047 continue;
1048 }
1049
1050 // Infer MinVLen from zvl*b.
1051 if (ExtName.consume_front("zvl")) {
1052 unsigned ZvlLen;
1053 if (ExtName.consumeInteger(10, ZvlLen))
1054 continue;
1055
1056 if (ExtName != "b")
1057 continue;
1058
1059 MinVLen = std::max(MinVLen, ZvlLen);
1060 continue;
1061 }
1062 }
1063}
1064
1065std::string RISCVISAInfo::toString() const {
1066 std::string Buffer;
1067 raw_string_ostream Arch(Buffer);
1068
1069 Arch << "rv" << XLen;
1070
1071 bool HasY = Exts.count("y") != 0;
1072 ListSeparator LS("_");
1073 for (auto const &Ext : Exts) {
1074 StringRef ExtName = Ext.first;
1075 if (HasY) {
1076 // Plain 'y' always implies 'i' (which is omitted in the normalized arch
1077 // string). Y+E requires a long base name arch string.
1078 if (ExtName == "i")
1079 continue;
1080 if (ExtName == "e")
1081 reportFatalUsageError("Y+E is not supported yet");
1082 }
1083 auto ExtInfo = Ext.second;
1084 Arch << LS << ExtName;
1085 Arch << ExtInfo.Major << "p" << ExtInfo.Minor;
1086 }
1087
1088 return Arch.str();
1089}
1090
1092RISCVISAInfo::postProcessAndChecking(std::unique_ptr<RISCVISAInfo> &&ISAInfo) {
1093 ISAInfo->updateImplication();
1094 ISAInfo->updateCombination();
1095 ISAInfo->updateImpliedLengths();
1096
1097 if (Error Result = ISAInfo->checkDependency())
1098 return std::move(Result);
1099 return std::move(ISAInfo);
1100}
1101
1103 bool HasY = Exts.count("y") != 0;
1104 if (XLen == 32) {
1105 if (Exts.count("xcheriot"))
1106 return "cheriot";
1107 if (Exts.count("e"))
1108 return HasY ? "il32pc64e" : "ilp32e";
1109 if (Exts.count("d"))
1110 return HasY ? "il32pc64d" : "ilp32d";
1111 if (Exts.count("f"))
1112 return HasY ? "il32pc64f" : "ilp32f";
1113 return HasY ? "il32pc64" : "ilp32";
1114 } else if (XLen == 64) {
1115 // RV64E has no capability ABI (yet).
1116 if (Exts.count("e"))
1117 return "lp64e";
1118 if (Exts.count("d"))
1119 return HasY ? "l64pc128d" : "lp64d";
1120 if (Exts.count("f"))
1121 return HasY ? "l64pc128f" : "lp64f";
1122 return HasY ? "l64pc128" : "lp64";
1123 }
1124 llvm_unreachable("Invalid XLEN");
1125}
1126
1128 if (Ext.empty())
1129 return false;
1130
1131 auto Pos = findLastNonVersionCharacter(Ext) + 1;
1132 StringRef Name = Ext.substr(0, Pos);
1133 StringRef Vers = Ext.substr(Pos);
1134 if (Vers.empty())
1135 return false;
1136
1137 unsigned Major, Minor, ConsumeLength;
1138 if (auto E = getExtensionVersion(Name, Vers, Major, Minor, ConsumeLength,
1139 true, true)) {
1140 consumeError(std::move(E));
1141 return false;
1142 }
1143
1144 return true;
1145}
1146
1148 if (Ext.empty())
1149 return std::string();
1150
1151 auto Pos = findLastNonVersionCharacter(Ext) + 1;
1152 StringRef Name = Ext.substr(0, Pos);
1153
1154 if (Pos != Ext.size() && !isSupportedExtensionWithVersion(Ext))
1155 return std::string();
1156
1157 if (!isSupportedExtension(Name))
1158 return std::string();
1159
1160 return isExperimentalExtension(Name) ? "experimental-" + Name.str()
1161 : Name.str();
1162}
1163
1165 const char *Name;
1166 unsigned GroupID;
1167 unsigned BitPosition;
1168};
1169
1170#define GET_RISCVExtensionBitmaskTable_IMPL
1171#include "llvm/TargetParser/RISCVTargetParserDef.inc"
1172
1174 // Note that this code currently accepts mixed case extension names, but
1175 // does not handle extension versions at all. That's probably fine because
1176 // there's only one extension version in the __riscv_feature_bits vector.
1177 for (auto E : ExtensionBitmask)
1178 if (Ext.equals_insensitive(E.Name))
1179 return std::make_pair(E.GroupID, E.BitPosition);
1180 return std::make_pair(-1, -1);
1181}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
#define _
#define I(x, y, z)
Definition MD5.cpp:57
Load MIR Sample Profile
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
#define P(N)
static void verifyTables()
static StringRef getExtensionTypeDesc(StringRef Ext)
static const char * RISCVGImplicationsZi[]
static std::optional< RISCVISAUtils::ExtensionVersion > findDefaultVersion(StringRef ExtName)
static size_t findLastNonVersionCharacter(StringRef Ext)
static Error getExtensionRequiresError(StringRef Ext, StringRef ReqExt)
static StringRef getExtensionType(StringRef Ext)
static Error getErrorForInvalidExt(StringRef ExtName)
static constexpr StringLiteral CombineIntoExts[]
static bool stripExperimentalPrefix(StringRef &Ext)
static std::optional< RISCVISAUtils::ExtensionVersion > isExperimentalExtension(StringRef Ext)
static void PrintExtension(StringRef Name, StringRef Version, StringRef Description)
static Error getBaseIncompatibleError(StringRef Ext, StringRef Base)
static Error getExtensionVersion(StringRef Ext, StringRef In, unsigned &Major, unsigned &Minor, unsigned &ConsumeLength, bool EnableExperimentalExtension, bool ExperimentalExtensionVersionCheck)
static Error getIncompatibleError(StringRef Ext1, StringRef Ext2)
static Error getError(const Twine &Message)
static const char * RISCVGImplications[]
This file contains some templates that are useful if you are working with the STL at all.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:480
This file contains some functions that are useful when dealing with strings.
static void verifyTables()
Value * RHS
Value * LHS
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
iterator end() const
Definition ArrayRef.h:130
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
static ErrorSuccess success()
Create a success value.
Definition Error.h:336
Tagged union holding either a T or a Error.
Definition Error.h:485
A helper class to return the specified delimiter string after the first invocation of operator String...
static LLVM_ABI bool isSupportedExtensionFeature(StringRef Ext)
static LLVM_ABI std::string getTargetFeatureForExtension(StringRef Ext)
static LLVM_ABI 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...
LLVM_ABI bool hasExtension(StringRef Ext) const
RISCVISAInfo(const RISCVISAInfo &)=delete
LLVM_ABI std::string toString() const
LLVM_ABI StringRef computeDefaultABI() const
static LLVM_ABI llvm::Expected< std::unique_ptr< RISCVISAInfo > > parseArchString(StringRef Arch, bool EnableExperimentalExtension, bool ExperimentalExtensionVersionCheck=true)
Parse RISC-V ISA info from arch string.
static LLVM_ABI bool isSupportedExtension(StringRef Ext)
static LLVM_ABI void printEnabledExtensions(bool IsRV64, std::set< StringRef > &EnabledFeatureNames, StringMap< StringRef > &DescMap)
static LLVM_ABI void printSupportedExtensions(StringMap< StringRef > &DescMap)
static LLVM_ABI llvm::Expected< std::unique_ptr< RISCVISAInfo > > parseFeatures(unsigned XLen, const std::vector< std::string > &Features)
Parse RISC-V ISA info from feature vector.
static LLVM_ABI std::pair< int, int > getRISCVFeaturesBitsInfo(StringRef Ext)
Return the group id and bit position of __riscv_feature_bits.
static LLVM_ABI llvm::Expected< std::unique_ptr< RISCVISAInfo > > createFromExtMap(unsigned XLen, const RISCVISAUtils::OrderedExtensionMap &Exts)
LLVM_ABI std::vector< std::string > toFeatures(bool AddAllExtensions=false, bool IgnoreUnknown=true) const
Convert RISC-V ISA info to a feature vector.
static LLVM_ABI bool isSupportedExtensionWithVersion(StringRef Ext)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
A wrapper around a string literal that serves as a proxy for constructing global tables of StringRefs...
Definition StringRef.h:888
bool empty() const
Definition StringMap.h:103
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
Definition StringMap.h:129
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
bool consumeInteger(unsigned Radix, T &Result)
Parse the current string as an integer of the specified radix.
Definition StringRef.h:519
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
Definition StringRef.h:490
std::string str() const
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:597
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition StringRef.h:258
constexpr bool empty() const
Check if the string is empty.
Definition StringRef.h:141
StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
Definition StringRef.h:635
StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
Definition StringRef.h:720
constexpr size_t size() const
Get the string size.
Definition StringRef.h:144
char front() const
Get the first character in the string.
Definition StringRef.h:147
StringRef take_front(size_t N=1) const
Return a StringRef equal to 'this' but with only the first N elements remaining.
Definition StringRef.h:606
size_t find(char C, size_t From=0) const
Search for the first character C in the string.
Definition StringRef.h:290
size_t count(char C) const
Return the number of occurrences of C in the string.
Definition StringRef.h:471
std::pair< StringRef, StringRef > rsplit(StringRef Separator) const
Split into two substrings around the last occurrence of a separator string.
Definition StringRef.h:769
bool consume_front(char Prefix)
Returns true if this StringRef has the given prefix and removes that prefix.
Definition StringRef.h:661
bool equals_insensitive(StringRef RHS) const
Check for string equality, ignoring case.
Definition StringRef.h:170
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
A raw_ostream that writes to an std::string.
std::string & str()
Returns the string's reference.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr StringLiteral AllStdExts
std::map< std::string, ExtensionVersion, ExtensionComparator > OrderedExtensionMap
OrderedExtensionMap is std::map, it's specialized to keep entries in canonical order of extension.
static constexpr uint64_t DefaultVersion
Definition SampleProf.h:127
This is an optimization pass for GlobalISel generic memory operations.
bool operator<(int64_t V1, const APSInt &V2)
Definition APSInt.h:360
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1755
bool isLower(char C)
Checks if character C is a lowercase letter as classified by "C" locale.
LLVM_ABI raw_fd_ostream & outs()
This returns a reference to a raw_fd_ostream for standard output.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
std::string utostr(uint64_t X, bool isNeg=false)
auto upper_bound(R &&Range, T &&Value)
Provide wrappers to std::upper_bound which take ranges instead of having to pass begin/end explicitly...
Definition STLExtras.h:2081
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition Error.h:1321
Op::Description Desc
@ invalid_argument
Definition Errc.h:56
bool isDigit(char C)
Checks if character C is one of the 10 decimal digits.
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:1986
@ Other
Any other memory.
Definition ModRef.h:68
FormattedString left_justify(StringRef Str, unsigned Width)
left_justify - append spaces after string so total output is Width characters.
Definition Format.h:123
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:2068
@ Add
Sum of integers.
ArrayRef(const T &OneElt) -> ArrayRef< T >
void consumeError(Error Err)
Consume a Error without doing anything.
Definition Error.h:1106
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
Definition Error.cpp:177
StringLiteral Name
bool operator<(const ImpliedExtsEntry &Other) const
const char * ImpliedExt
Represents the major and version number components of a RISC-V extension.