diff options
Diffstat (limited to 'llvm/lib/Support/RISCVISAInfo.cpp')
-rw-r--r-- | llvm/lib/Support/RISCVISAInfo.cpp | 136 |
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}}, |