Index: clang/lib/Basic/Targets/RISCV.cpp =================================================================== --- clang/lib/Basic/Targets/RISCV.cpp +++ clang/lib/Basic/Targets/RISCV.cpp @@ -150,7 +150,7 @@ auto ExtName = Extension.first; auto ExtInfo = Extension.second; unsigned Version = - (ExtInfo.MajorVersion * 1000000) + (ExtInfo.MinorVersion * 1000); + (ExtInfo.Version.Major * 1000000) + (ExtInfo.Version.Minor * 1000); Builder.defineMacro(Twine("__riscv_", ExtName), Twine(Version)); } @@ -223,10 +223,7 @@ if (Result.hasValue()) return Result.getValue(); - if (ISAInfo->isSupportedExtensionFeature(Feature)) - return ISAInfo->hasExtension(Feature); - - return false; + return ISAInfo->hasExtensionWithVersion(Feature); } /// Perform initialization based on the user configured set of features. Index: clang/lib/Driver/ToolChains/Arch/RISCV.cpp =================================================================== --- clang/lib/Driver/ToolChains/Arch/RISCV.cpp +++ clang/lib/Driver/ToolChains/Arch/RISCV.cpp @@ -41,8 +41,12 @@ return false; } - (*ISAInfo)->toFeatures( - Features, [&Args](const Twine &Str) { return Args.MakeArgString(Str); }); + std::vector ToFeatures; + (*ISAInfo)->toFeatures(ToFeatures); + + for (const auto &Feature : ToFeatures) + Features.push_back(Args.MakeArgString("+" + Feature)); + return true; } Index: clang/test/Driver/riscv-arch-version.c =================================================================== --- /dev/null +++ clang/test/Driver/riscv-arch-version.c @@ -0,0 +1,181 @@ +// RUN: %clang -target riscv32-unknown-elf -march=rv32e1p9 -### %s -c 2>&1 | \ +// RUN: FileCheck -check-prefix=RV32-E1P9 %s +// RV32-E1P9: "-target-feature" "+e" + +// RUN: %clang -target riscv32-unknown-elf -march=rv32im2p0 -### %s -c 2>&1 | \ +// RUN: FileCheck -check-prefix=RV32-M2P0 %s +// RV32-M2P0: "-target-feature" "+m" + +// RUN: %clang -target riscv32-unknown-elf -march=rv32ia2p0 -### %s -c 2>&1 | \ +// RUN: FileCheck -check-prefix=RV32-A2P0 %s +// RV32-A2P0: "-target-feature" "+a" + +// RUN: %clang -target riscv32-unknown-elf -march=rv32if2p0 -### %s -c 2>&1 | \ +// RUN: FileCheck -check-prefix=RV32-F2P0 %s +// RV32-F2P0: "-target-feature" "+f" + +// RUN: %clang -target riscv32-unknown-elf -march=rv32ifd2p0 -### %s -c 2>&1 | \ +// RUN: FileCheck -check-prefix=RV32-D2P0 %s +// RV32-D2P0: "-target-feature" "+f" "-target-feature" "+d" + +// RUN: %clang -target riscv32-unknown-elf -march=rv32ic2p0 -### %s -c 2>&1 | \ +// RUN: FileCheck -check-prefix=RV32-C2P0 %s +// RV32-C2P0: "-target-feature" "+c" + +// RUN: %clang -target riscv32-unknown-elf -march=rv32iv0p10 -menable-experimental-extensions -### %s -c 2>&1 | \ +// RUN: FileCheck -check-prefix=RV32-EXPERIMENTAL-V0P10 %s +// RV32-EXPERIMENTAL-V0P10: "-target-feature" "+experimental-v" + +// RUN: %clang -target riscv32-unknown-elf -march=rv32izba1p0 -menable-experimental-extensions -### %s -c 2>&1 | \ +// RUN: FileCheck -check-prefix=RV32-EXPERIMENTAL-ZBA1P0 %s +// RV32-EXPERIMENTAL-ZBA1P0: "-target-feature" "+experimental-zba" + +// RUN: %clang -target riscv32-unknown-elf -march=rv32izbb1p0 -menable-experimental-extensions -### %s -c 2>&1 | \ +// RUN: FileCheck -check-prefix=RV32-EXPERIMENTAL-ZBB1P0 %s +// RV32-EXPERIMENTAL-ZBB1P0: "-target-feature" "+experimental-zbb" + +// RUN: %clang -target riscv32-unknown-elf -march=rv32izbc1p0 -menable-experimental-extensions -### %s -c 2>&1 | \ +// RUN: FileCheck -check-prefix=RV32-EXPERIMENTAL-ZBC1P0 %s +// RV32-EXPERIMENTAL-ZBC1P0: "-target-feature" "+experimental-zbc" + +// RUN: %clang -target riscv32-unknown-elf -march=rv32izbe0p93 -menable-experimental-extensions -### %s -c 2>&1 | \ +// RUN: FileCheck -check-prefix=RV32-EXPERIMENTAL-ZBE0P93 %s +// RV32-EXPERIMENTAL-ZBE0P93: "-target-feature" "+experimental-zbe" + +// RUN: %clang -target riscv32-unknown-elf -march=rv32izbf0p93 -menable-experimental-extensions -### %s -c 2>&1 | \ +// RUN: FileCheck -check-prefix=RV32-EXPERIMENTAL-ZBF0P93 %s +// RV32-EXPERIMENTAL-ZBF0P93: "-target-feature" "+experimental-zbf" + +// RUN: %clang -target riscv32-unknown-elf -march=rv32izbm0p93 -menable-experimental-extensions -### %s -c 2>&1 | \ +// RUN: FileCheck -check-prefix=RV32-EXPERIMENTAL-ZBM0P93 %s +// RV32-EXPERIMENTAL-ZBM0P93: "-target-feature" "+experimental-zbm" + +// RUN: %clang -target riscv32-unknown-elf -march=rv32izbp0p93 -menable-experimental-extensions -### %s -c 2>&1 | \ +// RUN: FileCheck -check-prefix=RV32-EXPERIMENTAL-ZBP0P93 %s +// RV32-EXPERIMENTAL-ZBP0P93: "-target-feature" "+experimental-zbp" + +// RUN: %clang -target riscv32-unknown-elf -march=rv32izbr0p93 -menable-experimental-extensions -### %s -c 2>&1 | \ +// RUN: FileCheck -check-prefix=RV32-EXPERIMENTAL-ZBR0P93 %s +// RV32-EXPERIMENTAL-ZBR0P93: "-target-feature" "+experimental-zbr" + +// RUN: %clang -target riscv32-unknown-elf -march=rv32izbs1p0 -menable-experimental-extensions -### %s -c 2>&1 | \ +// RUN: FileCheck -check-prefix=RV32-EXPERIMENTAL-ZBS1P0 %s +// RV32-EXPERIMENTAL-ZBS1P0: "-target-feature" "+experimental-zbs" + +// RUN: %clang -target riscv32-unknown-elf -march=rv32izbt0p93 -menable-experimental-extensions -### %s -c 2>&1 | \ +// RUN: FileCheck -check-prefix=RV32-EXPERIMENTAL-ZBT0P93 %s +// RV32-EXPERIMENTAL-ZBT0P93: "-target-feature" "+experimental-zbt" + +// RUN: %clang -target riscv32-unknown-elf -march=rv32izvlsseg0p10 -menable-experimental-extensions -### %s -c 2>&1 | \ +// RUN: FileCheck -check-prefix=RV32-EXPERIMENTAL-ZVLSSEG0P10 %s +// RV32-EXPERIMENTAL-ZVLSSEG0P10: "-target-feature" "+experimental-zvlsseg" + +// RUN: %clang -target riscv32-unknown-elf -march=rv32izfhmin0p1 -menable-experimental-extensions -### %s -c 2>&1 | \ +// RUN: FileCheck -check-prefix=RV32-EXPERIMENTAL-ZFHMIN0P1 %s +// RV32-EXPERIMENTAL-ZFHMIN0P1: "-target-feature" "+experimental-zfhmin" + +// RUN: %clang -target riscv32-unknown-elf -march=rv32izfh0p1 -menable-experimental-extensions -### %s -c 2>&1 | \ +// RUN: FileCheck -check-prefix=RV32-EXPERIMENTAL-ZFH0P1 %s +// RV32-EXPERIMENTAL-ZFH0P1: "-target-feature" "+experimental-zfh" + +// Error Check Blow. + +// RUN: %clang -target riscv32-unknown-elf -march=rv32e2p0 -### %s -c 2>&1 | \ +// RUN: FileCheck -check-prefix=RV32-E2P0 %s +// RV32-E2P0: error: invalid arch name 'rv32e2p0' +// RV32-E2P0: unsupported version number 2.0 for extension 'e' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32im2p1 -### %s -c 2>&1 | \ +// RUN: FileCheck -check-prefix=RV32-M2P1 %s +// RV32-M2P1: error: invalid arch name 'rv32im2p1' +// RV32-M2P1: unsupported version number 2.1 for extension 'm' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32ia2p1 -### %s -c 2>&1 | \ +// RUN: FileCheck -check-prefix=RV32-A2P1 %s +// RV32-A2P1: error: invalid arch name 'rv32ia2p1' +// RV32-A2P1: unsupported version number 2.1 for extension 'a' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32if2p1 -### %s -c 2>&1 | \ +// RUN: FileCheck -check-prefix=RV32-F2P1 %s +// RV32-F2P1: error: invalid arch name 'rv32if2p1' +// RV32-F2P1: unsupported version number 2.1 for extension 'f' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32id2p1 -### %s -c 2>&1 | \ +// RUN: FileCheck -check-prefix=RV32-D2P1 %s +// RV32-D2P1: error: invalid arch name 'rv32id2p1' +// RV32-D2P1: unsupported version number 2.1 for extension 'd' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32ic2p1 -### %s -c 2>&1 | \ +// RUN: FileCheck -check-prefix=RV32-C2P1 %s +// RV32-C2P1: error: invalid arch name 'rv32ic2p1' +// RV32-C2P1: unsupported version number 2.1 for extension 'c' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32iv0p7 -menable-experimental-extensions -### %s -c 2>&1 | \ +// RUN: FileCheck -check-prefix=RV32-EXPERIMENTAL-V0P7 %s +// RV32-EXPERIMENTAL-V0P7: error: invalid arch name 'rv32iv0p7' +// RV32-EXPERIMENTAL-V0P7: unsupported version number 0.7 for experimental extension 'v' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32izba0p7 -menable-experimental-extensions -### %s -c 2>&1 | \ +// RUN: FileCheck -check-prefix=RV32-EXPERIMENTAL-ZBA0P7 %s +// RV32-EXPERIMENTAL-ZBA0P7: error: invalid arch name 'rv32izba0p7' +// RV32-EXPERIMENTAL-ZBA0P7: unsupported version number 0.7 for experimental extension 'zba' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32izbb0p7 -menable-experimental-extensions -### %s -c 2>&1 | \ +// RUN: FileCheck -check-prefix=RV32-EXPERIMENTAL-ZBB0P7 %s +// RV32-EXPERIMENTAL-ZBB0P7: error: invalid arch name 'rv32izbb0p7' +// RV32-EXPERIMENTAL-ZBB0P7: unsupported version number 0.7 for experimental extension 'zbb' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32izbc0p7 -menable-experimental-extensions -### %s -c 2>&1 | \ +// RUN: FileCheck -check-prefix=RV32-EXPERIMENTAL-ZBC0P7 %s +// RV32-EXPERIMENTAL-ZBC0P7: error: invalid arch name 'rv32izbc0p7' +// RV32-EXPERIMENTAL-ZBC0P7: unsupported version number 0.7 for experimental extension 'zbc' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32izbe0p7 -menable-experimental-extensions -### %s -c 2>&1 | \ +// RUN: FileCheck -check-prefix=RV32-EXPERIMENTAL-ZBE0P7 %s +// RV32-EXPERIMENTAL-ZBE0P7: error: invalid arch name 'rv32izbe0p7' +// RV32-EXPERIMENTAL-ZBE0P7: unsupported version number 0.7 for experimental extension 'zbe' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32izbf0p7 -menable-experimental-extensions -### %s -c 2>&1 | \ +// RUN: FileCheck -check-prefix=RV32-EXPERIMENTAL-ZBF0P7 %s +// RV32-EXPERIMENTAL-ZBF0P7: error: invalid arch name 'rv32izbf0p7' +// RV32-EXPERIMENTAL-ZBF0P7: unsupported version number 0.7 for experimental extension 'zbf' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32izbm0p7 -menable-experimental-extensions -### %s -c 2>&1 | \ +// RUN: FileCheck -check-prefix=RV32-EXPERIMENTAL-ZBM0P7 %s +// RV32-EXPERIMENTAL-ZBM0P7: error: invalid arch name 'rv32izbm0p7' +// RV32-EXPERIMENTAL-ZBM0P7: unsupported version number 0.7 for experimental extension 'zbm' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32izbp0p7 -menable-experimental-extensions -### %s -c 2>&1 | \ +// RUN: FileCheck -check-prefix=RV32-EXPERIMENTAL-ZBP0P7 %s +// RV32-EXPERIMENTAL-ZBP0P7: error: invalid arch name 'rv32izbp0p7' +// RV32-EXPERIMENTAL-ZBP0P7: unsupported version number 0.7 for experimental extension 'zbp' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32izbr0p7 -menable-experimental-extensions -### %s -c 2>&1 | \ +// RUN: FileCheck -check-prefix=RV32-EXPERIMENTAL-ZBR0P7 %s +// RV32-EXPERIMENTAL-ZBR0P7: error: invalid arch name 'rv32izbr0p7' +// RV32-EXPERIMENTAL-ZBR0P7: unsupported version number 0.7 for experimental extension 'zbr' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32izbs0p7 -menable-experimental-extensions -### %s -c 2>&1 | \ +// RUN: FileCheck -check-prefix=RV32-EXPERIMENTAL-ZBS0P7 %s +// RV32-EXPERIMENTAL-ZBS0P7: error: invalid arch name 'rv32izbs0p7' +// RV32-EXPERIMENTAL-ZBS0P7: unsupported version number 0.7 for experimental extension 'zbs' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32izbt0p7 -menable-experimental-extensions -### %s -c 2>&1 | \ +// RUN: FileCheck -check-prefix=RV32-EXPERIMENTAL-ZBT0P7 %s +// RV32-EXPERIMENTAL-ZBT0P7: error: invalid arch name 'rv32izbt0p7' +// RV32-EXPERIMENTAL-ZBT0P7: unsupported version number 0.7 for experimental extension 'zbt' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32izvlsseg0p1 -menable-experimental-extensions -### %s -c 2>&1 | \ +// RUN: FileCheck -check-prefix=RV32-EXPERIMENTAL-ZVLSSEG0P1 %s +// RV32-EXPERIMENTAL-ZVLSSEG0P1: error: invalid arch name 'rv32izvlsseg0p1' +// RV32-EXPERIMENTAL-ZVLSSEG0P1: unsupported version number 0.1 for experimental extension 'zvlsseg' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32izfhmin0p7 -menable-experimental-extensions -### %s -c 2>&1 | \ +// RUN: FileCheck -check-prefix=RV32-EXPERIMENTAL-ZFHMIN0P7 %s +// RV32-EXPERIMENTAL-ZFHMIN0P7: error: invalid arch name 'rv32izfhmin0p7' +// RV32-EXPERIMENTAL-ZFHMIN0P7: unsupported version number 0.7 for experimental extension 'zfhmin' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32izfh0p7 -menable-experimental-extensions -### %s -c 2>&1 | \ +// RUN: FileCheck -check-prefix=RV32-EXPERIMENTAL-ZFH0P7 %s +// RV32-EXPERIMENTAL-ZFH0P7: error: invalid arch name 'rv32izfh0p7' +// RV32-EXPERIMENTAL-ZFH0P7: unsupported version number 0.7 for experimental extension 'zfh' Index: llvm/include/llvm/Support/RISCVISAInfo.h =================================================================== --- llvm/include/llvm/Support/RISCVISAInfo.h +++ llvm/include/llvm/Support/RISCVISAInfo.h @@ -19,10 +19,34 @@ #include namespace llvm { + +/// Represents the major and version number components of a RISC-V extension +struct RISCVExtensionVersion { + unsigned Major; + unsigned Minor; + + RISCVExtensionVersion() : Major(0), Minor(0) {} + RISCVExtensionVersion(unsigned Maj, unsigned Min) : Major(Maj), Minor(Min) {} + + bool operator==(const RISCVExtensionVersion &Version) const { + return Major == Version.Major && Minor == Version.Minor; + } + + bool operator!=(const RISCVExtensionVersion &Version) const { + return !(*this == Version); + } + + bool operator<(const RISCVExtensionVersion &Version) const { + return (Major < Version.Major) || + (Major == Version.Major && Minor < Version.Minor); + } + + operator bool() const { return Major != 0 || Minor != 0; } +}; + struct RISCVExtensionInfo { std::string ExtName; - unsigned MajorVersion; - unsigned MinorVersion; + RISCVExtensionVersion Version; }; class RISCVISAInfo { @@ -47,15 +71,15 @@ /// Parse RISCV ISA info from arch string. static llvm::Expected> parseArchString(StringRef Arch, bool EnableExperimentalExtension, - bool ExperimentalExtensionVersionCheck = true); + bool ExperimentalExtensionVersionCheck = true, + bool IgnoreUnknownExtension = false); /// Parse RISCV ISA info from feature vector. static llvm::Expected> parseFeatures(unsigned XLen, const std::vector &Features); /// Convert RISCV ISA info to a feature vector. - void toFeatures(std::vector &Features, - std::function StrAlloc) const; + void toFeatures(std::vector &Features) const; const OrderedExtensionMap &getExtensions() const { return Exts; }; @@ -63,9 +87,11 @@ unsigned getFLen() const { return FLen; }; bool hasExtension(StringRef Ext) const; + bool hasExtensionWithVersion(StringRef Ext) const; std::string toString() const; - static bool isSupportedExtensionFeature(StringRef Ext); + static Optional + isSupportedExtensionFeature(StringRef Ext); static bool isSupportedExtension(StringRef Ext); static bool isSupportedExtension(StringRef Ext, unsigned MajorVersion, unsigned MinorVersion); Index: llvm/lib/Object/ELFObjectFile.cpp =================================================================== --- llvm/lib/Object/ELFObjectFile.cpp +++ llvm/lib/Object/ELFObjectFile.cpp @@ -26,6 +26,7 @@ #include "llvm/Support/MathExtras.h" #include "llvm/Support/RISCVAttributeParser.h" #include "llvm/Support/RISCVAttributes.h" +#include "llvm/Support/RISCVISAInfo.h" #include #include #include @@ -309,35 +310,27 @@ // The Arch pattern is [rv32|rv64][i|e]version(_[m|a|f|d|c]version)* // Version string pattern is (major)p(minor). Major and minor are optional. // For example, a version number could be 2p0, 2, or p92. - StringRef Arch = Attr.getValue(); - if (Arch.consume_front("rv32")) + auto ParseResult = + llvm::RISCVISAInfo::parseArchString(Attr.getValue(), true, true, true); + if (!ParseResult) + return Features; + + auto &ISAInfo = *ParseResult; + + if (ISAInfo->getXLen() == 32) Features.AddFeature("64bit", false); - else if (Arch.consume_front("rv64")) + else if (ISAInfo->getXLen() == 64) Features.AddFeature("64bit"); - while (!Arch.empty()) { - switch (Arch[0]) { - default: - break; // Ignore unexpected features. - case 'i': - Features.AddFeature("e", false); - break; - case 'd': - Features.AddFeature("f"); // D-ext will imply F-ext. - LLVM_FALLTHROUGH; - case 'e': - case 'm': - case 'a': - case 'f': - case 'c': - Features.AddFeature(Arch.take_front()); - break; - } - - // FIXME: Handle version numbers. - Arch = Arch.drop_until([](char c) { return c == '_' || c == '\0'; }); - Arch = Arch.drop_while([](char c) { return c == '_'; }); + if (PlatformFlags & ELF::EF_RISCV_RVC) { + Features.AddFeature("c", false); } + + std::vector ToFeatures; + ISAInfo->toFeatures(ToFeatures); + + for (const auto &Feature : ToFeatures) + Features.AddFeature(Feature); } return Features; Index: llvm/lib/Support/RISCVISAInfo.cpp =================================================================== --- llvm/lib/Support/RISCVISAInfo.cpp +++ llvm/lib/Support/RISCVISAInfo.cpp @@ -22,11 +22,6 @@ using namespace llvm; namespace { -/// Represents the major and version number components of a RISC-V extension -struct RISCVExtensionVersion { - unsigned Major; - unsigned Minor; -}; struct RISCVSupportedExtension { const char *Name; @@ -50,6 +45,7 @@ static const RISCVSupportedExtension SupportedExperimentalExtensions[] = { {"v", RISCVExtensionVersion{0, 10}}, + //{"v", RISCVExtensionVersion{0, 7}}, {"zba", RISCVExtensionVersion{1, 0}}, {"zbb", RISCVExtensionVersion{1, 0}}, {"zbc", RISCVExtensionVersion{1, 0}}, @@ -62,11 +58,17 @@ {"zbt", RISCVExtensionVersion{0, 93}}, {"zvlsseg", RISCVExtensionVersion{0, 10}}, + //{"zvlsseg", RISCVExtensionVersion{0, 7}}, {"zfhmin", RISCVExtensionVersion{0, 1}}, {"zfh", RISCVExtensionVersion{0, 1}}, }; +static Error getExtensionVersion(StringRef Ext, StringRef In, unsigned &Major, + unsigned &Minor, unsigned &ConsumeLength, + bool EnableExperimentalExtension, + bool ExperimentalExtensionVersionCheck); + static bool stripExperimentalPrefix(StringRef &Ext) { return Ext.consume_front("experimental-"); } @@ -120,8 +122,8 @@ unsigned MinorVersion) { RISCVExtensionInfo Ext; Ext.ExtName = ExtName.str(); - Ext.MajorVersion = MajorVersion; - Ext.MinorVersion = MinorVersion; + Ext.Version.Major = MajorVersion; + Ext.Version.Minor = MinorVersion; Exts[ExtName.str()] = Ext; } @@ -149,22 +151,47 @@ return StringRef(); } -static Optional isExperimentalExtension(StringRef Ext) { - auto ExtIterator = - llvm::find_if(SupportedExperimentalExtensions, FindByName(Ext)); - if (ExtIterator == std::end(SupportedExperimentalExtensions)) - return None; +static std::vector +getExperimentalExtensionVersions(StringRef Ext) { + std::vector Result; - return ExtIterator->Version; + for (auto &Extension : SupportedExperimentalExtensions) { + if (Extension.Name == Ext) + Result.push_back(Extension.Version); + } + + return Result; } -bool RISCVISAInfo::isSupportedExtensionFeature(StringRef Ext) { - bool IsExperimental = stripExperimentalPrefix(Ext); +Optional +RISCVISAInfo::isSupportedExtensionFeature(StringRef Ext) { + stripExperimentalPrefix(Ext); - if (IsExperimental) - return llvm::any_of(SupportedExperimentalExtensions, FindByName(Ext)); - else - return llvm::any_of(SupportedExtensions, FindByName(Ext)); + auto Pos = findFirstNonVersionCharacter(Ext) + 1; + StringRef Name(Ext.substr(0, Pos)); + StringRef Vers(Ext.substr(Pos)); + + unsigned Major, Minor, ConsumeLength; + if (Vers.empty()) { + auto Version = findDefaultVersion(Name); + if (!Version) + return None; + + Major = Version->Major; + Minor = Version->Minor; + + } else if (auto E = getExtensionVersion(Name, Vers, Major, Minor, + ConsumeLength, true, false)) { + // Not all features is related to ISA extension, like `relax` or + // `save-restore`, skip those feature. + consumeError(std::move(E)); + return None; + } + + if (!isSupportedExtension(Name, Major, Minor)) + return None; + + return RISCVExtensionInfo{Name.str(), {Major, Minor}}; } bool RISCVISAInfo::isSupportedExtension(StringRef Ext) { @@ -191,6 +218,20 @@ return Exts.count(Ext.str()) != 0; } +bool RISCVISAInfo::hasExtensionWithVersion(StringRef Ext) const { + auto Info = isSupportedExtensionFeature(Ext); + if (!Info) + return false; + + auto ExtInfoIt = Exts.find(Info->ExtName); + + if (ExtInfoIt == Exts.end()) + return false; + + return ExtInfoIt->second.Version.Major == Info->Version.Major && + ExtInfoIt->second.Version.Minor == Info->Version.Minor; +} + // Get the rank for single-letter extension, lower value meaning higher // priority. static int singleLetterExtensionRank(char Ext) { @@ -273,22 +314,35 @@ return LHS < RHS; } -void RISCVISAInfo::toFeatures( - std::vector &Features, - std::function StrAlloc) const { +static std::string addVersionSuffix(StringRef Suffix, StringRef ExtName, + unsigned Major, unsigned Minor) { + if (auto DefaultVersion = findDefaultVersion(ExtName)) + if (DefaultVersion->Major == Major && DefaultVersion->Minor == Minor) + return (Twine(Suffix) + ExtName).str(); + + return (Suffix + ExtName + Twine(Major) + "p" + Twine(Minor)).str(); +} + +void RISCVISAInfo::toFeatures(std::vector &Features) const { + for (auto &Ext : Exts) { StringRef ExtName = Ext.first; + auto Extension = Ext.second; + unsigned Major = Ext.second.Version.Major; + unsigned Minor = Ext.second.Version.Minor; if (ExtName == "i") continue; if (ExtName == "zvlsseg") { - Features.push_back("+experimental-v"); - Features.push_back("+experimental-zvlsseg"); - } else if (isExperimentalExtension(ExtName)) { - Features.push_back(StrAlloc("+experimental-" + ExtName)); + Features.push_back(addVersionSuffix("experimental-", "v", Major, Minor)); + Features.push_back( + addVersionSuffix("experimental-", "zvlsseg", Major, Minor)); + } else if (!getExperimentalExtensionVersions(ExtName).empty()) { + Features.push_back( + addVersionSuffix("experimental-", ExtName, Major, Minor)); } else { - Features.push_back(StrAlloc("+" + ExtName)); + Features.push_back(addVersionSuffix("", ExtName, Major, Minor)); } } } @@ -346,7 +400,8 @@ } // If experimental extension, require use of current version number number - if (auto ExperimentalExtension = isExperimentalExtension(Ext)) { + auto ExperimentalExtension = getExperimentalExtensionVersions(Ext); + if (!ExperimentalExtension.empty()) { if (!EnableExperimentalExtension) { std::string Error = "requires '-menable-experimental-extensions' for " "experimental extension '" + @@ -362,18 +417,27 @@ return createStringError(errc::invalid_argument, Error); } - auto SupportedVers = *ExperimentalExtension; - if (ExperimentalExtensionVersionCheck && - (Major != SupportedVers.Major || Minor != SupportedVers.Minor)) { - std::string Error = "unsupported version number " + MajorStr.str(); - if (!MinorStr.empty()) - Error += "." + MinorStr.str(); - Error += " for experimental extension '" + Ext.str() + - "'(this compiler supports " + utostr(SupportedVers.Major) + "." + - utostr(SupportedVers.Minor) + ")"; - return createStringError(errc::invalid_argument, Error); + for (auto Version : ExperimentalExtension) { + if (Major == Version.Major && Minor == Version.Minor) + return Error::success(); } - return Error::success(); + + if (!ExperimentalExtensionVersionCheck) + return Error::success(); + + std::string Error = "unsupported version number " + MajorStr.str(); + if (!MinorStr.empty()) + Error += "." + MinorStr.str(); + Error += " for experimental extension '" + Ext.str() + + "'(this compiler supports "; + + ListSeparator LS; + for (auto Version : ExperimentalExtension) { + Error += LS; + Error += (utostr(Version.Major) + "." + utostr(Version.Minor)); + } + Error += ")"; + return createStringError(errc::invalid_argument, Error); } // Exception rule for `g`, we don't have clear version scheme for that on @@ -409,27 +473,19 @@ for (auto &Feature : Features) { StringRef ExtName = Feature; - bool Experimental = false; assert(ExtName.size() > 1 && (ExtName[0] == '+' || ExtName[0] == '-')); bool Add = ExtName[0] == '+'; ExtName = ExtName.drop_front(1); // Drop '+' or '-' - Experimental = stripExperimentalPrefix(ExtName); - auto ExtensionInfos = Experimental - ? makeArrayRef(SupportedExperimentalExtensions) - : makeArrayRef(SupportedExtensions); - auto ExtensionInfoIterator = - llvm::find_if(ExtensionInfos, FindByName(ExtName)); - // Not all features is related to ISA extension, like `relax` or - // `save-restore`, skip those feature. - if (ExtensionInfoIterator == ExtensionInfos.end()) + auto Info = isSupportedExtensionFeature(ExtName); + if (!Info) continue; if (Add) - ISAInfo->addExtension(ExtName, ExtensionInfoIterator->Version.Major, - ExtensionInfoIterator->Version.Minor); + ISAInfo->addExtension(Info->ExtName, Info->Version.Major, + Info->Version.Minor); else - ISAInfo->Exts.erase(ExtName.str()); + ISAInfo->Exts.erase(Info->ExtName); } ISAInfo->updateImplication(); @@ -443,7 +499,8 @@ llvm::Expected> RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension, - bool ExperimentalExtensionVersionCheck) { + bool ExperimentalExtensionVersionCheck, + bool IgnoreUnknownExtension) { // RISC-V ISA strings must be lowercase. if (llvm::any_of(Arch, isupper)) { return createStringError(errc::invalid_argument, @@ -544,9 +601,10 @@ "standard user-level extension not given in canonical order '%c'", C); } - - return createStringError(errc::invalid_argument, - "invalid standard user-level extension '%c'", C); + if (!IgnoreUnknownExtension) + return createStringError(errc::invalid_argument, + "invalid standard user-level extension '%c'", + C); } // Move to next char to prevent repeated letter. @@ -558,18 +616,23 @@ Next = std::string(std::next(I), E); if (auto E = getExtensionVersion(std::string(1, C), Next, Major, Minor, ConsumeLength, EnableExperimentalExtension, - ExperimentalExtensionVersionCheck)) - 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.find(C) == StringRef::npos) - return createStringError(errc::invalid_argument, - "unsupported standard user-level extension '%c'", - C); - ISAInfo->addExtension(std::string(1, C), Major, Minor); + ExperimentalExtensionVersionCheck)) { + if (IgnoreUnknownExtension) + consumeError(std::move(E)); + else + return std::move(E); + } else { + // 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.find(C) != StringRef::npos) + ISAInfo->addExtension(std::string(1, C), Major, Minor); + else if (!IgnoreUnknownExtension) + return createStringError( + errc::invalid_argument, + "unsupported standard user-level extension '%c'", C); + } // Consume full extension name and version, including any optional '_' // between this extension and the next @@ -724,10 +787,9 @@ for (auto &Ext : Exts) { auto I = llvm::lower_bound(ImpliedExts, Ext.first); if (I != std::end(ImpliedExts) && I->Name == Ext.first) { - for (auto &ImpliedExt : I->Exts) { - auto Version = findDefaultVersion(ImpliedExt); - addExtension(ImpliedExt, Version->Major, Version->Minor); - } + for (auto &ImpliedExt : I->Exts) + addExtension(ImpliedExt, Ext.second.Version.Major, + Ext.second.Version.Minor); } } } @@ -752,7 +814,7 @@ StringRef ExtName = Ext.first; auto ExtInfo = Ext.second; Arch << LS << ExtName; - Arch << ExtInfo.MajorVersion << "p" << ExtInfo.MinorVersion; + Arch << ExtInfo.Version.Major << "p" << ExtInfo.Version.Minor; } return Arch.str(); Index: llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp =================================================================== --- llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -2153,9 +2153,10 @@ } auto &ISAInfo = *ParseResult; - for (auto Feature : RISCVFeatureKV) - if (ISAInfo->hasExtension(Feature.Key)) + for (auto Feature : RISCVFeatureKV) { + if (ISAInfo->hasExtensionWithVersion(Feature.Key)) setFeatureBits(Feature.Value, Feature.Key); + } if (ISAInfo->getXLen() == 32) clearFeatureBits(RISCV::Feature64Bit, "64bit"); Index: llvm/lib/Target/RISCV/RISCV.td =================================================================== --- llvm/lib/Target/RISCV/RISCV.td +++ llvm/lib/Target/RISCV/RISCV.td @@ -13,28 +13,28 @@ //===----------------------------------------------------------------------===// def FeatureStdExtM - : SubtargetFeature<"m", "HasStdExtM", "true", + : SubtargetFeature<"m", "StdExtM", "RISCVExtensionVersion{2, 0}", "'M' (Integer Multiplication and Division)">; def HasStdExtM : Predicate<"Subtarget->hasStdExtM()">, AssemblerPredicate<(all_of FeatureStdExtM), "'M' (Integer Multiplication and Division)">; def FeatureStdExtA - : SubtargetFeature<"a", "HasStdExtA", "true", + : SubtargetFeature<"a", "StdExtA", "RISCVExtensionVersion{2, 0}", "'A' (Atomic Instructions)">; def HasStdExtA : Predicate<"Subtarget->hasStdExtA()">, AssemblerPredicate<(all_of FeatureStdExtA), "'A' (Atomic Instructions)">; def FeatureStdExtF - : SubtargetFeature<"f", "HasStdExtF", "true", + : SubtargetFeature<"f", "StdExtF", "RISCVExtensionVersion{2, 0}", "'F' (Single-Precision Floating-Point)">; def HasStdExtF : Predicate<"Subtarget->hasStdExtF()">, AssemblerPredicate<(all_of FeatureStdExtF), "'F' (Single-Precision Floating-Point)">; def FeatureStdExtD - : SubtargetFeature<"d", "HasStdExtD", "true", + : SubtargetFeature<"d", "StdExtD", "RISCVExtensionVersion{2, 0}", "'D' (Double-Precision Floating-Point)", [FeatureStdExtF]>; def HasStdExtD : Predicate<"Subtarget->hasStdExtD()">, @@ -42,7 +42,8 @@ "'D' (Double-Precision Floating-Point)">; def FeatureStdExtZfhmin - : SubtargetFeature<"experimental-zfhmin", "HasStdExtZfhmin", "true", + : SubtargetFeature<"experimental-zfhmin", "StdExtZfhmin", + "RISCVExtensionVersion{0, 1}", "'Zfhmin' (Half-Precision Floating-Point Minimal)", [FeatureStdExtF]>; def HasStdExtZfhmin : Predicate<"Subtarget->hasStdExtZfhmin()">, @@ -50,7 +51,8 @@ "'Zfhmin' (Half-Precision Floating-Point Minimal)">; def FeatureStdExtZfh - : SubtargetFeature<"experimental-zfh", "HasStdExtZfh", "true", + : SubtargetFeature<"experimental-zfh", "StdExtZfh", + "RISCVExtensionVersion{0, 1}", "'Zfh' (Half-Precision Floating-Point)", [FeatureStdExtZfhmin, FeatureStdExtF]>; def HasStdExtZfh : Predicate<"Subtarget->hasStdExtZfh()">, @@ -58,14 +60,15 @@ "'Zfh' (Half-Precision Floating-Point)">; def FeatureStdExtC - : SubtargetFeature<"c", "HasStdExtC", "true", + : SubtargetFeature<"c", "StdExtC", "RISCVExtensionVersion{2, 0}", "'C' (Compressed Instructions)">; def HasStdExtC : Predicate<"Subtarget->hasStdExtC()">, AssemblerPredicate<(all_of FeatureStdExtC), "'C' (Compressed Instructions)">; def FeatureStdExtZba - : SubtargetFeature<"experimental-zba", "HasStdExtZba", "true", + : SubtargetFeature<"experimental-zba", "StdExtZba", + "RISCVExtensionVersion{1, 0}", "'Zba' (Address calculation 'B' Instructions)">; def HasStdExtZba : Predicate<"Subtarget->hasStdExtZba()">, AssemblerPredicate<(all_of FeatureStdExtZba), @@ -73,63 +76,72 @@ def NotHasStdExtZba : Predicate<"!Subtarget->hasStdExtZba()">; def FeatureStdExtZbb - : SubtargetFeature<"experimental-zbb", "HasStdExtZbb", "true", + : SubtargetFeature<"experimental-zbb", "StdExtZbb", + "RISCVExtensionVersion{1, 0}", "'Zbb' (Base 'B' Instructions)">; def HasStdExtZbb : Predicate<"Subtarget->hasStdExtZbb()">, AssemblerPredicate<(all_of FeatureStdExtZbb), "'Zbb' (Base 'B' Instructions)">; def FeatureStdExtZbc - : SubtargetFeature<"experimental-zbc", "HasStdExtZbc", "true", + : SubtargetFeature<"experimental-zbc", "StdExtZbc", + "RISCVExtensionVersion{1, 0}", "'Zbc' (Carry-Less 'B' Instructions)">; def HasStdExtZbc : Predicate<"Subtarget->hasStdExtZbc()">, AssemblerPredicate<(all_of FeatureStdExtZbc), "'Zbc' (Carry-Less 'B' Instructions)">; def FeatureStdExtZbe - : SubtargetFeature<"experimental-zbe", "HasStdExtZbe", "true", + : SubtargetFeature<"experimental-zbe", "StdExtZbe", + "RISCVExtensionVersion{0, 93}", "'Zbe' (Extract-Deposit 'B' Instructions)">; def HasStdExtZbe : Predicate<"Subtarget->hasStdExtZbe()">, AssemblerPredicate<(all_of FeatureStdExtZbe), "'Zbe' (Extract-Deposit 'B' Instructions)">; def FeatureStdExtZbf - : SubtargetFeature<"experimental-zbf", "HasStdExtZbf", "true", + : SubtargetFeature<"experimental-zbf", "StdExtZbf", + "RISCVExtensionVersion{0, 93}", "'Zbf' (Bit-Field 'B' Instructions)">; def HasStdExtZbf : Predicate<"Subtarget->hasStdExtZbf()">, AssemblerPredicate<(all_of FeatureStdExtZbf), "'Zbf' (Bit-Field 'B' Instructions)">; def FeatureStdExtZbm - : SubtargetFeature<"experimental-zbm", "HasStdExtZbm", "true", + : SubtargetFeature<"experimental-zbm", "StdExtZbm", + "RISCVExtensionVersion{0, 93}", "'Zbm' (Matrix 'B' Instructions)">; def HasStdExtZbm : Predicate<"Subtarget->hasStdExtZbm()">, AssemblerPredicate<(all_of FeatureStdExtZbm), "'Zbm' (Matrix 'B' Instructions)">; def FeatureStdExtZbp - : SubtargetFeature<"experimental-zbp", "HasStdExtZbp", "true", + : SubtargetFeature<"experimental-zbp", "StdExtZbp", + "RISCVExtensionVersion{0, 93}", "'Zbp' (Permutation 'B' Instructions)">; def HasStdExtZbp : Predicate<"Subtarget->hasStdExtZbp()">, AssemblerPredicate<(all_of FeatureStdExtZbp), "'Zbp' (Permutation 'B' Instructions)">; def FeatureStdExtZbr - : SubtargetFeature<"experimental-zbr", "HasStdExtZbr", "true", + : SubtargetFeature<"experimental-zbr", "StdExtZbr", + "RISCVExtensionVersion{0, 93}", "'Zbr' (Polynomial Reduction 'B' Instructions)">; def HasStdExtZbr : Predicate<"Subtarget->hasStdExtZbr()">, AssemblerPredicate<(all_of FeatureStdExtZbr), "'Zbr' (Polynomial Reduction 'B' Instructions)">; def FeatureStdExtZbs - : SubtargetFeature<"experimental-zbs", "HasStdExtZbs", "true", + : SubtargetFeature<"experimental-zbs", "StdExtZbs", + "RISCVExtensionVersion{1, 0}", "'Zbs' (Single-Bit 'B' Instructions)">; def HasStdExtZbs : Predicate<"Subtarget->hasStdExtZbs()">, AssemblerPredicate<(all_of FeatureStdExtZbs), "'Zbs' (Single-Bit 'B' Instructions)">; def FeatureStdExtZbt - : SubtargetFeature<"experimental-zbt", "HasStdExtZbt", "true", + : SubtargetFeature<"experimental-zbt", "StdExtZbt", + "RISCVExtensionVersion{0, 93}", "'Zbt' (Ternary 'B' Instructions)">; def HasStdExtZbt : Predicate<"Subtarget->hasStdExtZbt()">, AssemblerPredicate<(all_of FeatureStdExtZbt), @@ -151,22 +163,26 @@ "RVC Hint Instructions">; def FeatureStdExtV - : SubtargetFeature<"experimental-v", "HasStdExtV", "true", + : SubtargetFeature<"experimental-v", "StdExtV", + "RISCVExtensionVersion{0, 10}", "'V' (Vector Instructions)">; -def HasStdExtV : Predicate<"Subtarget->hasStdExtV()">, - AssemblerPredicate<(all_of FeatureStdExtV), - "'V' (Vector Instructions)">; +def HasStdExtV + : Predicate<"Subtarget->hasStdExtV()">, + AssemblerPredicate<(all_of FeatureStdExtV), + "'V' (Vector Instructions)">; def HasVInstructions : Predicate<"Subtarget->hasVInstructions()">; def HasVInstructionsAnyF : Predicate<"Subtarget->hasVInstructionsAnyF()">; def FeatureStdExtZvlsseg - : SubtargetFeature<"experimental-zvlsseg", "HasStdExtZvlsseg", "true", + : SubtargetFeature<"experimental-zvlsseg", "StdExtZvlsseg", + "RISCVExtensionVersion{0, 10}", "'Zvlsseg' (Vector segment load/store instructions)", [FeatureStdExtV]>; -def HasStdExtZvlsseg : Predicate<"Subtarget->hasStdExtZvlsseg()">, - AssemblerPredicate<(all_of FeatureStdExtZvlsseg), - "'Zvlsseg' (Vector segment load/store instructions)">; +def HasStdExtZvlsseg + : Predicate<"Subtarget->hasStdExtZvlsseg()">, + AssemblerPredicate<(all_of FeatureStdExtZvlsseg), + "'Zvlsseg' (Vector segment load/store instructions)">; def Feature64Bit : SubtargetFeature<"64bit", "HasRV64", "true", "Implements RV64">; @@ -181,7 +197,7 @@ def RV64 : HwMode<"+64bit">; def FeatureRV32E - : SubtargetFeature<"e", "IsRV32E", "true", + : SubtargetFeature<"e", "StdExtE", "RISCVExtensionVersion{1, 9}", "Implements RV32E (provides 16 rather than 32 GPRs)">; def IsRV32E : Predicate<"Subtarget->isRV32E()">, AssemblerPredicate<(all_of FeatureRV32E)>; Index: llvm/lib/Target/RISCV/RISCVSubtarget.h =================================================================== --- llvm/lib/Target/RISCV/RISCVSubtarget.h +++ llvm/lib/Target/RISCV/RISCVSubtarget.h @@ -24,6 +24,7 @@ #include "llvm/CodeGen/SelectionDAGTargetInfo.h" #include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/IR/DataLayout.h" +#include "llvm/Support/RISCVISAInfo.h" #include "llvm/Target/TargetMachine.h" #define GET_SUBTARGETINFO_HEADER @@ -34,27 +35,28 @@ class RISCVSubtarget : public RISCVGenSubtargetInfo { virtual void anchor(); - bool HasStdExtM = false; - bool HasStdExtA = false; - bool HasStdExtF = false; - bool HasStdExtD = false; - bool HasStdExtC = false; - bool HasStdExtZba = false; - bool HasStdExtZbb = false; - bool HasStdExtZbc = false; - bool HasStdExtZbe = false; - bool HasStdExtZbf = false; - bool HasStdExtZbm = false; - bool HasStdExtZbp = false; - bool HasStdExtZbr = false; - bool HasStdExtZbs = false; - bool HasStdExtZbt = false; - bool HasStdExtV = false; - bool HasStdExtZvlsseg = false; - bool HasStdExtZfhmin = false; - bool HasStdExtZfh = false; + RISCVExtensionVersion StdExtM; + RISCVExtensionVersion StdExtA; + RISCVExtensionVersion StdExtF; + RISCVExtensionVersion StdExtD; + RISCVExtensionVersion StdExtC; + RISCVExtensionVersion StdExtZba; + RISCVExtensionVersion StdExtZbb; + RISCVExtensionVersion StdExtZbc; + RISCVExtensionVersion StdExtZbe; + RISCVExtensionVersion StdExtZbf; + RISCVExtensionVersion StdExtZbm; + RISCVExtensionVersion StdExtZbp; + RISCVExtensionVersion StdExtZbr; + RISCVExtensionVersion StdExtZbs; + RISCVExtensionVersion StdExtZbt; + RISCVExtensionVersion StdExtV; + RISCVExtensionVersion StdExtZvlsseg; + RISCVExtensionVersion StdExtZvamo; + RISCVExtensionVersion StdExtZfhmin; + RISCVExtensionVersion StdExtZfh; + RISCVExtensionVersion StdExtE; bool HasRV64 = false; - bool IsRV32E = false; bool EnableLinkerRelax = false; bool EnableRVCHintInstrs = true; bool EnableSaveRestore = false; @@ -100,27 +102,27 @@ return &TSInfo; } bool enableMachineScheduler() const override { return true; } - bool hasStdExtM() const { return HasStdExtM; } - bool hasStdExtA() const { return HasStdExtA; } - bool hasStdExtF() const { return HasStdExtF; } - bool hasStdExtD() const { return HasStdExtD; } - bool hasStdExtC() const { return HasStdExtC; } - bool hasStdExtZba() const { return HasStdExtZba; } - bool hasStdExtZbb() const { return HasStdExtZbb; } - bool hasStdExtZbc() const { return HasStdExtZbc; } - bool hasStdExtZbe() const { return HasStdExtZbe; } - bool hasStdExtZbf() const { return HasStdExtZbf; } - bool hasStdExtZbm() const { return HasStdExtZbm; } - bool hasStdExtZbp() const { return HasStdExtZbp; } - bool hasStdExtZbr() const { return HasStdExtZbr; } - bool hasStdExtZbs() const { return HasStdExtZbs; } - bool hasStdExtZbt() const { return HasStdExtZbt; } - bool hasStdExtV() const { return HasStdExtV; } - bool hasStdExtZvlsseg() const { return HasStdExtZvlsseg; } - bool hasStdExtZfhmin() const { return HasStdExtZfhmin; } - bool hasStdExtZfh() const { return HasStdExtZfh; } + bool hasStdExtM() const { return StdExtM; } + bool hasStdExtA() const { return StdExtA; } + bool hasStdExtF() const { return StdExtF; } + bool hasStdExtD() const { return StdExtD; } + bool hasStdExtC() const { return StdExtC; } + bool hasStdExtZba() const { return StdExtZba; } + bool hasStdExtZbb() const { return StdExtZbb; } + bool hasStdExtZbc() const { return StdExtZbc; } + bool hasStdExtZbe() const { return StdExtZbe; } + bool hasStdExtZbf() const { return StdExtZbf; } + bool hasStdExtZbm() const { return StdExtZbm; } + bool hasStdExtZbp() const { return StdExtZbp; } + bool hasStdExtZbr() const { return StdExtZbr; } + bool hasStdExtZbs() const { return StdExtZbs; } + bool hasStdExtZbt() const { return StdExtZbt; } + bool hasStdExtV() const { return StdExtV; } + bool hasStdExtZvlsseg() const { return StdExtZvlsseg; } + bool hasStdExtZfhmin() const { return StdExtZfhmin; } + bool hasStdExtZfh() const { return StdExtZfh; } bool is64Bit() const { return HasRV64; } - bool isRV32E() const { return IsRV32E; } + bool isRV32E() const { return StdExtE; } bool enableLinkerRelax() const { return EnableLinkerRelax; } bool enableRVCHintInstrs() const { return EnableRVCHintInstrs; } bool enableSaveRestore() const { return EnableSaveRestore; } @@ -133,11 +135,11 @@ } // Vector codegen related methods. - bool hasVInstructions() const { return HasStdExtV; } - bool hasVInstructionsI64() const { return HasStdExtV; } - bool hasVInstructionsF16() const { return HasStdExtV && hasStdExtZfh(); } - bool hasVInstructionsF32() const { return HasStdExtV && hasStdExtF(); } - bool hasVInstructionsF64() const { return HasStdExtV && hasStdExtD(); } + bool hasVInstructions() const { return StdExtV; } + bool hasVInstructionsI64() const { return StdExtV; } + bool hasVInstructionsF16() const { return StdExtV && hasStdExtZfh(); } + bool hasVInstructionsF32() const { return StdExtV && hasStdExtF(); } + bool hasVInstructionsF64() const { return StdExtV && hasStdExtD(); } // F16 and F64 both require F32. bool hasVInstructionsAnyF() const { return hasVInstructionsF32(); } unsigned getMaxInterleaveFactor() const { Index: llvm/test/CodeGen/RISCV/attributes-version.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/RISCV/attributes-version.ll @@ -0,0 +1,81 @@ +; Generate ELF attributes from llc. + +; RUN: llc -mtriple=riscv32 -mattr=+m %s -o - | FileCheck --check-prefix=RV32M %s +; RUN: llc -mtriple=riscv32 -mattr=+a %s -o - | FileCheck --check-prefix=RV32A %s +; RUN: llc -mtriple=riscv32 -mattr=+f %s -o - | FileCheck --check-prefix=RV32F %s +; RUN: llc -mtriple=riscv32 -mattr=+d %s -o - | FileCheck --check-prefix=RV32D %s +; RUN: llc -mtriple=riscv32 -mattr=+c %s -o - | FileCheck --check-prefix=RV32C %s +; RUN: llc -mtriple=riscv32 -mattr=+experimental-zfhmin %s -o - | FileCheck --check-prefix=RV32ZFHMIN %s +; RUN: llc -mtriple=riscv32 -mattr=+experimental-zfh %s -o - | FileCheck --check-prefix=RV32ZFH %s +; RUN: llc -mtriple=riscv32 -mattr=+experimental-zba %s -o - | FileCheck --check-prefix=RV32ZBA %s +; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbb %s -o - | FileCheck --check-prefix=RV32ZBB %s +; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbc %s -o - | FileCheck --check-prefix=RV32ZBC %s +; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbe %s -o - | FileCheck --check-prefix=RV32ZBE %s +; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbf %s -o - | FileCheck --check-prefix=RV32ZBF %s +; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbm %s -o - | FileCheck --check-prefix=RV32ZBM %s +; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbp %s -o - | FileCheck --check-prefix=RV32ZBP %s +; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbr %s -o - | FileCheck --check-prefix=RV32ZBR %s +; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbs %s -o - | FileCheck --check-prefix=RV32ZBS %s +; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbt %s -o - | FileCheck --check-prefix=RV32ZBT %s + + +; RV32M: .attribute 5, "rv32i2p0_m2p0" +; RV32A: .attribute 5, "rv32i2p0_a2p0" +; RV32F: .attribute 5, "rv32i2p0_f2p0" +; RV32D: .attribute 5, "rv32i2p0_f2p0_d2p0" +; RV32C: .attribute 5, "rv32i2p0_c2p0" +; RV32V: .attribute 5, "rv32i2p0_v0p10_zvlsseg0p10" +; RV32ZFHMIN: .attribute 5, "rv32i2p0_f2p0_zfhmin0p1" +; RV32ZFH: .attribute 5, "rv32i2p0_f2p0_zfh0p1_zfhmin0p1" +; RV32ZBA: .attribute 5, "rv32i2p0_zba1p0" +; RV32ZBB: .attribute 5, "rv32i2p0_zbb1p0" +; RV32ZBC: .attribute 5, "rv32i2p0_zbc1p0" +; RV32ZBE: .attribute 5, "rv32i2p0_zbe0p93" +; RV32ZBF: .attribute 5, "rv32i2p0_zbf0p93" +; RV32ZBM: .attribute 5, "rv32i2p0_zbm0p93" +; RV32ZBP: .attribute 5, "rv32i2p0_zbp0p93" +; RV32ZBR: .attribute 5, "rv32i2p0_zbr0p93" +; RV32ZBS: .attribute 5, "rv32i2p0_zbs1p0" +; RV32ZBT: .attribute 5, "rv32i2p0_zbt0p93" + + +; RUN: llc -mtriple=riscv32 -mattr=+m0p7 < %s 2>&1 | FileCheck --check-prefix=RV32M0P7 %s +; RUN: llc -mtriple=riscv32 -mattr=+a0p7 < %s 2>&1 | FileCheck --check-prefix=RV32A0P7 %s +; RUN: llc -mtriple=riscv32 -mattr=+f0p7 < %s 2>&1 | FileCheck --check-prefix=RV32F0P7 %s +; RUN: llc -mtriple=riscv32 -mattr=+d0p7 < %s 2>&1 | FileCheck --check-prefix=RV32D0P7 %s +; RUN: llc -mtriple=riscv32 -mattr=+c0p7 < %s 2>&1 | FileCheck --check-prefix=RV32C0P7 %s +; RUN: llc -mtriple=riscv32 -mattr=+experimental-zfhmin0p7 < %s 2>&1 | FileCheck --check-prefix=RV32ZFHMIN0P7 %s +; RUN: llc -mtriple=riscv32 -mattr=+experimental-zfh0p7 < %s 2>&1 | FileCheck --check-prefix=RV32ZFH0P7 %s +; RUN: llc -mtriple=riscv32 -mattr=+experimental-zba0p7 < %s 2>&1 | FileCheck --check-prefix=RV32ZBA0P7 %s +; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbb0p7 < %s 2>&1 | FileCheck --check-prefix=RV32ZBB0P7 %s +; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbc0p7 < %s 2>&1 | FileCheck --check-prefix=RV32ZBC0P7 %s +; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbe0p7 < %s 2>&1 | FileCheck --check-prefix=RV32ZBE0P7 %s +; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbf0p7 < %s 2>&1 | FileCheck --check-prefix=RV32ZBF0P7 %s +; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbm0p7 < %s 2>&1 | FileCheck --check-prefix=RV32ZBM0P7 %s +; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbp0p7 < %s 2>&1 | FileCheck --check-prefix=RV32ZBP0P7 %s +; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbr0p7 < %s 2>&1 | FileCheck --check-prefix=RV32ZBR0P7 %s +; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbs0p7 < %s 2>&1 | FileCheck --check-prefix=RV32ZBS0P7 %s +; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbt0p7 < %s 2>&1 | FileCheck --check-prefix=RV32ZBT0P7 %s + +; RV32M0P7: '+m0p7' is not a recognized feature for this target +; RV32A0P7: '+a0p7' is not a recognized feature for this target +; RV32F0P7: '+f0p7' is not a recognized feature for this target +; RV32D0P7: '+d0p7' is not a recognized feature for this target +; RV32C0P7: '+c0p7' is not a recognized feature for this target +; RV32ZFHMIN0P7: '+experimental-zfhmin0p7' is not a recognized feature for this target +; RV32ZFH0P7: '+experimental-zfh0p7' is not a recognized feature for this target +; RV32ZBA0P7: '+experimental-zba0p7' is not a recognized feature for this target +; RV32ZBB0P7: '+experimental-zbb0p7' is not a recognized feature for this target +; RV32ZBC0P7: '+experimental-zbc0p7' is not a recognized feature for this target +; RV32ZBE0P7: '+experimental-zbe0p7' is not a recognized feature for this target +; RV32ZBF0P7: '+experimental-zbf0p7' is not a recognized feature for this target +; RV32ZBM0P7: '+experimental-zbm0p7' is not a recognized feature for this target +; RV32ZBP0P7: '+experimental-zbp0p7' is not a recognized feature for this target +; RV32ZBR0P7: '+experimental-zbr0p7' is not a recognized feature for this target +; RV32ZBS0P7: '+experimental-zbs0p7' is not a recognized feature for this target +; RV32ZBT0P7: '+experimental-zbt0p7' is not a recognized feature for this target + +define i32 @addi(i32 %a) { + %1 = add i32 %a, 1 + ret i32 %1 +} Index: llvm/test/tools/llvm-objdump/ELF/RISCV/unknown-arch-attr.test =================================================================== --- llvm/test/tools/llvm-objdump/ELF/RISCV/unknown-arch-attr.test +++ llvm/test/tools/llvm-objdump/ELF/RISCV/unknown-arch-attr.test @@ -3,7 +3,7 @@ ## The expected behavior is to ignore the unrecognized arch feature and ## continue to process the following arch features. ## -## The object file has the "rv32i2p0_x1p0_m2p0" arch feature. "x1p0" is an +## The object file has the "rv32i2p0_y1p0_m2p0" arch feature. "y1p0" is an ## unrecognized architecture extension. llvm-objdump will ignore it and decode ## "mul" instruction correctly according to "m2p0" in the arch feature. ## @@ -34,5 +34,5 @@ Content: 3385C502 - Name: .riscv.attributes Type: SHT_RISCV_ATTRIBUTES -## The content is the encoding of the arch feature "rv32i2p0_x1p0_m2p0" - Content: 412300000072697363760001190000000572763332693270305F783170305F6D32703000 +## The content is the encoding of the arch feature "rv32i2p0_y1p0_m2p0" + Content: 412300000072697363760001190000000572763332693270305F793170305F6D32703000