diff --git a/llvm/include/llvm/Support/RISCVISAInfo.h b/llvm/include/llvm/Support/RISCVISAInfo.h --- a/llvm/include/llvm/Support/RISCVISAInfo.h +++ b/llvm/include/llvm/Support/RISCVISAInfo.h @@ -85,10 +85,12 @@ static bool isSupportedExtensionFeature(StringRef Ext); static bool isSupportedExtension(StringRef Ext); + static bool isSupportedExtensionWithVersion(StringRef Ext); static bool isSupportedExtension(StringRef Ext, unsigned MajorVersion, unsigned MinorVersion); static llvm::Expected> postProcessAndChecking(std::unique_ptr &&ISAInfo); + static std::string getTargetFeatureFromOneExt(StringRef Ext); private: RISCVISAInfo(unsigned XLen) diff --git a/llvm/lib/Support/RISCVISAInfo.cpp b/llvm/lib/Support/RISCVISAInfo.cpp --- a/llvm/lib/Support/RISCVISAInfo.cpp +++ b/llvm/lib/Support/RISCVISAInfo.cpp @@ -181,7 +181,7 @@ // 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) { +static size_t findLastNonVersionCharacter(StringRef Ext) { assert(!Ext.empty() && "Already guarded by if-statement in ::parseArchString"); @@ -789,7 +789,7 @@ StringRef Type = getExtensionType(Ext); StringRef Desc = getExtensionTypeDesc(Ext); - auto Pos = findFirstNonVersionCharacter(Ext) + 1; + auto Pos = findLastNonVersionCharacter(Ext) + 1; StringRef Name(Ext.substr(0, Pos)); StringRef Vers(Ext.substr(Pos)); @@ -1192,3 +1192,41 @@ } llvm_unreachable("Invalid XLEN"); } + +bool RISCVISAInfo::isSupportedExtensionWithVersion(StringRef Ext) { + if (Ext.empty()) + return false; + + auto Pos = findLastNonVersionCharacter(Ext) + 1; + StringRef Name = Ext.substr(0, Pos); + StringRef Vers = Ext.substr(Pos); + if (Vers.empty()) + return false; + + unsigned Major, Minor, ConsumeLength; + if (auto E = getExtensionVersion(Name, Vers, Major, Minor, ConsumeLength, + true, true)) { + consumeError(std::move(E)); + return false; + } + + return true; +} + +std::string RISCVISAInfo::getTargetFeatureFromOneExt(StringRef Ext) { + if (Ext.empty()) + return std::string(); + + auto Pos = findLastNonVersionCharacter(Ext) + 1; + StringRef Name = Ext.substr(0, Pos); + StringRef Vers = Ext.substr(Pos); + + if (!Vers.empty() && !isSupportedExtensionWithVersion(Ext)) + return std::string(); + + if (!isSupportedExtension(Name)) + return std::string(); + + return isExperimentalExtension(Name) ? "experimental-" + Name.str() + : Name.str(); +} diff --git a/llvm/unittests/Support/RISCVISAInfoTest.cpp b/llvm/unittests/Support/RISCVISAInfoTest.cpp --- a/llvm/unittests/Support/RISCVISAInfoTest.cpp +++ b/llvm/unittests/Support/RISCVISAInfoTest.cpp @@ -485,3 +485,24 @@ ElementsAre("i", "m", "l", "c", "y", "zicsr", "zmfoo", "zfinx", "zzfoo", "sbar", "sfoo", "xbar", "xfoo")); } + +TEST(isSupportedExtensionWithVersion, AcceptsSingleExtensionWithVersion) { + EXPECT_EQ(RISCVISAInfo::isSupportedExtensionWithVersion("zbb1p0"), true); + EXPECT_EQ(RISCVISAInfo::isSupportedExtensionWithVersion("zbb"), false); + EXPECT_EQ(RISCVISAInfo::isSupportedExtensionWithVersion("zfoo1p0"), false); + EXPECT_EQ(RISCVISAInfo::isSupportedExtensionWithVersion("zfoo"), false); + EXPECT_EQ(RISCVISAInfo::isSupportedExtensionWithVersion(""), false); + EXPECT_EQ(RISCVISAInfo::isSupportedExtensionWithVersion("c2p0zbb1p0"), false); +} + +TEST(getTargetFeatureFromOneExt, RetrieveTargetFeatureFromOneExt) { + EXPECT_EQ(RISCVISAInfo::getTargetFeatureFromOneExt("zbb"), "zbb"); + EXPECT_EQ(RISCVISAInfo::getTargetFeatureFromOneExt("zihintntl0p2"), + "experimental-zihintntl"); + EXPECT_EQ(RISCVISAInfo::getTargetFeatureFromOneExt("zihintntl"), + "experimental-zihintntl"); + EXPECT_EQ(RISCVISAInfo::getTargetFeatureFromOneExt("zihintntl1234p4321"), ""); + EXPECT_EQ(RISCVISAInfo::getTargetFeatureFromOneExt("zfoo"), ""); + EXPECT_EQ(RISCVISAInfo::getTargetFeatureFromOneExt(""), ""); + EXPECT_EQ(RISCVISAInfo::getTargetFeatureFromOneExt("zbbzihintntl"), ""); +}