aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Support/RISCVISAInfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Support/RISCVISAInfo.cpp')
-rw-r--r--llvm/lib/Support/RISCVISAInfo.cpp136
1 files changed, 94 insertions, 42 deletions
diff --git a/llvm/lib/Support/RISCVISAInfo.cpp b/llvm/lib/Support/RISCVISAInfo.cpp
index 0fe286d239d4..1b1bff023d2f 100644
--- a/llvm/lib/Support/RISCVISAInfo.cpp
+++ b/llvm/lib/Support/RISCVISAInfo.cpp
@@ -1,4 +1,4 @@
-//===-- RISCVISAInfo.cpp - RISCV Arch String Parser --------------===//
+//===-- RISCVISAInfo.cpp - RISCV Arch String Parser -------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -7,7 +7,6 @@
//===----------------------------------------------------------------------===//
#include "llvm/Support/RISCVISAInfo.h"
-#include "llvm/ADT/None.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/StringExtras.h"
@@ -17,6 +16,7 @@
#include "llvm/Support/raw_ostream.h"
#include <array>
+#include <optional>
#include <string>
#include <vector>
@@ -37,7 +37,7 @@ struct RISCVSupportedExtension {
} // end anonymous namespace
-static constexpr StringLiteral AllStdExts = "mafdqlcbkjtpvn";
+static constexpr StringLiteral AllStdExts = "mafdqlcbkjtpvnh";
static const RISCVSupportedExtension SupportedExtensions[] = {
{"i", RISCVExtensionVersion{2, 0}},
@@ -48,6 +48,8 @@ static const RISCVSupportedExtension SupportedExtensions[] = {
{"d", RISCVExtensionVersion{2, 0}},
{"c", RISCVExtensionVersion{2, 0}},
+ {"h", RISCVExtensionVersion{1, 0}},
+
{"zihintpause", RISCVExtensionVersion{2, 0}},
{"zfhmin", RISCVExtensionVersion{1, 0}},
@@ -101,16 +103,23 @@ static const RISCVSupportedExtension SupportedExtensions[] = {
{"zicbom", RISCVExtensionVersion{1, 0}},
{"zicboz", RISCVExtensionVersion{1, 0}},
{"zicbop", RISCVExtensionVersion{1, 0}},
+
+ {"svnapot", RISCVExtensionVersion{1, 0}},
+ {"svpbmt", RISCVExtensionVersion{1, 0}},
+ {"svinval", RISCVExtensionVersion{1, 0}},
+ {"xventanacondops", RISCVExtensionVersion{1, 0}},
+ {"xtheadvdot", RISCVExtensionVersion{1, 0}},
};
static const RISCVSupportedExtension SupportedExperimentalExtensions[] = {
- {"zbe", RISCVExtensionVersion{0, 93}},
- {"zbf", RISCVExtensionVersion{0, 93}},
- {"zbm", RISCVExtensionVersion{0, 93}},
- {"zbp", RISCVExtensionVersion{0, 93}},
- {"zbr", RISCVExtensionVersion{0, 93}},
- {"zbt", RISCVExtensionVersion{0, 93}},
+ {"zihintntl", RISCVExtensionVersion{0, 2}},
+
+ {"zca", RISCVExtensionVersion{0, 70}},
+ {"zcd", RISCVExtensionVersion{0, 70}},
+ {"zcf", RISCVExtensionVersion{0, 70}},
{"zvfh", RISCVExtensionVersion{0, 1}},
+ {"zawrs", RISCVExtensionVersion{1, 0}},
+ {"ztso", RISCVExtensionVersion{0, 1}},
};
static bool stripExperimentalPrefix(StringRef &Ext) {
@@ -118,15 +127,15 @@ static bool stripExperimentalPrefix(StringRef &Ext) {
}
// This function finds the first character that doesn't belong to a version
-// (e.g. zbe0p93 is extension 'zbe' of version '0p93'). So the function will
+// (e.g. zba1p0 is extension 'zba' of version '1p0'). So the function will
// consume [0-9]*p[0-9]* starting from the backward. An extension name will not
// end with a digit or the letter 'p', so this function will parse correctly.
// NOTE: This function is NOT able to take empty strings or strings that only
// have version numbers and no extension name. It assumes the extension name
// will be at least more than one character.
static size_t findFirstNonVersionCharacter(StringRef Ext) {
- assert(!Ext.empty() &&
- "Already guarded by if-statement in ::parseArchString");
+ assert(!Ext.empty() &&
+ "Already guarded by if-statement in ::parseArchString");
int Pos = Ext.size() - 1;
while (Pos > 0 && isDigit(Ext[Pos]))
@@ -139,6 +148,7 @@ static size_t findFirstNonVersionCharacter(StringRef Ext) {
return Pos;
}
+namespace {
struct FindByName {
FindByName(StringRef Ext) : Ext(Ext){};
StringRef Ext;
@@ -146,12 +156,14 @@ struct FindByName {
return ExtInfo.Name == Ext;
}
};
+} // namespace
-static Optional<RISCVExtensionVersion> findDefaultVersion(StringRef ExtName) {
+static std::optional<RISCVExtensionVersion>
+findDefaultVersion(StringRef ExtName) {
// Find default version of an extension.
// TODO: We might set default version based on profile or ISA spec.
- for (auto &ExtInfo : {makeArrayRef(SupportedExtensions),
- makeArrayRef(SupportedExperimentalExtensions)}) {
+ for (auto &ExtInfo : {ArrayRef(SupportedExtensions),
+ ArrayRef(SupportedExperimentalExtensions)}) {
auto ExtensionInfoIterator = llvm::find_if(ExtInfo, FindByName(ExtName));
if (ExtensionInfoIterator == ExtInfo.end()) {
@@ -159,7 +171,7 @@ static Optional<RISCVExtensionVersion> findDefaultVersion(StringRef ExtName) {
}
return ExtensionInfoIterator->Version;
}
- return None;
+ return std::nullopt;
}
void RISCVISAInfo::addExtension(StringRef ExtName, unsigned MajorVersion,
@@ -195,11 +207,12 @@ static StringRef getExtensionType(StringRef Ext) {
return StringRef();
}
-static Optional<RISCVExtensionVersion> isExperimentalExtension(StringRef Ext) {
+static std::optional<RISCVExtensionVersion>
+isExperimentalExtension(StringRef Ext) {
auto ExtIterator =
llvm::find_if(SupportedExperimentalExtensions, FindByName(Ext));
if (ExtIterator == std::end(SupportedExperimentalExtensions))
- return None;
+ return std::nullopt;
return ExtIterator->Version;
}
@@ -273,17 +286,14 @@ static int multiLetterExtensionRank(const std::string &ExtName) {
case 's':
HighOrder = 0;
break;
- case 'h':
- HighOrder = 1;
- break;
case 'z':
- HighOrder = 2;
+ HighOrder = 1;
// `z` extension must be sorted by canonical order of second letter.
// e.g. zmx has higher rank than zax.
LowOrder = singleLetterExtensionRank(ExtName[1]);
break;
case 'x':
- HighOrder = 3;
+ HighOrder = 2;
break;
default:
llvm_unreachable("Unknown prefix for multi-char extension");
@@ -321,7 +331,8 @@ bool RISCVISAInfo::compareExtension(const std::string &LHS,
void RISCVISAInfo::toFeatures(
std::vector<StringRef> &Features,
- std::function<StringRef(const Twine &)> StrAlloc) const {
+ llvm::function_ref<StringRef(const Twine &)> StrAlloc,
+ bool AddAllExtensions) const {
for (auto const &Ext : Exts) {
StringRef ExtName = Ext.first;
@@ -334,6 +345,19 @@ void RISCVISAInfo::toFeatures(
Features.push_back(StrAlloc("+" + ExtName));
}
}
+ if (AddAllExtensions) {
+ for (const RISCVSupportedExtension &Ext : SupportedExtensions) {
+ if (Exts.count(Ext.Name))
+ continue;
+ Features.push_back(StrAlloc(Twine("-") + Ext.Name));
+ }
+
+ for (const RISCVSupportedExtension &Ext : SupportedExperimentalExtensions) {
+ if (Exts.count(Ext.Name))
+ continue;
+ Features.push_back(StrAlloc(Twine("-experimental-") + Ext.Name));
+ }
+ }
}
// Extensions may have a version number, and may be separated by
@@ -458,8 +482,8 @@ RISCVISAInfo::parseFeatures(unsigned XLen,
ExtName = ExtName.drop_front(1); // Drop '+' or '-'
Experimental = stripExperimentalPrefix(ExtName);
auto ExtensionInfos = Experimental
- ? makeArrayRef(SupportedExperimentalExtensions)
- : makeArrayRef(SupportedExtensions);
+ ? ArrayRef(SupportedExperimentalExtensions)
+ : ArrayRef(SupportedExtensions);
auto ExtensionInfoIterator =
llvm::find_if(ExtensionInfos, FindByName(ExtName));
@@ -480,7 +504,8 @@ RISCVISAInfo::parseFeatures(unsigned XLen,
llvm::Expected<std::unique_ptr<RISCVISAInfo>>
RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension,
- bool ExperimentalExtensionVersionCheck) {
+ bool ExperimentalExtensionVersionCheck,
+ bool IgnoreUnknown) {
// RISC-V ISA strings must be lowercase.
if (llvm::any_of(Arch, isupper)) {
return createStringError(errc::invalid_argument,
@@ -547,7 +572,7 @@ RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension,
// No matter which version is given to `g`, we always set imafd to default
// version since the we don't have clear version scheme for that on
// ISA spec.
- for (auto Ext : {"i", "m", "a", "f", "d"})
+ for (const auto *Ext : {"i", "m", "a", "f", "d"})
if (auto Version = findDefaultVersion(Ext))
ISAInfo->addExtension(Ext, Version->Major, Version->Minor);
else
@@ -565,6 +590,11 @@ RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension,
auto StdExtsItr = StdExts.begin();
auto StdExtsEnd = StdExts.end();
+ auto GoToNextExt = [](StringRef::iterator &I, unsigned ConsumeLength) {
+ I += 1 + ConsumeLength;
+ if (*I == '_')
+ ++I;
+ };
for (auto I = Exts.begin(), E = Exts.end(); I != E;) {
char C = *I;
@@ -595,25 +625,32 @@ RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension,
Next = std::string(std::next(I), E);
if (auto E = getExtensionVersion(std::string(1, C), Next, Major, Minor,
ConsumeLength, EnableExperimentalExtension,
- ExperimentalExtensionVersionCheck))
+ ExperimentalExtensionVersionCheck)) {
+ if (IgnoreUnknown) {
+ consumeError(std::move(E));
+ GoToNextExt(I, ConsumeLength);
+ continue;
+ }
return std::move(E);
+ }
// The order is OK, then push it into features.
// TODO: Use version number when setting target features
- // Currently LLVM supports only "mafdcbv".
- StringRef SupportedStandardExtension = "mafdcbv";
- if (!SupportedStandardExtension.contains(C))
+ // Currently LLVM supports only "mafdcvh".
+ if (!isSupportedExtension(StringRef(&C, 1))) {
+ if (IgnoreUnknown) {
+ GoToNextExt(I, ConsumeLength);
+ continue;
+ }
return createStringError(errc::invalid_argument,
"unsupported standard user-level extension '%c'",
C);
+ }
ISAInfo->addExtension(std::string(1, C), Major, Minor);
// Consume full extension name and version, including any optional '_'
// between this extension and the next
- ++I;
- I += ConsumeLength;
- if (*I == '_')
- ++I;
+ GoToNextExt(I, ConsumeLength);
}
// Handle other types of extensions other than the standard
@@ -647,20 +684,26 @@ RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension,
StringRef Name(Ext.substr(0, Pos));
StringRef Vers(Ext.substr(Pos));
- if (Type.empty())
+ if (Type.empty()) {
+ if (IgnoreUnknown)
+ continue;
return createStringError(errc::invalid_argument,
"invalid extension prefix '" + Ext + "'");
+ }
// Check ISA extensions are specified in the canonical order.
while (I != E && *I != Type)
++I;
- if (I == E)
+ if (I == E) {
+ if (IgnoreUnknown)
+ continue;
return createStringError(errc::invalid_argument,
"%s not given in canonical order '%s'",
Desc.str().c_str(), Ext.str().c_str());
+ }
- if (Name.size() == Type.size()) {
+ if (!IgnoreUnknown && Name.size() == Type.size()) {
return createStringError(errc::invalid_argument,
"%s name missing after '%s'",
Desc.str().c_str(), Type.str().c_str());
@@ -669,13 +712,19 @@ RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension,
unsigned Major, Minor, ConsumeLength;
if (auto E = getExtensionVersion(Name, Vers, Major, Minor, ConsumeLength,
EnableExperimentalExtension,
- ExperimentalExtensionVersionCheck))
+ ExperimentalExtensionVersionCheck)) {
+ if (IgnoreUnknown) {
+ consumeError(std::move(E));
+ continue;
+ }
return std::move(E);
+ }
// Check if duplicated extension.
- if (llvm::is_contained(AllExts, Name))
+ if (!IgnoreUnknown && llvm::is_contained(AllExts, Name)) {
return createStringError(errc::invalid_argument, "duplicated %s '%s'",
Desc.str().c_str(), Name.str().c_str());
+ }
ISAInfo->addExtension(Name, Major, Minor);
// Extension format is correct, keep parsing the extensions.
@@ -772,9 +821,11 @@ static const char *ImpliedExtsZvl256b[] = {"zvl128b"};
static const char *ImpliedExtsZvl128b[] = {"zvl64b"};
static const char *ImpliedExtsZvl64b[] = {"zvl32b"};
static const char *ImpliedExtsZk[] = {"zkn", "zkt", "zkr"};
-static const char *ImpliedExtsZkn[] = {"zbkb", "zbkc", "zbkx", "zkne", "zknd", "zknh"};
+static const char *ImpliedExtsZkn[] = {"zbkb", "zbkc", "zbkx",
+ "zkne", "zknd", "zknh"};
static const char *ImpliedExtsZks[] = {"zbkb", "zbkc", "zbkx", "zksed", "zksh"};
static const char *ImpliedExtsZvfh[] = {"zve32f"};
+static const char *ImpliedExtsXTHeadVdot[] = {"v"};
struct ImpliedExtsEntry {
StringLiteral Name;
@@ -790,6 +841,7 @@ struct ImpliedExtsEntry {
// Note: The table needs to be sorted by name.
static constexpr ImpliedExtsEntry ImpliedExts[] = {
{{"v"}, {ImpliedExtsV}},
+ {{"xtheadvdot"}, {ImpliedExtsXTHeadVdot}},
{{"zdinx"}, {ImpliedExtsZdinx}},
{{"zfh"}, {ImpliedExtsZfh}},
{{"zfhmin"}, {ImpliedExtsZfhmin}},