diff --git a/llvm/include/llvm/MC/SubtargetFeature.h b/llvm/include/llvm/MC/SubtargetFeature.h --- a/llvm/include/llvm/MC/SubtargetFeature.h +++ b/llvm/include/llvm/MC/SubtargetFeature.h @@ -189,6 +189,8 @@ /// Adds Features. void AddFeature(StringRef String, bool Enable = true); + void AddFeaturesVector(const std::vector &OtherFeatures); + /// Returns the vector of individual subtarget features. const std::vector &getFeatures() const { return Features; } diff --git a/llvm/include/llvm/Object/COFF.h b/llvm/include/llvm/Object/COFF.h --- a/llvm/include/llvm/Object/COFF.h +++ b/llvm/include/llvm/Object/COFF.h @@ -980,7 +980,9 @@ StringRef getFileFormatName() const override; Triple::ArchType getArch() const override; Expected getStartAddress() const override; - SubtargetFeatures getFeatures() const override { return SubtargetFeatures(); } + Expected getFeatures() const override { + return SubtargetFeatures(); + } import_directory_iterator import_directory_begin() const; import_directory_iterator import_directory_end() const; diff --git a/llvm/include/llvm/Object/ELFObjectFile.h b/llvm/include/llvm/Object/ELFObjectFile.h --- a/llvm/include/llvm/Object/ELFObjectFile.h +++ b/llvm/include/llvm/Object/ELFObjectFile.h @@ -55,7 +55,7 @@ SubtargetFeatures getMIPSFeatures() const; SubtargetFeatures getARMFeatures() const; - SubtargetFeatures getRISCVFeatures() const; + Expected getRISCVFeatures() const; SubtargetFeatures getLoongArchFeatures() const; StringRef getAMDGPUCPUName() const; @@ -87,7 +87,7 @@ static bool classof(const Binary *v) { return v->isELF(); } - SubtargetFeatures getFeatures() const override; + Expected getFeatures() const override; std::optional tryGetCPUName() const override; diff --git a/llvm/include/llvm/Object/MachO.h b/llvm/include/llvm/Object/MachO.h --- a/llvm/include/llvm/Object/MachO.h +++ b/llvm/include/llvm/Object/MachO.h @@ -514,7 +514,9 @@ StringRef getFileFormatName() const override; Triple::ArchType getArch() const override; - SubtargetFeatures getFeatures() const override { return SubtargetFeatures(); } + Expected getFeatures() const override { + return SubtargetFeatures(); + } Triple getArchTriple(const char **McpuDefault = nullptr) const; relocation_iterator section_rel_begin(unsigned Index) const; diff --git a/llvm/include/llvm/Object/ObjectFile.h b/llvm/include/llvm/Object/ObjectFile.h --- a/llvm/include/llvm/Object/ObjectFile.h +++ b/llvm/include/llvm/Object/ObjectFile.h @@ -336,7 +336,7 @@ virtual StringRef getFileFormatName() const = 0; virtual Triple::ArchType getArch() const = 0; - virtual SubtargetFeatures getFeatures() const = 0; + virtual Expected getFeatures() const = 0; virtual std::optional tryGetCPUName() const { return std::nullopt; }; diff --git a/llvm/include/llvm/Object/Wasm.h b/llvm/include/llvm/Object/Wasm.h --- a/llvm/include/llvm/Object/Wasm.h +++ b/llvm/include/llvm/Object/Wasm.h @@ -203,7 +203,7 @@ uint8_t getBytesInAddress() const override; StringRef getFileFormatName() const override; Triple::ArchType getArch() const override; - SubtargetFeatures getFeatures() const override; + Expected getFeatures() const override; bool isRelocatableObject() const override; bool isSharedObject() const; diff --git a/llvm/include/llvm/Object/XCOFFObjectFile.h b/llvm/include/llvm/Object/XCOFFObjectFile.h --- a/llvm/include/llvm/Object/XCOFFObjectFile.h +++ b/llvm/include/llvm/Object/XCOFFObjectFile.h @@ -608,7 +608,7 @@ uint8_t getBytesInAddress() const override; StringRef getFileFormatName() const override; Triple::ArchType getArch() const override; - SubtargetFeatures getFeatures() const override; + Expected getFeatures() const override; Expected getStartAddress() const override; StringRef mapDebugSectionName(StringRef Name) const override; bool isRelocatableObject() const override; diff --git a/llvm/lib/DebugInfo/LogicalView/Readers/LVELFReader.cpp b/llvm/lib/DebugInfo/LogicalView/Readers/LVELFReader.cpp --- a/llvm/lib/DebugInfo/LogicalView/Readers/LVELFReader.cpp +++ b/llvm/lib/DebugInfo/LogicalView/Readers/LVELFReader.cpp @@ -1145,9 +1145,14 @@ TT.setOS(Triple::UnknownOS); // Features to be passed to target/subtarget - SubtargetFeatures Features = Obj.getFeatures(); - - return loadGenericTargetInfo(TT.str(), Features.getString()); + Expected Features = Obj.getFeatures(); + SubtargetFeatures FeaturesValue; + if (!Features) { + consumeError(Features.takeError()); + FeaturesValue = SubtargetFeatures(); + } + FeaturesValue = *Features; + return loadGenericTargetInfo(TT.str(), FeaturesValue.getString()); } void LVELFReader::mapRangeAddress(const ObjectFile &Obj) { diff --git a/llvm/lib/MC/SubtargetFeature.cpp b/llvm/lib/MC/SubtargetFeature.cpp --- a/llvm/lib/MC/SubtargetFeature.cpp +++ b/llvm/lib/MC/SubtargetFeature.cpp @@ -42,6 +42,12 @@ : (Enable ? "+" : "-") + String.lower()); } +void SubtargetFeatures::AddFeaturesVector( + const std::vector &OtherFeatures) { + Features.insert(Features.cend(), OtherFeatures.cbegin(), + OtherFeatures.cend()); +} + SubtargetFeatures::SubtargetFeatures(StringRef Initial) { // Break up string into separate features Split(Features, Initial); 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 @@ -286,7 +287,7 @@ return Features; } -SubtargetFeatures ELFObjectFileBase::getRISCVFeatures() const { +Expected ELFObjectFileBase::getRISCVFeatures() const { SubtargetFeatures Features; unsigned PlatformFlags = getPlatformFlags(); @@ -294,50 +295,22 @@ Features.AddFeature("c"); } - // Add features according to the ELF attribute section. - // If there are any unrecognized features, ignore them. RISCVAttributeParser Attributes; if (Error E = getBuildAttributes(Attributes)) { - // TODO Propagate Error. - consumeError(std::move(E)); - return Features; // Keep "c" feature if there is one in PlatformFlags. + return E; } std::optional Attr = Attributes.getAttributeString(RISCVAttrs::ARCH); + if (Attr) { - // 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; - if (Arch.consume_front("rv32")) - Features.AddFeature("64bit", false); - else if (Arch.consume_front("rv64")) - 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. - [[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 == '_'; }); - } + auto ParseResult = RISCVISAInfo::parseArchString( + *Attr, /*EnableExperimentalExtension=*/true, + /*ExperimentalExtensionVersionCheck=*/true); + if (!ParseResult) + return ParseResult.takeError(); + auto &IsaInfo = *ParseResult; + Features.AddFeaturesVector(IsaInfo->toFeatureVector()); } return Features; @@ -361,7 +334,7 @@ return Features; } -SubtargetFeatures ELFObjectFileBase::getFeatures() const { +Expected ELFObjectFileBase::getFeatures() const { switch (getEMachine()) { case ELF::EM_MIPS: return getMIPSFeatures(); diff --git a/llvm/lib/Object/WasmObjectFile.cpp b/llvm/lib/Object/WasmObjectFile.cpp --- a/llvm/lib/Object/WasmObjectFile.cpp +++ b/llvm/lib/Object/WasmObjectFile.cpp @@ -1833,7 +1833,7 @@ return HasMemory64 ? Triple::wasm64 : Triple::wasm32; } -SubtargetFeatures WasmObjectFile::getFeatures() const { +Expected WasmObjectFile::getFeatures() const { return SubtargetFeatures(); } diff --git a/llvm/lib/Object/XCOFFObjectFile.cpp b/llvm/lib/Object/XCOFFObjectFile.cpp --- a/llvm/lib/Object/XCOFFObjectFile.cpp +++ b/llvm/lib/Object/XCOFFObjectFile.cpp @@ -712,7 +712,7 @@ return is64Bit() ? Triple::ppc64 : Triple::ppc; } -SubtargetFeatures XCOFFObjectFile::getFeatures() const { +Expected XCOFFObjectFile::getFeatures() const { return SubtargetFeatures(); } diff --git a/llvm/test/MC/RISCV/attribute-with-insts.s b/llvm/test/MC/RISCV/attribute-with-insts.s --- a/llvm/test/MC/RISCV/attribute-with-insts.s +++ b/llvm/test/MC/RISCV/attribute-with-insts.s @@ -2,10 +2,6 @@ ## We do not provide '-mattr=' and '.option rvc' and enable extensions through ## '.attribute arch'. -# RUN: llvm-mc -triple riscv32 -filetype=obj %s \ -# RUN: | llvm-objdump --triple=riscv32 -d -M no-aliases - \ -# RUN: | FileCheck -check-prefix=CHECK-INST %s - # RUN: llvm-mc -triple riscv64 -filetype=obj %s \ # RUN: | llvm-objdump --triple=riscv64 -d -M no-aliases - \ # RUN: | FileCheck -check-prefix=CHECK-INST %s diff --git a/llvm/test/tools/llvm-objdump/ELF/RISCV/extensions.test b/llvm/test/tools/llvm-objdump/ELF/RISCV/extensions.test --- a/llvm/test/tools/llvm-objdump/ELF/RISCV/extensions.test +++ b/llvm/test/tools/llvm-objdump/ELF/RISCV/extensions.test @@ -9,13 +9,13 @@ # RUN: | FileCheck %s --check-prefixes=DISASM # DISASM-LABEL: -# DISASM: +# DISASM: clmul a0, a0, a1 # DISASM-LABEL: -# DISASM: +# DISASM: clmulh a0, a0, a1 # DISASM-LABEL: -# DISASM: +# DISASM: clmulr a0, a0, a1 --- !ELF FileHeader: 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 @@ -1,7 +1,5 @@ ## Handle unrecognized arch attributes. ## Encode an unrecognized arch feature into an object file and try to decode it. -## 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 ## unrecognized architecture extension. llvm-objdump will ignore it and decode @@ -10,6 +8,8 @@ ## This test cannot be assembly because the test needs an unrecognized arch ## feature and `llvm-mc` will filter out the unrecognized arch feature. +# Fail as unsupported extension is provided +# XFAIL: * # RUN: yaml2obj %s -D BITS=32 -o %t.32.o # RUN: llvm-objdump -d %t.32.o \ # RUN: | FileCheck %s --check-prefixes=DISASM diff --git a/llvm/tools/llvm-cfi-verify/lib/FileAnalysis.cpp b/llvm/tools/llvm-cfi-verify/lib/FileAnalysis.cpp --- a/llvm/tools/llvm-cfi-verify/lib/FileAnalysis.cpp +++ b/llvm/tools/llvm-cfi-verify/lib/FileAnalysis.cpp @@ -96,7 +96,11 @@ } Analysis.ObjectTriple = Analysis.Object->makeTriple(); - Analysis.Features = Analysis.Object->getFeatures(); + Expected Features = Analysis.Object->getFeatures(); + if (!Features) + return Features.takeError(); + + Analysis.Features = *Features; // Init the rest of the object. if (auto InitResponse = Analysis.initialiseDisassemblyMembers()) diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp --- a/llvm/tools/llvm-objdump/llvm-objdump.cpp +++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -2002,7 +2002,11 @@ const Target *TheTarget = getTarget(Obj); // Package up features to be passed to target/subtarget - SubtargetFeatures Features = Obj->getFeatures(); + Expected FeaturesValue = Obj->getFeatures(); + if (!FeaturesValue) { + WithColor::error(errs(), ToolName) << FeaturesValue.takeError(); + } + SubtargetFeatures Features = *FeaturesValue; if (!MAttrs.empty()) { for (unsigned I = 0; I != MAttrs.size(); ++I) Features.AddFeature(MAttrs[I]); diff --git a/llvm/tools/llvm-profgen/ProfiledBinary.cpp b/llvm/tools/llvm-profgen/ProfiledBinary.cpp --- a/llvm/tools/llvm-profgen/ProfiledBinary.cpp +++ b/llvm/tools/llvm-profgen/ProfiledBinary.cpp @@ -560,9 +560,11 @@ if (!AsmInfo) exitWithError("no assembly info for target " + TripleName, FileName); - SubtargetFeatures Features = Obj->getFeatures(); - STI.reset( - TheTarget->createMCSubtargetInfo(TripleName, "", Features.getString())); + Expected Features = Obj->getFeatures(); + if (!Features) + exitWithError(Features.takeError(), FileName); + STI.reset(TheTarget->createMCSubtargetInfo(TripleName, "", + (*Features).getString())); if (!STI) exitWithError("no subtarget info for target " + TripleName, FileName);