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 @@ -45,7 +45,8 @@ /// Parse RISCV ISA info from arch string. static llvm::Expected> parseArchString(StringRef Arch, bool EnableExperimentalExtension, - bool ExperimentalExtensionVersionCheck = true); + bool ExperimentalExtensionVersionCheck = true, + bool IgnoreUnknown = false); /// Parse RISCV ISA info from feature vector. static llvm::Expected> diff --git a/llvm/lib/Object/ELFObjectFile.cpp b/llvm/lib/Object/ELFObjectFile.cpp --- a/llvm/lib/Object/ELFObjectFile.cpp +++ b/llvm/lib/Object/ELFObjectFile.cpp @@ -25,6 +25,7 @@ #include "llvm/Support/MathExtras.h" #include "llvm/Support/RISCVAttributeParser.h" #include "llvm/Support/RISCVAttributes.h" +#include "llvm/Support/RISCVISAInfo.h" #include #include #include @@ -304,38 +305,29 @@ Optional Attr = Attributes.getAttributeString(RISCVAttrs::ARCH); if (Attr.hasValue()) { - // 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")) + // Suppress version checking for experimental extensions to prevent erroring + // when getting any unknown version. + auto ParseResult = RISCVISAInfo::parseArchString( + *Attr, /*EnableExperimentalExtension=*/true, + /*ExperimentalExtensionVersionCheck=*/false, + /*IgnoreUnknown=*/true); + if (!ParseResult) { + // TODO: Propagate Error. + consumeError(ParseResult.takeError()); + return Features; + } + std::unique_ptr &ISAInfo = *ParseResult; + + if (ISAInfo->getXLen() == 32) Features.AddFeature("64bit", false); - else if (Arch.consume_front("rv64")) + else if (ISAInfo->getXLen() == 64) Features.AddFeature("64bit"); + else + llvm_unreachable("XLEN should be 32 or 64."); - 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 == '_'; }); - } + std::vector FeatureVector = ISAInfo->toFeatureVector(); + for (const std::string &Feature : FeatureVector) + Features.AddFeature(StringRef(Feature)); } return Features; 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 @@ -474,7 +474,8 @@ llvm::Expected> 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, @@ -589,19 +590,27 @@ 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)); + goto ParseStdExtFail; + } 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)) + if (!isSupportedExtension(StringRef(&C, 1))) { + if (IgnoreUnknown) + goto ParseStdExtFail; return createStringError(errc::invalid_argument, "unsupported standard user-level extension '%c'", C); + } ISAInfo->addExtension(std::string(1, C), Major, Minor); + ParseStdExtFail: // Consume full extension name and version, including any optional '_' // between this extension and the next ++I; @@ -641,20 +650,28 @@ 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()) { + if (IgnoreUnknown) + continue; return createStringError(errc::invalid_argument, "%s name missing after '%s'", Desc.str().c_str(), Type.str().c_str()); @@ -663,13 +680,21 @@ 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)) { + if (IgnoreUnknown) + continue; 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. diff --git a/llvm/test/tools/llvm-objdump/ELF/RISCV/objdump.s b/llvm/test/tools/llvm-objdump/ELF/RISCV/objdump.s new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-objdump/ELF/RISCV/objdump.s @@ -0,0 +1,8 @@ +# RUN: llvm-mc -filetype=obj -triple riscv64 < %s | \ +# RUN: llvm-objdump -d -M no-aliases - | \ +# RUN: FileCheck %s + .attribute 5, "rv64gcv" +# CHECK-LABEL: : +foo: +# CHECK: vsetvli a3, a2, e8, m8, tu, mu + vsetvli a3, a2, e8, m8, tu, mu diff --git a/llvm/test/tools/llvm-objdump/ELF/RISCV/unknown-arch-attr.test b/llvm/test/tools/llvm-objdump/ELF/RISCV/unknown-arch-attr.test --- a/llvm/test/tools/llvm-objdump/ELF/RISCV/unknown-arch-attr.test +++ b/llvm/test/tools/llvm-objdump/ELF/RISCV/unknown-arch-attr.test @@ -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_m2p0_x1p0" + Content: 412300000072697363760001190000000572763332693270305F6D3270305F7831703000