1 //===-- RISCVISAInfo.cpp - RISC-V Arch String Parser ----------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/TargetParser/RISCVISAInfo.h"
10 #include "llvm/ADT/STLExtras.h"
11 #include "llvm/ADT/StringExtras.h"
12 #include "llvm/ADT/StringRef.h"
13 #include "llvm/Support/Errc.h"
14 #include "llvm/Support/Error.h"
15 #include "llvm/Support/raw_ostream.h"
27 struct RISCVSupportedExtension
{
29 /// Supported version.
30 RISCVISAUtils::ExtensionVersion Version
;
32 bool operator<(const RISCVSupportedExtension
&RHS
) const {
33 return StringRef(Name
) < StringRef(RHS
.Name
);
41 bool operator<(const RISCVProfile
&RHS
) const {
42 return StringRef(Name
) < StringRef(RHS
.Name
);
46 } // end anonymous namespace
48 static const char *RISCVGImplications
[] = {
49 "i", "m", "a", "f", "d", "zicsr", "zifencei"
52 #define GET_SUPPORTED_EXTENSIONS
53 #include "llvm/TargetParser/RISCVTargetParserDef.inc"
55 #define GET_SUPPORTED_PROFILES
56 #include "llvm/TargetParser/RISCVTargetParserDef.inc"
58 static void verifyTables() {
60 static std::atomic
<bool> TableChecked(false);
61 if (!TableChecked
.load(std::memory_order_relaxed
)) {
62 assert(llvm::is_sorted(SupportedExtensions
) &&
63 "Extensions are not sorted by name");
64 assert(llvm::is_sorted(SupportedExperimentalExtensions
) &&
65 "Experimental extensions are not sorted by name");
66 assert(llvm::is_sorted(SupportedProfiles
) &&
67 "Profiles are not sorted by name");
68 assert(llvm::is_sorted(SupportedExperimentalProfiles
) &&
69 "Experimental profiles are not sorted by name");
70 TableChecked
.store(true, std::memory_order_relaxed
);
75 static void PrintExtension(StringRef Name
, StringRef Version
,
76 StringRef Description
) {
78 unsigned VersionWidth
= Description
.empty() ? 0 : 10;
79 outs() << left_justify(Name
, 21) << left_justify(Version
, VersionWidth
)
80 << Description
<< "\n";
83 void RISCVISAInfo::printSupportedExtensions(StringMap
<StringRef
> &DescMap
) {
84 outs() << "All available -march extensions for RISC-V\n\n";
85 PrintExtension("Name", "Version", (DescMap
.empty() ? "" : "Description"));
87 RISCVISAUtils::OrderedExtensionMap ExtMap
;
88 for (const auto &E
: SupportedExtensions
)
89 ExtMap
[E
.Name
] = {E
.Version
.Major
, E
.Version
.Minor
};
90 for (const auto &E
: ExtMap
) {
92 std::to_string(E
.second
.Major
) + "." + std::to_string(E
.second
.Minor
);
93 PrintExtension(E
.first
, Version
, DescMap
[E
.first
]);
96 outs() << "\nExperimental extensions\n";
98 for (const auto &E
: SupportedExperimentalExtensions
)
99 ExtMap
[E
.Name
] = {E
.Version
.Major
, E
.Version
.Minor
};
100 for (const auto &E
: ExtMap
) {
101 std::string Version
=
102 std::to_string(E
.second
.Major
) + "." + std::to_string(E
.second
.Minor
);
103 PrintExtension(E
.first
, Version
, DescMap
["experimental-" + E
.first
]);
106 outs() << "\nSupported Profiles\n";
107 for (const auto &P
: SupportedProfiles
)
108 outs().indent(4) << P
.Name
<< "\n";
110 outs() << "\nExperimental Profiles\n";
111 for (const auto &P
: SupportedExperimentalProfiles
)
112 outs().indent(4) << P
.Name
<< "\n";
114 outs() << "\nUse -march to specify the target's extension.\n"
115 "For example, clang -march=rv32i_v1p0\n";
118 void RISCVISAInfo::printEnabledExtensions(
119 bool IsRV64
, std::set
<StringRef
> &EnabledFeatureNames
,
120 StringMap
<StringRef
> &DescMap
) {
121 outs() << "Extensions enabled for the given RISC-V target\n\n";
122 PrintExtension("Name", "Version", (DescMap
.empty() ? "" : "Description"));
124 RISCVISAUtils::OrderedExtensionMap FullExtMap
;
125 RISCVISAUtils::OrderedExtensionMap ExtMap
;
126 for (const auto &E
: SupportedExtensions
)
127 if (EnabledFeatureNames
.count(E
.Name
) != 0) {
128 FullExtMap
[E
.Name
] = {E
.Version
.Major
, E
.Version
.Minor
};
129 ExtMap
[E
.Name
] = {E
.Version
.Major
, E
.Version
.Minor
};
131 for (const auto &E
: ExtMap
) {
132 std::string Version
=
133 std::to_string(E
.second
.Major
) + "." + std::to_string(E
.second
.Minor
);
134 PrintExtension(E
.first
, Version
, DescMap
[E
.first
]);
137 outs() << "\nExperimental extensions\n";
139 for (const auto &E
: SupportedExperimentalExtensions
) {
140 StringRef
Name(E
.Name
);
141 if (EnabledFeatureNames
.count("experimental-" + Name
.str()) != 0) {
142 FullExtMap
[E
.Name
] = {E
.Version
.Major
, E
.Version
.Minor
};
143 ExtMap
[E
.Name
] = {E
.Version
.Major
, E
.Version
.Minor
};
146 for (const auto &E
: ExtMap
) {
147 std::string Version
=
148 std::to_string(E
.second
.Major
) + "." + std::to_string(E
.second
.Minor
);
149 PrintExtension(E
.first
, Version
, DescMap
["experimental-" + E
.first
]);
152 unsigned XLen
= IsRV64
? 64 : 32;
153 if (auto ISAString
= RISCVISAInfo::createFromExtMap(XLen
, FullExtMap
))
154 outs() << "\nISA String: " << ISAString
.get()->toString() << "\n";
157 static bool stripExperimentalPrefix(StringRef
&Ext
) {
158 return Ext
.consume_front("experimental-");
161 // This function finds the last character that doesn't belong to a version
162 // (e.g. zba1p0 is extension 'zba' of version '1p0'). So the function will
163 // consume [0-9]*p[0-9]* starting from the backward. An extension name will not
164 // end with a digit or the letter 'p', so this function will parse correctly.
165 // NOTE: This function is NOT able to take empty strings or strings that only
166 // have version numbers and no extension name. It assumes the extension name
167 // will be at least more than one character.
168 static size_t findLastNonVersionCharacter(StringRef Ext
) {
169 assert(!Ext
.empty() &&
170 "Already guarded by if-statement in ::parseArchString");
172 int Pos
= Ext
.size() - 1;
173 while (Pos
> 0 && isDigit(Ext
[Pos
]))
175 if (Pos
> 0 && Ext
[Pos
] == 'p' && isDigit(Ext
[Pos
- 1])) {
177 while (Pos
> 0 && isDigit(Ext
[Pos
]))
185 bool operator()(const RISCVSupportedExtension
&LHS
, StringRef RHS
) {
186 return StringRef(LHS
.Name
) < RHS
;
188 bool operator()(StringRef LHS
, const RISCVSupportedExtension
&RHS
) {
189 return LHS
< StringRef(RHS
.Name
);
194 static std::optional
<RISCVISAUtils::ExtensionVersion
>
195 findDefaultVersion(StringRef ExtName
) {
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
),
199 ArrayRef(SupportedExperimentalExtensions
)}) {
200 auto I
= llvm::lower_bound(ExtInfo
, ExtName
, LessExtName());
202 if (I
== ExtInfo
.end() || I
->Name
!= ExtName
)
210 static StringRef
getExtensionTypeDesc(StringRef Ext
) {
211 if (Ext
.starts_with('s'))
212 return "standard supervisor-level extension";
213 if (Ext
.starts_with('x'))
214 return "non-standard user-level extension";
215 if (Ext
.starts_with('z'))
216 return "standard user-level extension";
220 static StringRef
getExtensionType(StringRef Ext
) {
221 if (Ext
.starts_with('s'))
223 if (Ext
.starts_with('x'))
225 if (Ext
.starts_with('z'))
230 static std::optional
<RISCVISAUtils::ExtensionVersion
>
231 isExperimentalExtension(StringRef Ext
) {
233 llvm::lower_bound(SupportedExperimentalExtensions
, Ext
, LessExtName());
234 if (I
== std::end(SupportedExperimentalExtensions
) || I
->Name
!= Ext
)
240 bool RISCVISAInfo::isSupportedExtensionFeature(StringRef Ext
) {
241 bool IsExperimental
= stripExperimentalPrefix(Ext
);
243 ArrayRef
<RISCVSupportedExtension
> ExtInfo
=
244 IsExperimental
? ArrayRef(SupportedExperimentalExtensions
)
245 : ArrayRef(SupportedExtensions
);
247 auto I
= llvm::lower_bound(ExtInfo
, Ext
, LessExtName());
248 return I
!= ExtInfo
.end() && I
->Name
== Ext
;
251 bool RISCVISAInfo::isSupportedExtension(StringRef Ext
) {
254 for (auto ExtInfo
: {ArrayRef(SupportedExtensions
),
255 ArrayRef(SupportedExperimentalExtensions
)}) {
256 auto I
= llvm::lower_bound(ExtInfo
, Ext
, LessExtName());
257 if (I
!= ExtInfo
.end() && I
->Name
== Ext
)
264 bool RISCVISAInfo::isSupportedExtension(StringRef Ext
, unsigned MajorVersion
,
265 unsigned MinorVersion
) {
266 for (auto ExtInfo
: {ArrayRef(SupportedExtensions
),
267 ArrayRef(SupportedExperimentalExtensions
)}) {
269 std::equal_range(ExtInfo
.begin(), ExtInfo
.end(), Ext
, LessExtName());
270 for (auto I
= Range
.first
, E
= Range
.second
; I
!= E
; ++I
)
271 if (I
->Version
.Major
== MajorVersion
&& I
->Version
.Minor
== MinorVersion
)
278 bool RISCVISAInfo::hasExtension(StringRef Ext
) const {
279 stripExperimentalPrefix(Ext
);
281 if (!isSupportedExtension(Ext
))
284 return Exts
.count(Ext
.str()) != 0;
287 std::vector
<std::string
> RISCVISAInfo::toFeatures(bool AddAllExtensions
,
288 bool IgnoreUnknown
) const {
289 std::vector
<std::string
> Features
;
290 for (const auto &[ExtName
, _
] : Exts
) {
291 // i is a base instruction set, not an extension (see
292 // https://github.com/riscv/riscv-isa-manual/blob/main/src/naming.adoc#base-integer-isa)
293 // and is not recognized in clang -cc1
296 if (IgnoreUnknown
&& !isSupportedExtension(ExtName
))
299 if (isExperimentalExtension(ExtName
)) {
300 Features
.push_back((llvm::Twine("+experimental-") + ExtName
).str());
302 Features
.push_back((llvm::Twine("+") + ExtName
).str());
305 if (AddAllExtensions
) {
306 for (const RISCVSupportedExtension
&Ext
: SupportedExtensions
) {
307 if (Exts
.count(Ext
.Name
))
309 Features
.push_back((llvm::Twine("-") + Ext
.Name
).str());
312 for (const RISCVSupportedExtension
&Ext
: SupportedExperimentalExtensions
) {
313 if (Exts
.count(Ext
.Name
))
315 Features
.push_back((llvm::Twine("-experimental-") + Ext
.Name
).str());
321 static Error
getError(const Twine
&Message
) {
322 return createStringError(errc::invalid_argument
, Message
);
325 static Error
getErrorForInvalidExt(StringRef ExtName
) {
326 if (ExtName
.size() == 1) {
327 return getError("unsupported standard user-level extension '" + ExtName
+
330 return getError("unsupported " + getExtensionTypeDesc(ExtName
) + " '" +
334 // Extensions may have a version number, and may be separated by
335 // an underscore '_' e.g.: rv32i2_m2.
336 // Version number is divided into major and minor version numbers,
337 // separated by a 'p'. If the minor version is 0 then 'p0' can be
338 // omitted from the version string. E.g., rv32i2p0, rv32i2, rv32i2p1.
339 static Error
getExtensionVersion(StringRef Ext
, StringRef In
, unsigned &Major
,
340 unsigned &Minor
, unsigned &ConsumeLength
,
341 bool EnableExperimentalExtension
,
342 bool ExperimentalExtensionVersionCheck
) {
343 StringRef MajorStr
, MinorStr
;
347 MajorStr
= In
.take_while(isDigit
);
348 In
= In
.substr(MajorStr
.size());
350 if (!MajorStr
.empty() && In
.consume_front("p")) {
351 MinorStr
= In
.take_while(isDigit
);
352 In
= In
.substr(MajorStr
.size() + MinorStr
.size() - 1);
354 // Expected 'p' to be followed by minor version number.
355 if (MinorStr
.empty()) {
356 return getError("minor version number missing after 'p' for extension '" +
361 if (!MajorStr
.empty() && MajorStr
.getAsInteger(10, Major
))
362 return getError("Failed to parse major version number for extension '" +
365 if (!MinorStr
.empty() && MinorStr
.getAsInteger(10, Minor
))
366 return getError("Failed to parse minor version number for extension '" +
369 ConsumeLength
= MajorStr
.size();
371 if (!MinorStr
.empty())
372 ConsumeLength
+= MinorStr
.size() + 1 /*'p'*/;
374 // Expected multi-character extension with version number to have no
375 // subsequent characters (i.e. must either end string or be followed by
377 if (Ext
.size() > 1 && In
.size())
379 "multi-character extensions must be separated by underscores");
381 // If experimental extension, require use of current version number
382 if (auto ExperimentalExtension
= isExperimentalExtension(Ext
)) {
383 if (!EnableExperimentalExtension
)
384 return getError("requires '-menable-experimental-extensions' "
385 "for experimental extension '" +
388 if (ExperimentalExtensionVersionCheck
&&
389 (MajorStr
.empty() && MinorStr
.empty()))
391 "experimental extension requires explicit version number `" + Ext
+
394 auto SupportedVers
= *ExperimentalExtension
;
395 if (ExperimentalExtensionVersionCheck
&&
396 (Major
!= SupportedVers
.Major
|| Minor
!= SupportedVers
.Minor
)) {
397 std::string Error
= "unsupported version number " + MajorStr
.str();
398 if (!MinorStr
.empty())
399 Error
+= "." + MinorStr
.str();
400 Error
+= " for experimental extension '" + Ext
.str() +
401 "' (this compiler supports " + utostr(SupportedVers
.Major
) +
402 "." + utostr(SupportedVers
.Minor
) + ")";
403 return getError(Error
);
405 return Error::success();
408 // Exception rule for `g`, we don't have clear version scheme for that on
411 return Error::success();
413 if (MajorStr
.empty() && MinorStr
.empty()) {
414 if (auto DefaultVersion
= findDefaultVersion(Ext
)) {
415 Major
= DefaultVersion
->Major
;
416 Minor
= DefaultVersion
->Minor
;
418 // No matter found or not, return success, assume other place will
420 return Error::success();
423 if (RISCVISAInfo::isSupportedExtension(Ext
, Major
, Minor
))
424 return Error::success();
426 if (!RISCVISAInfo::isSupportedExtension(Ext
))
427 return getErrorForInvalidExt(Ext
);
429 std::string Error
= "unsupported version number " + MajorStr
.str();
430 if (!MinorStr
.empty())
431 Error
+= "." + MinorStr
.str();
432 Error
+= " for extension '" + Ext
.str() + "'";
433 return getError(Error
);
436 llvm::Expected
<std::unique_ptr
<RISCVISAInfo
>>
437 RISCVISAInfo::createFromExtMap(unsigned XLen
,
438 const RISCVISAUtils::OrderedExtensionMap
&Exts
) {
439 assert(XLen
== 32 || XLen
== 64);
440 std::unique_ptr
<RISCVISAInfo
> ISAInfo(new RISCVISAInfo(XLen
));
442 ISAInfo
->Exts
= Exts
;
444 return RISCVISAInfo::postProcessAndChecking(std::move(ISAInfo
));
447 llvm::Expected
<std::unique_ptr
<RISCVISAInfo
>>
448 RISCVISAInfo::parseFeatures(unsigned XLen
,
449 const std::vector
<std::string
> &Features
) {
450 assert(XLen
== 32 || XLen
== 64);
451 std::unique_ptr
<RISCVISAInfo
> ISAInfo(new RISCVISAInfo(XLen
));
453 for (auto &Feature
: Features
) {
454 StringRef ExtName
= Feature
;
455 assert(ExtName
.size() > 1 && (ExtName
[0] == '+' || ExtName
[0] == '-'));
456 bool Add
= ExtName
[0] == '+';
457 ExtName
= ExtName
.drop_front(1); // Drop '+' or '-'
458 bool Experimental
= stripExperimentalPrefix(ExtName
);
459 auto ExtensionInfos
= Experimental
460 ? ArrayRef(SupportedExperimentalExtensions
)
461 : ArrayRef(SupportedExtensions
);
462 auto ExtensionInfoIterator
=
463 llvm::lower_bound(ExtensionInfos
, ExtName
, LessExtName());
465 // Not all features is related to ISA extension, like `relax` or
466 // `save-restore`, skip those feature.
467 if (ExtensionInfoIterator
== ExtensionInfos
.end() ||
468 ExtensionInfoIterator
->Name
!= ExtName
)
472 ISAInfo
->Exts
[ExtName
.str()] = ExtensionInfoIterator
->Version
;
474 ISAInfo
->Exts
.erase(ExtName
.str());
477 return RISCVISAInfo::postProcessAndChecking(std::move(ISAInfo
));
480 llvm::Expected
<std::unique_ptr
<RISCVISAInfo
>>
481 RISCVISAInfo::parseNormalizedArchString(StringRef Arch
) {
482 // RISC-V ISA strings must be [a-z0-9_]
484 Arch
, [](char C
) { return isDigit(C
) || isLower(C
) || C
== '_'; }))
485 return getError("string may only contain [a-z0-9_]");
487 // Must start with a valid base ISA name.
489 if (Arch
.consume_front("rv32"))
491 else if (Arch
.consume_front("rv64"))
494 if (XLen
== 0 || Arch
.empty() || (Arch
[0] != 'i' && Arch
[0] != 'e'))
495 return getError("arch string must begin with valid base ISA");
497 std::unique_ptr
<RISCVISAInfo
> ISAInfo(new RISCVISAInfo(XLen
));
499 // Each extension is of the form ${name}${major_version}p${minor_version}
500 // and separated by _. Split by _ and then extract the name and version
501 // information for each extension.
502 while (!Arch
.empty()) {
503 if (Arch
[0] == '_') {
504 if (Arch
.size() == 1 || Arch
[1] == '_')
505 return getError("extension name missing after separator '_'");
506 Arch
= Arch
.drop_front();
509 size_t Idx
= Arch
.find('_');
510 StringRef Ext
= Arch
.slice(0, Idx
);
511 Arch
= Arch
.substr(Idx
);
513 StringRef Prefix
, MinorVersionStr
;
514 std::tie(Prefix
, MinorVersionStr
) = Ext
.rsplit('p');
515 if (MinorVersionStr
.empty())
516 return getError("extension lacks version in expected format");
517 unsigned MajorVersion
, MinorVersion
;
518 if (MinorVersionStr
.getAsInteger(10, MinorVersion
))
519 return getError("failed to parse minor version number");
521 // Split Prefix into the extension name and the major version number
522 // (the trailing digits of Prefix).
523 size_t VersionStart
= Prefix
.size();
524 while (VersionStart
!= 0) {
525 if (!isDigit(Prefix
[VersionStart
- 1]))
529 if (VersionStart
== Prefix
.size())
530 return getError("extension lacks version in expected format");
532 if (VersionStart
== 0)
533 return getError("missing extension name");
535 StringRef ExtName
= Prefix
.slice(0, VersionStart
);
536 StringRef MajorVersionStr
= Prefix
.substr(VersionStart
);
537 if (MajorVersionStr
.getAsInteger(10, MajorVersion
))
538 return getError("failed to parse major version number");
540 if ((ExtName
[0] == 'z' || ExtName
[0] == 's' || ExtName
[0] == 'x') &&
541 (ExtName
.size() == 1 || isDigit(ExtName
[1])))
542 return getError("'" + Twine(ExtName
[0]) +
543 "' must be followed by a letter");
548 RISCVISAUtils::ExtensionVersion
{MajorVersion
, MinorVersion
})
550 return getError("duplicate extension '" + ExtName
+ "'");
552 ISAInfo
->updateImpliedLengths();
553 return std::move(ISAInfo
);
556 llvm::Expected
<std::unique_ptr
<RISCVISAInfo
>>
557 RISCVISAInfo::parseArchString(StringRef Arch
, bool EnableExperimentalExtension
,
558 bool ExperimentalExtensionVersionCheck
) {
559 // RISC-V ISA strings must be [a-z0-9_]
561 Arch
, [](char C
) { return isDigit(C
) || isLower(C
) || C
== '_'; }))
562 return getError("string may only contain [a-z0-9_]");
564 // ISA string must begin with rv32, rv64, or a profile.
566 if (Arch
.consume_front("rv32")) {
568 } else if (Arch
.consume_front("rv64")) {
571 // Try parsing as a profile.
572 auto ProfileCmp
= [](StringRef Arch
, const RISCVProfile
&Profile
) {
573 return Arch
< Profile
.Name
;
575 auto I
= llvm::upper_bound(SupportedProfiles
, Arch
, ProfileCmp
);
576 bool FoundProfile
= I
!= std::begin(SupportedProfiles
) &&
577 Arch
.starts_with(std::prev(I
)->Name
);
579 I
= llvm::upper_bound(SupportedExperimentalProfiles
, Arch
, ProfileCmp
);
580 FoundProfile
= (I
!= std::begin(SupportedExperimentalProfiles
) &&
581 Arch
.starts_with(std::prev(I
)->Name
));
582 if (FoundProfile
&& !EnableExperimentalExtension
) {
583 return getError("requires '-menable-experimental-extensions' "
585 std::prev(I
)->Name
+ "'");
590 std::string NewArch
= I
->MArch
.str();
591 StringRef ArchWithoutProfile
= Arch
.drop_front(I
->Name
.size());
592 if (!ArchWithoutProfile
.empty()) {
593 if (ArchWithoutProfile
.front() != '_')
594 return getError("additional extensions must be after separator '_'");
595 NewArch
+= ArchWithoutProfile
.str();
597 return parseArchString(NewArch
, EnableExperimentalExtension
,
598 ExperimentalExtensionVersionCheck
);
602 if (XLen
== 0 || Arch
.empty())
604 "string must begin with rv32{i,e,g}, rv64{i,e,g}, or a supported "
607 std::unique_ptr
<RISCVISAInfo
> ISAInfo(new RISCVISAInfo(XLen
));
609 // The canonical order specified in ISA manual.
610 // Ref: Table 22.1 in RISC-V User-Level ISA V2.2
611 char Baseline
= Arch
.front();
612 // Skip the baseline.
613 Arch
= Arch
.drop_front();
615 unsigned Major
, Minor
, ConsumeLength
;
617 // First letter should be 'e', 'i' or 'g'.
620 return getError("first letter after \'rv" + Twine(XLen
) +
621 "\' should be 'e', 'i' or 'g'");
624 // Baseline is `i` or `e`
625 if (auto E
= getExtensionVersion(
626 StringRef(&Baseline
, 1), Arch
, Major
, Minor
, ConsumeLength
,
627 EnableExperimentalExtension
, ExperimentalExtensionVersionCheck
))
630 ISAInfo
->Exts
[std::string(1, Baseline
)] = {Major
, Minor
};
633 // g expands to extensions in RISCVGImplications.
634 if (!Arch
.empty() && isDigit(Arch
.front()))
635 return getError("version not supported for 'g'");
637 // Versions for g are disallowed, and this was checked for previously.
640 // No matter which version is given to `g`, we always set imafd to default
641 // version since the we don't have clear version scheme for that on
643 for (const char *Ext
: RISCVGImplications
) {
644 auto Version
= findDefaultVersion(Ext
);
645 assert(Version
&& "Default extension version not found?");
646 // Postpone AddExtension until end of this function
647 ISAInfo
->Exts
[std::string(Ext
)] = {Version
->Major
, Version
->Minor
};
652 // Consume the base ISA version number and any '_' between rvxxx and the
654 Arch
= Arch
.drop_front(ConsumeLength
);
656 while (!Arch
.empty()) {
657 if (Arch
.front() == '_') {
658 if (Arch
.size() == 1 || Arch
[1] == '_')
659 return getError("extension name missing after separator '_'");
660 Arch
= Arch
.drop_front();
663 size_t Idx
= Arch
.find('_');
664 StringRef Ext
= Arch
.slice(0, Idx
);
665 Arch
= Arch
.substr(Idx
);
668 StringRef Name
, Vers
, Desc
;
669 if (RISCVISAUtils::AllStdExts
.contains(Ext
.front())) {
670 Name
= Ext
.take_front(1);
671 Ext
= Ext
.drop_front();
673 Desc
= "standard user-level extension";
674 } else if (Ext
.front() == 'z' || Ext
.front() == 's' ||
675 Ext
.front() == 'x') {
676 // Handle other types of extensions other than the standard
677 // general purpose and standard user-level extensions.
678 // Parse the ISA string containing non-standard user-level
679 // extensions, standard supervisor-level extensions and
680 // non-standard supervisor-level extensions.
681 // These extensions start with 'z', 's', 'x' prefixes, might have a
682 // version number (major, minor) and are separated by a single
683 // underscore '_'. We do not enforce a canonical order for them.
684 StringRef Type
= getExtensionType(Ext
);
685 Desc
= getExtensionTypeDesc(Ext
);
686 auto Pos
= findLastNonVersionCharacter(Ext
) + 1;
687 Name
= Ext
.substr(0, Pos
);
688 Vers
= Ext
.substr(Pos
);
691 assert(!Type
.empty() && "Empty type?");
692 if (Name
.size() == Type
.size())
693 return getError(Desc
+ " name missing after '" + Type
+ "'");
695 return getError("invalid standard user-level extension '" +
696 Twine(Ext
.front()) + "'");
699 unsigned Major
, Minor
, ConsumeLength
;
700 if (auto E
= getExtensionVersion(Name
, Vers
, Major
, Minor
, ConsumeLength
,
701 EnableExperimentalExtension
,
702 ExperimentalExtensionVersionCheck
))
705 if (Name
.size() == 1)
706 Ext
= Ext
.substr(ConsumeLength
);
708 if (!RISCVISAInfo::isSupportedExtension(Name
))
709 return getErrorForInvalidExt(Name
);
711 // Insert and error for duplicates.
714 RISCVISAUtils::ExtensionVersion
{Major
, Minor
})
716 return getError("duplicated " + Desc
+ " '" + Name
+ "'");
718 } while (!Ext
.empty());
721 return RISCVISAInfo::postProcessAndChecking(std::move(ISAInfo
));
724 static Error
getIncompatibleError(StringRef Ext1
, StringRef Ext2
) {
725 return getError("'" + Ext1
+ "' and '" + Ext2
+
726 "' extensions are incompatible");
729 static Error
getExtensionRequiresError(StringRef Ext
, StringRef ReqExt
) {
730 return getError("'" + Ext
+ "' requires '" + ReqExt
+
731 "' extension to also be specified");
734 Error
RISCVISAInfo::checkDependency() {
735 bool HasE
= Exts
.count("e") != 0;
736 bool HasI
= Exts
.count("i") != 0;
737 bool HasC
= Exts
.count("c") != 0;
738 bool HasF
= Exts
.count("f") != 0;
739 bool HasD
= Exts
.count("d") != 0;
740 bool HasZfinx
= Exts
.count("zfinx") != 0;
741 bool HasVector
= Exts
.count("zve32x") != 0;
742 bool HasZvl
= MinVLen
!= 0;
743 bool HasZcmt
= Exts
.count("zcmt") != 0;
744 static constexpr StringLiteral XqciExts
[] = {
745 {"xqcia"}, {"xqciac"}, {"xqcicli"}, {"xqcicm"}, {"xqcics"},
746 {"xqcicsr"}, {"xqciint"}, {"xqcilsm"}, {"xqcisls"}};
749 return getIncompatibleError("i", "e");
751 if (HasF
&& HasZfinx
)
752 return getIncompatibleError("f", "zfinx");
754 if (HasZvl
&& !HasVector
)
755 return getExtensionRequiresError("zvl*b", "v' or 'zve*");
757 if ((HasZcmt
|| Exts
.count("zcmp")) && HasD
&& (HasC
|| Exts
.count("zcd")))
758 return getError(Twine("'") + (HasZcmt
? "zcmt" : "zcmp") +
759 "' extension is incompatible with '" +
760 (HasC
? "c" : "zcd") +
761 "' extension when 'd' extension is enabled");
763 if (XLen
!= 32 && Exts
.count("zcf"))
764 return getError("'zcf' is only supported for 'rv32'");
766 if (Exts
.count("xwchc") != 0) {
768 return getError("'xwchc' is only supported for 'rv32'");
771 return getIncompatibleError("d", "xwchc");
773 if (Exts
.count("zcb") != 0)
774 return getIncompatibleError("xwchc", "zcb");
777 for (auto Ext
: XqciExts
)
778 if (Exts
.count(Ext
.str()) && (XLen
!= 32))
779 return getError("'" + Twine(Ext
) + "'" + " is only supported for 'rv32'");
781 return Error::success();
784 struct ImpliedExtsEntry
{
786 const char *ImpliedExt
;
788 bool operator<(const ImpliedExtsEntry
&Other
) const {
789 return Name
< Other
.Name
;
793 static bool operator<(const ImpliedExtsEntry
&LHS
, StringRef RHS
) {
794 return LHS
.Name
< RHS
;
797 static bool operator<(StringRef LHS
, const ImpliedExtsEntry
&RHS
) {
798 return LHS
< RHS
.Name
;
801 #define GET_IMPLIED_EXTENSIONS
802 #include "llvm/TargetParser/RISCVTargetParserDef.inc"
804 void RISCVISAInfo::updateImplication() {
805 bool HasE
= Exts
.count("e") != 0;
806 bool HasI
= Exts
.count("i") != 0;
808 // If not in e extension and i extension does not exist, i extension is
810 if (!HasE
&& !HasI
) {
811 auto Version
= findDefaultVersion("i");
812 Exts
["i"] = *Version
;
818 assert(llvm::is_sorted(ImpliedExts
) && "Table not sorted by Name");
820 // This loop may execute over 1 iteration since implication can be layered
821 // Exits loop if no more implication is applied
822 SmallVector
<StringRef
, 16> WorkList
;
823 for (auto const &Ext
: Exts
)
824 WorkList
.push_back(Ext
.first
);
826 while (!WorkList
.empty()) {
827 StringRef ExtName
= WorkList
.pop_back_val();
828 auto Range
= std::equal_range(std::begin(ImpliedExts
),
829 std::end(ImpliedExts
), ExtName
);
830 std::for_each(Range
.first
, Range
.second
,
831 [&](const ImpliedExtsEntry
&Implied
) {
832 const char *ImpliedExt
= Implied
.ImpliedExt
;
833 if (Exts
.count(ImpliedExt
))
835 auto Version
= findDefaultVersion(ImpliedExt
);
836 Exts
[ImpliedExt
] = *Version
;
837 WorkList
.push_back(ImpliedExt
);
841 // Add Zcf if Zce and F are enabled on RV32.
842 if (XLen
== 32 && Exts
.count("zce") && Exts
.count("f") &&
843 !Exts
.count("zcf")) {
844 auto Version
= findDefaultVersion("zcf");
845 Exts
["zcf"] = *Version
;
849 static constexpr StringLiteral CombineIntoExts
[] = {
850 {"zk"}, {"zkn"}, {"zks"}, {"zvkn"}, {"zvknc"},
851 {"zvkng"}, {"zvks"}, {"zvksc"}, {"zvksg"},
854 void RISCVISAInfo::updateCombination() {
855 bool MadeChange
= false;
858 for (StringRef CombineExt
: CombineIntoExts
) {
859 if (Exts
.count(CombineExt
.str()))
862 // Look up the extension in the ImpliesExt table to find everything it
864 auto Range
= std::equal_range(std::begin(ImpliedExts
),
865 std::end(ImpliedExts
), CombineExt
);
866 bool HasAllRequiredFeatures
= std::all_of(
867 Range
.first
, Range
.second
, [&](const ImpliedExtsEntry
&Implied
) {
868 return Exts
.count(Implied
.ImpliedExt
);
870 if (HasAllRequiredFeatures
) {
871 auto Version
= findDefaultVersion(CombineExt
);
872 Exts
[CombineExt
.str()] = *Version
;
876 } while (MadeChange
);
879 void RISCVISAInfo::updateImpliedLengths() {
880 assert(FLen
== 0 && MaxELenFp
== 0 && MaxELen
== 0 && MinVLen
== 0 &&
881 "Expected lengths to be initialied to zero");
883 // TODO: Handle q extension.
886 else if (Exts
.count("f"))
889 if (Exts
.count("v")) {
890 MaxELenFp
= std::max(MaxELenFp
, 64u);
891 MaxELen
= std::max(MaxELen
, 64u);
894 for (auto const &Ext
: Exts
) {
895 StringRef ExtName
= Ext
.first
;
896 // Infer MaxELen and MaxELenFp from Zve(32/64)(x/f/d)
897 if (ExtName
.consume_front("zve")) {
899 if (ExtName
.consumeInteger(10, ZveELen
))
903 MaxELenFp
= std::max(MaxELenFp
, 32u);
904 else if (ExtName
== "d")
905 MaxELenFp
= std::max(MaxELenFp
, 64u);
906 else if (ExtName
!= "x")
909 MaxELen
= std::max(MaxELen
, ZveELen
);
913 // Infer MinVLen from zvl*b.
914 if (ExtName
.consume_front("zvl")) {
916 if (ExtName
.consumeInteger(10, ZvlLen
))
922 MinVLen
= std::max(MinVLen
, ZvlLen
);
928 std::string
RISCVISAInfo::toString() const {
930 raw_string_ostream
Arch(Buffer
);
932 Arch
<< "rv" << XLen
;
934 ListSeparator
LS("_");
935 for (auto const &Ext
: Exts
) {
936 StringRef ExtName
= Ext
.first
;
937 auto ExtInfo
= Ext
.second
;
938 Arch
<< LS
<< ExtName
;
939 Arch
<< ExtInfo
.Major
<< "p" << ExtInfo
.Minor
;
945 llvm::Expected
<std::unique_ptr
<RISCVISAInfo
>>
946 RISCVISAInfo::postProcessAndChecking(std::unique_ptr
<RISCVISAInfo
> &&ISAInfo
) {
947 ISAInfo
->updateImplication();
948 ISAInfo
->updateCombination();
949 ISAInfo
->updateImpliedLengths();
951 if (Error Result
= ISAInfo
->checkDependency())
952 return std::move(Result
);
953 return std::move(ISAInfo
);
956 StringRef
RISCVISAInfo::computeDefaultABI() const {
965 } else if (XLen
== 64) {
974 llvm_unreachable("Invalid XLEN");
977 bool RISCVISAInfo::isSupportedExtensionWithVersion(StringRef Ext
) {
981 auto Pos
= findLastNonVersionCharacter(Ext
) + 1;
982 StringRef Name
= Ext
.substr(0, Pos
);
983 StringRef Vers
= Ext
.substr(Pos
);
987 unsigned Major
, Minor
, ConsumeLength
;
988 if (auto E
= getExtensionVersion(Name
, Vers
, Major
, Minor
, ConsumeLength
,
990 consumeError(std::move(E
));
997 std::string
RISCVISAInfo::getTargetFeatureForExtension(StringRef Ext
) {
999 return std::string();
1001 auto Pos
= findLastNonVersionCharacter(Ext
) + 1;
1002 StringRef Name
= Ext
.substr(0, Pos
);
1004 if (Pos
!= Ext
.size() && !isSupportedExtensionWithVersion(Ext
))
1005 return std::string();
1007 if (!isSupportedExtension(Name
))
1008 return std::string();
1010 return isExperimentalExtension(Name
) ? "experimental-" + Name
.str()
1014 struct RISCVExtBit
{
1015 const StringLiteral ext
;
1020 constexpr static RISCVExtBit RISCVBitPositions
[] = {
1021 {"a", 0, 0}, {"c", 0, 2},
1022 {"d", 0, 3}, {"f", 0, 5},
1023 {"i", 0, 8}, {"m", 0, 12},
1024 {"v", 0, 21}, {"zacas", 0, 26},
1025 {"zba", 0, 27}, {"zbb", 0, 28},
1026 {"zbc", 0, 29}, {"zbkb", 0, 30},
1027 {"zbkc", 0, 31}, {"zbkx", 0, 32},
1028 {"zbs", 0, 33}, {"zfa", 0, 34},
1029 {"zfh", 0, 35}, {"zfhmin", 0, 36},
1030 {"zicboz", 0, 37}, {"zicond", 0, 38},
1031 {"zihintntl", 0, 39}, {"zihintpause", 0, 40},
1032 {"zknd", 0, 41}, {"zkne", 0, 42},
1033 {"zknh", 0, 43}, {"zksed", 0, 44},
1034 {"zksh", 0, 45}, {"zkt", 0, 46},
1035 {"ztso", 0, 47}, {"zvbb", 0, 48},
1036 {"zvbc", 0, 49}, {"zvfh", 0, 50},
1037 {"zvfhmin", 0, 51}, {"zvkb", 0, 52},
1038 {"zvkg", 0, 53}, {"zvkned", 0, 54},
1039 {"zvknha", 0, 55}, {"zvknhb", 0, 56},
1040 {"zvksed", 0, 57}, {"zvksh", 0, 58},
1041 {"zvkt", 0, 59}, {"zve32x", 0, 60},
1042 {"zve32f", 0, 61}, {"zve64x", 0, 62},
1043 {"zve64f", 0, 63}, {"zve64d", 1, 0},
1044 {"zimop", 1, 1}, {"zca", 1, 2},
1045 {"zcb", 1, 3}, {"zcd", 1, 4},
1046 {"zcf", 1, 5}, {"zcmop", 1, 6},
1049 std::pair
<int, int> RISCVISAInfo::getRISCVFeaturesBitsInfo(StringRef Ext
) {
1050 // Note that this code currently accepts mixed case extension names, but
1051 // does not handle extension versions at all. That's probably fine because
1052 // there's only one extension version in the __riscv_feature_bits vector.
1053 for (auto E
: RISCVBitPositions
)
1054 if (E
.ext
.equals_insensitive(Ext
))
1055 return std::make_pair(E
.groupid
, E
.bitpos
);
1056 return std::make_pair(-1, -1);