[clang] [llvm] [Hexagon] ELF attributes for Hexagon (PR #85359)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Mar 14 21:06:21 PDT 2024
https://github.com/quic-areg created https://github.com/llvm/llvm-project/pull/85359
Defines a subset of attributes and emits them to a section called .hexagon.attributes.
The current attributes recorded are the attributes needed by llvm-objdump to automatically determine target features and eliminate the need to manually pass features.
>From b035993b477160d9ac6ef01c8d27e6681682f251 Mon Sep 17 00:00:00 2001
From: quic-areg <aregmi at quicinc.com>
Date: Thu, 14 Mar 2024 20:31:37 -0700
Subject: [PATCH] [Hexagon] ELF attributes for Hexagon
Defines a subset of attributes and emits them to a section called
.hexagon.attributes.
The current attributes recorded are the attributes needed by
llvm-objdump to automatically determine target features and eliminate
the need to manually pass features.
---
clang/lib/Driver/ToolChains/Clang.cpp | 8 ++
.../Driver/hexagon-default-build-attributes.s | 20 ++++
llvm/include/llvm/BinaryFormat/ELF.h | 2 +
llvm/include/llvm/Object/ELFObjectFile.h | 4 +-
.../llvm/Support/HexagonAttributeParser.h | 36 +++++++
llvm/include/llvm/Support/HexagonAttributes.h | 32 +++++++
llvm/lib/Object/ELF.cpp | 5 +-
llvm/lib/Object/ELFObjectFile.cpp | 78 +++++++++++++++
llvm/lib/ObjectYAML/ELFYAML.cpp | 1 +
llvm/lib/Support/CMakeLists.txt | 2 +
llvm/lib/Support/HexagonAttributeParser.cpp | 55 +++++++++++
llvm/lib/Support/HexagonAttributes.cpp | 27 ++++++
.../Hexagon/AsmParser/HexagonAsmParser.cpp | 63 ++++++++++++-
llvm/lib/Target/Hexagon/HexagonAsmPrinter.cpp | 20 ++++
llvm/lib/Target/Hexagon/HexagonAsmPrinter.h | 4 +
.../Target/Hexagon/HexagonTargetStreamer.h | 9 ++
.../MCTargetDesc/HexagonMCELFStreamer.cpp | 61 ++++++++++++
.../MCTargetDesc/HexagonMCTargetDesc.cpp | 72 ++++++++++++--
.../MCTargetDesc/HexagonMCTargetDesc.h | 6 +-
llvm/test/CodeGen/Hexagon/build-attributes.ll | 16 ++++
.../test/MC/Hexagon/directive-attribute-err.s | 24 +++++
llvm/test/MC/Hexagon/directive-attribute.s | 41 ++++++++
llvm/test/MC/Hexagon/hexagon_attributes.s | 94 +++++++++++++++++++
llvm/tools/llvm-readobj/ELFDumper.cpp | 6 ++
24 files changed, 676 insertions(+), 10 deletions(-)
create mode 100644 clang/test/Driver/hexagon-default-build-attributes.s
create mode 100644 llvm/include/llvm/Support/HexagonAttributeParser.h
create mode 100644 llvm/include/llvm/Support/HexagonAttributes.h
create mode 100644 llvm/lib/Support/HexagonAttributeParser.cpp
create mode 100644 llvm/lib/Support/HexagonAttributes.cpp
create mode 100644 llvm/test/CodeGen/Hexagon/build-attributes.ll
create mode 100644 llvm/test/MC/Hexagon/directive-attribute-err.s
create mode 100644 llvm/test/MC/Hexagon/directive-attribute.s
create mode 100644 llvm/test/MC/Hexagon/hexagon_attributes.s
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 3a7a1cf99c79ac..5628a6cd002b82 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -8477,6 +8477,14 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
case llvm::Triple::riscv64:
AddRISCVTargetArgs(Args, CmdArgs);
break;
+
+ case llvm::Triple::hexagon:
+ if (Args.hasFlag(options::OPT_mdefault_build_attributes,
+ options::OPT_mno_default_build_attributes, true)) {
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back("-hexagon-add-build-attributes");
+ }
+ break;
}
// Consume all the warning flags. Usually this would be handled more
diff --git a/clang/test/Driver/hexagon-default-build-attributes.s b/clang/test/Driver/hexagon-default-build-attributes.s
new file mode 100644
index 00000000000000..b83181d6d52e01
--- /dev/null
+++ b/clang/test/Driver/hexagon-default-build-attributes.s
@@ -0,0 +1,20 @@
+/// Enabled by default for assembly
+// RUN: %clang -target hexagon-unknown-elf -### %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-ENABLED
+
+/// Can be forced on or off for assembly.
+// RUN: %clang -target hexagon-unknown-elf -### %s 2>&1 -mno-default-build-attributes \
+// RUN: | FileCheck %s -check-prefix CHECK-DISABLED
+// RUN: %clang -target hexagon-unknown-elf -### %s 2>&1 -mdefault-build-attributes \
+// RUN: | FileCheck %s -check-prefix CHECK-ENABLED
+
+/// Option ignored C/C++ (since we always emit hardware and ABI build attributes
+/// during codegen).
+// RUN: %clang -target hexagon-unknown-elf -### -x c %s -mdefault-build-attributes 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-DISABLED
+// RUN: %clang -target hexagon-unknown-elf -### -x c++ %s -mdefault-build-attributes 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-DISABLED
+
+// CHECK-DISABLED-NOT: "-hexagon-add-build-attributes"
+// CHECK-ENABLED: "-hexagon-add-build-attributes"
+// expected-warning {{argument unused during compilation: '-mno-default-build-attributes'}}
diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h
index bace3a92677a82..877f3f7862c8ba 100644
--- a/llvm/include/llvm/BinaryFormat/ELF.h
+++ b/llvm/include/llvm/BinaryFormat/ELF.h
@@ -1141,6 +1141,8 @@ enum : unsigned {
SHT_CSKY_ATTRIBUTES = 0x70000001U,
+ SHT_HEXAGON_ATTRIBUTES = 0x70000003U,
+
SHT_HIPROC = 0x7fffffff, // Highest processor arch-specific type.
SHT_LOUSER = 0x80000000, // Lowest type reserved for applications.
SHT_HIUSER = 0xffffffff // Highest type reserved for applications.
diff --git a/llvm/include/llvm/Object/ELFObjectFile.h b/llvm/include/llvm/Object/ELFObjectFile.h
index c9227da65708cc..7d04d8f8d54bf8 100644
--- a/llvm/include/llvm/Object/ELFObjectFile.h
+++ b/llvm/include/llvm/Object/ELFObjectFile.h
@@ -60,6 +60,7 @@ class ELFObjectFileBase : public ObjectFile {
SubtargetFeatures getMIPSFeatures() const;
SubtargetFeatures getARMFeatures() const;
+ SubtargetFeatures getHexagonFeatures() const;
Expected<SubtargetFeatures> getRISCVFeatures() const;
SubtargetFeatures getLoongArchFeatures() const;
@@ -395,7 +396,8 @@ template <class ELFT> class ELFObjectFile : public ELFObjectFileBase {
for (const Elf_Shdr &Sec : *SectionsOrErr) {
if (Sec.sh_type == ELF::SHT_ARM_ATTRIBUTES ||
- Sec.sh_type == ELF::SHT_RISCV_ATTRIBUTES) {
+ Sec.sh_type == ELF::SHT_RISCV_ATTRIBUTES ||
+ Sec.sh_type == ELF::SHT_HEXAGON_ATTRIBUTES) {
auto ErrorOrContents = EF.getSectionContents(Sec);
if (!ErrorOrContents)
return ErrorOrContents.takeError();
diff --git a/llvm/include/llvm/Support/HexagonAttributeParser.h b/llvm/include/llvm/Support/HexagonAttributeParser.h
new file mode 100644
index 00000000000000..c7d866af08f5f7
--- /dev/null
+++ b/llvm/include/llvm/Support/HexagonAttributeParser.h
@@ -0,0 +1,36 @@
+//===-- HexagonAttributeParser.h - Hexagon Attribute 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.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_HEXAGONATTRIBUTEPARSER_H
+#define LLVM_SUPPORT_HEXAGONATTRIBUTEPARSER_H
+
+#include "llvm/Support/ELFAttributeParser.h"
+#include "llvm/Support/HexagonAttributes.h"
+
+namespace llvm {
+class HexagonAttributeParser : public ELFAttributeParser {
+ struct DisplayHandler {
+ HexagonAttrs::AttrType Attribute;
+ Error (HexagonAttributeParser::*Routine)(unsigned);
+ };
+
+ static const DisplayHandler DisplayRoutines[];
+
+ Error handler(uint64_t Tag, bool &Handled) override;
+
+public:
+ HexagonAttributeParser(ScopedPrinter *SP)
+ : ELFAttributeParser(SP, HexagonAttrs::getHexagonAttributeTags(),
+ "hexagon") {}
+ HexagonAttributeParser()
+ : ELFAttributeParser(HexagonAttrs::getHexagonAttributeTags(), "hexagon") {}
+};
+
+} // namespace llvm
+
+#endif
diff --git a/llvm/include/llvm/Support/HexagonAttributes.h b/llvm/include/llvm/Support/HexagonAttributes.h
new file mode 100644
index 00000000000000..8a50d8993e633b
--- /dev/null
+++ b/llvm/include/llvm/Support/HexagonAttributes.h
@@ -0,0 +1,32 @@
+//===-- HexagonAttributes.h - Qualcomm Hexagon Attributes -----------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_HEXAGONATTRIBUTES_H
+#define LLVM_SUPPORT_HEXAGONATTRIBUTES_H
+
+#include "llvm/Support/ELFAttributes.h"
+
+namespace llvm {
+namespace HexagonAttrs {
+
+const TagNameMap &getHexagonAttributeTags();
+
+enum AttrType : unsigned {
+ ARCH = 4,
+ HVXARCH = 5,
+ HVXIEEEFP = 6,
+ HVXQFLOAT = 7,
+ ZREG = 8,
+ AUDIO = 9,
+ CABAC = 10
+};
+
+} // namespace HexagonAttrs
+} // namespace llvm
+
+#endif
diff --git a/llvm/lib/Object/ELF.cpp b/llvm/lib/Object/ELF.cpp
index 137f606dd2d46b..55dd0c8e06c092 100644
--- a/llvm/lib/Object/ELF.cpp
+++ b/llvm/lib/Object/ELF.cpp
@@ -251,7 +251,10 @@ StringRef llvm::object::getELFSectionTypeName(uint32_t Machine, unsigned Type) {
}
break;
case ELF::EM_HEXAGON:
- switch (Type) { STRINGIFY_ENUM_CASE(ELF, SHT_HEX_ORDERED); }
+ switch (Type) {
+ STRINGIFY_ENUM_CASE(ELF, SHT_HEX_ORDERED);
+ STRINGIFY_ENUM_CASE(ELF, SHT_HEXAGON_ATTRIBUTES);
+ }
break;
case ELF::EM_X86_64:
switch (Type) { STRINGIFY_ENUM_CASE(ELF, SHT_X86_64_UNWIND); }
diff --git a/llvm/lib/Object/ELFObjectFile.cpp b/llvm/lib/Object/ELFObjectFile.cpp
index 33be48196ae7d2..efec612957de33 100644
--- a/llvm/lib/Object/ELFObjectFile.cpp
+++ b/llvm/lib/Object/ELFObjectFile.cpp
@@ -20,6 +20,7 @@
#include "llvm/Support/ARMAttributeParser.h"
#include "llvm/Support/ARMBuildAttributes.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/HexagonAttributeParser.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/RISCVAttributeParser.h"
#include "llvm/Support/RISCVAttributes.h"
@@ -287,6 +288,81 @@ SubtargetFeatures ELFObjectFileBase::getARMFeatures() const {
return Features;
}
+static std::optional<std::string> hexagonAttrToFeatureString(unsigned Attr) {
+ switch (Attr) {
+ case 5:
+ return "v5";
+ case 55:
+ return "v55";
+ case 60:
+ return "v60";
+ case 62:
+ return "v62";
+ case 65:
+ return "v65";
+ case 67:
+ return "v67";
+ case 68:
+ return "v68";
+ case 69:
+ return "v69";
+ case 71:
+ return "v71";
+ case 73:
+ return "v73";
+ default:
+ return {};
+ }
+}
+
+SubtargetFeatures ELFObjectFileBase::getHexagonFeatures() const {
+ SubtargetFeatures Features;
+ HexagonAttributeParser Parser;
+ if (Error E = getBuildAttributes(Parser)) {
+ // Return no attributes if none can be read.
+ // This behavior is important for backwards compatibility.
+ consumeError(std::move(E));
+ return Features;
+ }
+ std::optional<unsigned> Attr;
+
+ if ((Attr = Parser.getAttributeValue(HexagonAttrs::ARCH))) {
+ if (std::optional<std::string> FeatureString =
+ hexagonAttrToFeatureString(*Attr))
+ Features.AddFeature(*FeatureString);
+ }
+
+ if ((Attr = Parser.getAttributeValue(HexagonAttrs::HVXARCH))) {
+ std::optional<std::string> FeatureString =
+ hexagonAttrToFeatureString(*Attr);
+ // There is no corresponding hvx arch for v5 and v55.
+ if (FeatureString && *Attr >= 60)
+ Features.AddFeature("hvx" + *FeatureString);
+ }
+
+ if ((Attr = Parser.getAttributeValue(HexagonAttrs::HVXIEEEFP)))
+ if (*Attr)
+ Features.AddFeature("hvx-ieee-fp");
+
+ if ((Attr = Parser.getAttributeValue(HexagonAttrs::HVXQFLOAT)))
+ if (*Attr)
+ Features.AddFeature("hvx-qfloat");
+
+ if ((Attr = Parser.getAttributeValue(HexagonAttrs::ZREG)))
+ if (*Attr)
+ Features.AddFeature("zreg");
+
+ if ((Attr = Parser.getAttributeValue(HexagonAttrs::AUDIO)))
+ if (*Attr)
+ Features.AddFeature("audio");
+
+ if ((Attr = Parser.getAttributeValue(HexagonAttrs::CABAC)))
+ if (*Attr)
+ Features.AddFeature("cabac");
+
+ return Features;
+}
+
Expected<SubtargetFeatures> ELFObjectFileBase::getRISCVFeatures() const {
SubtargetFeatures Features;
unsigned PlatformFlags = getPlatformFlags();
@@ -349,6 +425,8 @@ Expected<SubtargetFeatures> ELFObjectFileBase::getFeatures() const {
return getRISCVFeatures();
case ELF::EM_LOONGARCH:
return getLoongArchFeatures();
+ case ELF::EM_HEXAGON:
+ return getHexagonFeatures();
default:
return SubtargetFeatures();
}
diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp
index 9c1a28db592a1c..045211c44b9079 100644
--- a/llvm/lib/ObjectYAML/ELFYAML.cpp
+++ b/llvm/lib/ObjectYAML/ELFYAML.cpp
@@ -716,6 +716,7 @@ void ScalarEnumerationTraits<ELFYAML::ELF_SHT>::enumeration(
break;
case ELF::EM_HEXAGON:
ECase(SHT_HEX_ORDERED);
+ ECase(SHT_HEXAGON_ATTRIBUTES);
break;
case ELF::EM_X86_64:
ECase(SHT_X86_64_UNWIND);
diff --git a/llvm/lib/Support/CMakeLists.txt b/llvm/lib/Support/CMakeLists.txt
index b9c13c43e9a7c5..da2a4b4cdec568 100644
--- a/llvm/lib/Support/CMakeLists.txt
+++ b/llvm/lib/Support/CMakeLists.txt
@@ -188,6 +188,8 @@ add_llvm_component_library(LLVMSupport
GlobPattern.cpp
GraphWriter.cpp
Hashing.cpp
+ HexagonAttributeParser.cpp
+ HexagonAttributes.cpp
InitLLVM.cpp
InstructionCost.cpp
IntEqClasses.cpp
diff --git a/llvm/lib/Support/HexagonAttributeParser.cpp b/llvm/lib/Support/HexagonAttributeParser.cpp
new file mode 100644
index 00000000000000..2143162d11c79c
--- /dev/null
+++ b/llvm/lib/Support/HexagonAttributeParser.cpp
@@ -0,0 +1,55 @@
+//===-- HexagonAttributeParser.cpp - Hexagon Attribute Parser -------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/HexagonAttributeParser.h"
+
+using namespace llvm;
+
+const HexagonAttributeParser::DisplayHandler
+ HexagonAttributeParser::DisplayRoutines[] = {
+ {
+ HexagonAttrs::ARCH,
+ &ELFAttributeParser::integerAttribute,
+ },
+ {
+ HexagonAttrs::HVXARCH,
+ &ELFAttributeParser::integerAttribute,
+ },
+ {
+ HexagonAttrs::HVXIEEEFP,
+ &ELFAttributeParser::integerAttribute,
+ },
+ {
+ HexagonAttrs::HVXQFLOAT,
+ &ELFAttributeParser::integerAttribute,
+ },
+ {
+ HexagonAttrs::ZREG,
+ &ELFAttributeParser::integerAttribute,
+ },
+ {
+ HexagonAttrs::AUDIO,
+ &ELFAttributeParser::integerAttribute,
+ },
+ {
+ HexagonAttrs::CABAC,
+ &ELFAttributeParser::integerAttribute,
+ }};
+
+Error HexagonAttributeParser::handler(uint64_t Tag, bool &Handled) {
+ Handled = false;
+ for (const auto &R : DisplayRoutines) {
+ if (uint64_t(R.Attribute) == Tag) {
+ if (Error E = (this->*R.Routine)(Tag))
+ return E;
+ Handled = true;
+ break;
+ }
+ }
+ return Error::success();
+}
diff --git a/llvm/lib/Support/HexagonAttributes.cpp b/llvm/lib/Support/HexagonAttributes.cpp
new file mode 100644
index 00000000000000..165215c8fb676a
--- /dev/null
+++ b/llvm/lib/Support/HexagonAttributes.cpp
@@ -0,0 +1,27 @@
+//===-- HexagonAttributes.cpp - Qualcomm Hexagon Attributes ---------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/HexagonAttributes.h"
+
+using namespace llvm;
+using namespace llvm::HexagonAttrs;
+
+static constexpr TagNameItem TagData[] = {
+ {ARCH, "Tag_arch"},
+ {HVXARCH, "Tag_hvx_arch"},
+ {HVXIEEEFP, "Tag_hvx_ieeefp"},
+ {HVXQFLOAT, "Tag_hvx_qfloat"},
+ {ZREG, "Tag_zreg"},
+ {AUDIO, "Tag_audio"},
+ {CABAC, "Tag_cabac"},
+};
+
+constexpr TagNameMap HexagonAttributeTags{TagData};
+const TagNameMap &llvm::HexagonAttrs::getHexagonAttributeTags() {
+ return HexagonAttributeTags;
+}
diff --git a/llvm/lib/Target/Hexagon/AsmParser/HexagonAsmParser.cpp b/llvm/lib/Target/Hexagon/AsmParser/HexagonAsmParser.cpp
index fd7d25fa16d1da..d6d4a96b0d302f 100644
--- a/llvm/lib/Target/Hexagon/AsmParser/HexagonAsmParser.cpp
+++ b/llvm/lib/Target/Hexagon/AsmParser/HexagonAsmParser.cpp
@@ -43,6 +43,7 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
+#include "llvm/Support/HexagonAttributes.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/SMLoc.h"
#include "llvm/Support/SourceMgr.h"
@@ -79,7 +80,8 @@ static cl::opt<bool> ErrorNoncontigiousRegister(
"merror-noncontigious-register",
cl::desc("Error for register names that aren't contigious"),
cl::init(false));
-
+static cl::opt<bool> AddBuildAttributes("hexagon-add-build-attributes",
+ cl::init(false));
namespace {
struct HexagonOperand;
@@ -120,6 +122,9 @@ class HexagonAsmParser : public MCTargetAsmParser {
SMLoc &EndLoc) override;
bool ParseDirectiveSubsection(SMLoc L);
bool ParseDirectiveComm(bool IsLocal, SMLoc L);
+
+ bool parseDirectiveAttribute(SMLoc L);
+
bool RegisterMatchesArch(unsigned MatchNum) const;
bool matchBundleOptions();
@@ -164,6 +169,9 @@ class HexagonAsmParser : public MCTargetAsmParser {
Parser.addAliasForDirective(".word", ".4byte");
MCAsmParserExtension::Initialize(_Parser);
+
+ if (AddBuildAttributes)
+ getTargetStreamer().emitTargetAttributes(*STI);
}
bool splitIdentifier(OperandVector &Operands);
@@ -652,6 +660,57 @@ bool HexagonAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
return finishBundle(IDLoc, Out);
return false;
}
+/// parseDirectiveAttribute
+/// ::= .attribute int, int
+/// ::= .attribute Tag_name, int
+bool HexagonAsmParser::parseDirectiveAttribute(SMLoc L) {
+ MCAsmParser &Parser = getParser();
+ int64_t Tag;
+ SMLoc TagLoc = Parser.getTok().getLoc();
+ if (Parser.getTok().is(AsmToken::Identifier)) {
+ StringRef Name = Parser.getTok().getIdentifier();
+ std::optional<unsigned> Ret = ELFAttrs::attrTypeFromString(
+ Name, HexagonAttrs::getHexagonAttributeTags());
+ if (!Ret)
+ return Error(TagLoc, "attribute name not recognized: " + Name);
+ Tag = *Ret;
+ Parser.Lex();
+ } else {
+ const MCExpr *AttrExpr;
+
+ TagLoc = Parser.getTok().getLoc();
+ if (Parser.parseExpression(AttrExpr))
+ return true;
+
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(AttrExpr);
+ if (check(!CE, TagLoc, "expected numeric constant"))
+ return true;
+
+ Tag = CE->getValue();
+ }
+
+ if (Parser.parseComma())
+ return true;
+
+ // We currently only have integer values.
+ int64_t IntegerValue = 0;
+ SMLoc ValueExprLoc = Parser.getTok().getLoc();
+ const MCExpr *ValueExpr;
+ if (Parser.parseExpression(ValueExpr))
+ return true;
+
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ValueExpr);
+ if (!CE)
+ return Error(ValueExprLoc, "expected numeric constant");
+ IntegerValue = CE->getValue();
+
+ if (Parser.parseEOL())
+ return true;
+
+ getTargetStreamer().emitAttribute(Tag, IntegerValue);
+
+ return false;
+}
/// ParseDirective parses the Hexagon specific directives
bool HexagonAsmParser::ParseDirective(AsmToken DirectiveID) {
@@ -664,6 +723,8 @@ bool HexagonAsmParser::ParseDirective(AsmToken DirectiveID) {
return ParseDirectiveComm(false, DirectiveID.getLoc());
if (IDVal.lower() == ".subsection")
return ParseDirectiveSubsection(DirectiveID.getLoc());
+ if (IDVal == ".attribute")
+ return parseDirectiveAttribute(DirectiveID.getLoc());
return true;
}
diff --git a/llvm/lib/Target/Hexagon/HexagonAsmPrinter.cpp b/llvm/lib/Target/Hexagon/HexagonAsmPrinter.cpp
index 4ee67cb05d4953..d2f64ac9e90b0b 100644
--- a/llvm/lib/Target/Hexagon/HexagonAsmPrinter.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonAsmPrinter.cpp
@@ -17,6 +17,7 @@
#include "HexagonInstrInfo.h"
#include "HexagonRegisterInfo.h"
#include "HexagonSubtarget.h"
+#include "HexagonTargetStreamer.h"
#include "MCTargetDesc/HexagonInstPrinter.h"
#include "MCTargetDesc/HexagonMCExpr.h"
#include "MCTargetDesc/HexagonMCInstrInfo.h"
@@ -46,6 +47,7 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Target/TargetMachine.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
@@ -775,6 +777,24 @@ void HexagonAsmPrinter::emitInstruction(const MachineInstr *MI) {
OutStreamer->emitInstruction(MCB, getSubtargetInfo());
}
+void HexagonAsmPrinter::emitStartOfAsmFile(Module &M) {
+ if (TM.getTargetTriple().isOSBinFormatELF())
+ emitAttributes();
+}
+
+void HexagonAsmPrinter::emitEndOfAsmFile(Module &M) {
+ HexagonTargetStreamer &HTS =
+ static_cast<HexagonTargetStreamer &>(*OutStreamer->getTargetStreamer());
+ if (TM.getTargetTriple().isOSBinFormatELF())
+ HTS.finishAttributeSection();
+}
+
+void HexagonAsmPrinter::emitAttributes() {
+ HexagonTargetStreamer &HTS =
+ static_cast<HexagonTargetStreamer &>(*OutStreamer->getTargetStreamer());
+ HTS.emitTargetAttributes(*TM.getMCSubtargetInfo());
+}
+
void HexagonAsmPrinter::EmitSled(const MachineInstr &MI, SledKind Kind) {
static const int8_t NoopsInSledCount = 4;
// We want to emit the following pattern:
diff --git a/llvm/lib/Target/Hexagon/HexagonAsmPrinter.h b/llvm/lib/Target/Hexagon/HexagonAsmPrinter.h
index 5cb1edf54d1a76..b555c885965036 100644
--- a/llvm/lib/Target/Hexagon/HexagonAsmPrinter.h
+++ b/llvm/lib/Target/Hexagon/HexagonAsmPrinter.h
@@ -29,6 +29,8 @@ class TargetMachine;
class HexagonAsmPrinter : public AsmPrinter {
const HexagonSubtarget *Subtarget = nullptr;
+ void emitAttributes();
+
public:
explicit HexagonAsmPrinter(TargetMachine &TM,
std::unique_ptr<MCStreamer> Streamer)
@@ -68,6 +70,8 @@ class TargetMachine;
const char *ExtraCode, raw_ostream &OS) override;
bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
const char *ExtraCode, raw_ostream &OS) override;
+ void emitStartOfAsmFile(Module &M) override;
+ void emitEndOfAsmFile(Module &M) override;
};
} // end namespace llvm
diff --git a/llvm/lib/Target/Hexagon/HexagonTargetStreamer.h b/llvm/lib/Target/Hexagon/HexagonTargetStreamer.h
index ff84363106629f..a2f93d476bfe1b 100644
--- a/llvm/lib/Target/Hexagon/HexagonTargetStreamer.h
+++ b/llvm/lib/Target/Hexagon/HexagonTargetStreamer.h
@@ -24,6 +24,15 @@ class HexagonTargetStreamer : public MCTargetStreamer {
virtual void emitLocalCommonSymbolSorted(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlign,
unsigned AccessGranularity){};
+ void finish() override {}
+
+ virtual void finishAttributeSection() {}
+
+ virtual void emitAttribute(unsigned Attribute, unsigned Value) {}
+
+ void emitTargetAttributes(const MCSubtargetInfo &STI);
+
+ virtual void reset() {}
};
}
diff --git a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCELFStreamer.cpp b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCELFStreamer.cpp
index d1678fa0241ca8..22c82bf5ac1b40 100644
--- a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCELFStreamer.cpp
+++ b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCELFStreamer.cpp
@@ -12,6 +12,8 @@
//===----------------------------------------------------------------------===//
#include "MCTargetDesc/HexagonMCELFStreamer.h"
+#include "HexagonTargetStreamer.h"
+#include "MCTargetDesc/HexagonMCChecker.h"
#include "MCTargetDesc/HexagonMCInstrInfo.h"
#include "MCTargetDesc/HexagonMCShuffler.h"
#include "llvm/ADT/StringRef.h"
@@ -27,11 +29,13 @@
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCSymbolELF.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/HexagonAttributes.h"
#include "llvm/Support/MathExtras.h"
#include <cassert>
#include <cstdint>
@@ -147,6 +151,63 @@ void HexagonMCELFStreamer::HexagonMCEmitLocalCommonSymbol(MCSymbol *Symbol,
HexagonMCEmitCommonSymbol(Symbol, Size, ByteAlignment, AccessSize);
}
+static unsigned featureToArchVersion(unsigned Feature) {
+ switch (Feature) {
+ case Hexagon::ArchV5:
+ return 5;
+ case Hexagon::ArchV55:
+ return 55;
+ case Hexagon::ArchV60:
+ case Hexagon::ExtensionHVXV60:
+ return 60;
+ case Hexagon::ArchV62:
+ case Hexagon::ExtensionHVXV62:
+ return 62;
+ case Hexagon::ArchV65:
+ case Hexagon::ExtensionHVXV65:
+ return 65;
+ case Hexagon::ArchV66:
+ case Hexagon::ExtensionHVXV66:
+ return 66;
+ case Hexagon::ArchV67:
+ case Hexagon::ExtensionHVXV67:
+ return 67;
+ case Hexagon::ArchV68:
+ case Hexagon::ExtensionHVXV68:
+ return 68;
+ case Hexagon::ArchV69:
+ case Hexagon::ExtensionHVXV69:
+ return 69;
+ case Hexagon::ArchV71:
+ case Hexagon::ExtensionHVXV71:
+ return 71;
+ case Hexagon::ArchV73:
+ case Hexagon::ExtensionHVXV73:
+ return 73;
+ }
+ llvm_unreachable("Expected valid arch feature");
+ return 0;
+}
+
+void HexagonTargetStreamer::emitTargetAttributes(const MCSubtargetInfo &STI) {
+ auto Features = STI.getFeatureBits();
+ unsigned Arch = featureToArchVersion(Hexagon_MC::getArchVersion(Features));
+ std::optional<unsigned> HVXArch = Hexagon_MC::getHVXVersion(Features);
+ emitAttribute(HexagonAttrs::ARCH, Arch);
+ if (HVXArch)
+ emitAttribute(HexagonAttrs::HVXARCH, featureToArchVersion(*HVXArch));
+ if (Features.test(Hexagon::ExtensionHVXIEEEFP))
+ emitAttribute(HexagonAttrs::HVXIEEEFP, 1);
+ if (Features.test(Hexagon::ExtensionHVXQFloat))
+ emitAttribute(HexagonAttrs::HVXQFLOAT, 1);
+ if (Features.test(Hexagon::ExtensionZReg))
+ emitAttribute(HexagonAttrs::ZREG, 1);
+ if (Features.test(Hexagon::ExtensionAudio))
+ emitAttribute(HexagonAttrs::AUDIO, 1);
+ if (Features.test(Hexagon::FeatureCabac))
+ emitAttribute(HexagonAttrs::CABAC, 1);
+}
+
namespace llvm {
MCStreamer *createHexagonELFStreamer(Triple const &TT, MCContext &Context,
std::unique_ptr<MCAsmBackend> MAB,
diff --git a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp
index 0740ac58a33813..dc8328a6705da8 100644
--- a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp
+++ b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp
@@ -35,6 +35,7 @@
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/HexagonAttributes.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <cstdint>
@@ -224,12 +225,13 @@ bool isSlot0Only(unsigned units) {
namespace {
class HexagonTargetAsmStreamer : public HexagonTargetStreamer {
+ formatted_raw_ostream &OS;
+ bool IsVerboseAsm;
+
public:
- HexagonTargetAsmStreamer(MCStreamer &S,
- formatted_raw_ostream &OS,
- bool isVerboseAsm,
- MCInstPrinter &IP)
- : HexagonTargetStreamer(S) {}
+ HexagonTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS,
+ bool IsVerboseAsm, MCInstPrinter &IP)
+ : HexagonTargetStreamer(S), OS(OS), IsVerboseAsm(IsVerboseAsm) {}
void prettyPrintAsm(MCInstPrinter &InstPrinter, uint64_t Address,
const MCInst &Inst, const MCSubtargetInfo &STI,
@@ -266,6 +268,21 @@ class HexagonTargetAsmStreamer : public HexagonTargetStreamer {
else
OS << "\t}" << PacketBundle.second;
}
+
+ void finish() override { finishAttributeSection(); }
+
+ void finishAttributeSection() override {}
+
+ void emitAttribute(unsigned Attribute, unsigned Value) override {
+ OS << "\t.attribute\t" << Attribute << ", " << Twine(Value);
+ if (IsVerboseAsm) {
+ StringRef Name = ELFAttrs::attrTypeAsString(
+ Attribute, HexagonAttrs::getHexagonAttributeTags());
+ if (!Name.empty())
+ OS << "\t// " << Name;
+ }
+ OS << "\n";
+ }
};
class HexagonTargetELFStreamer : public HexagonTargetStreamer {
@@ -279,7 +296,6 @@ class HexagonTargetELFStreamer : public HexagonTargetStreamer {
MCA.setELFHeaderEFlags(Hexagon_MC::GetELFFlags(STI));
}
-
void emitCommonSymbolSorted(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment,
unsigned AccessSize) override {
@@ -297,6 +313,27 @@ class HexagonTargetELFStreamer : public HexagonTargetStreamer {
HexagonELFStreamer.HexagonMCEmitLocalCommonSymbol(
Symbol, Size, Align(ByteAlignment), AccessSize);
}
+
+ void finish() override { finishAttributeSection(); }
+
+ void reset() override { AttributeSection = nullptr; }
+
+private:
+ MCSection *AttributeSection = nullptr;
+
+ void finishAttributeSection() override {
+ MCELFStreamer &S = getStreamer();
+ if (S.Contents.empty())
+ return;
+
+ S.emitAttributesSection("hexagon", ".hexagon.attributes",
+ ELF::SHT_HEXAGON_ATTRIBUTES, AttributeSection);
+ }
+
+ void emitAttribute(uint32_t Attribute, uint32_t Value) override {
+ getStreamer().setAttributeItem(Attribute, Value,
+ /*OverwriteExisting=*/true);
+ }
};
} // end anonymous namespace
@@ -591,6 +628,29 @@ void Hexagon_MC::addArchSubtarget(MCSubtargetInfo const *STI, StringRef FS) {
}
}
+std::optional<unsigned>
+Hexagon_MC::getHVXVersion(const FeatureBitset &Features) {
+ for (auto Arch : {Hexagon::ExtensionHVXV73, Hexagon::ExtensionHVXV71,
+ Hexagon::ExtensionHVXV69, Hexagon::ExtensionHVXV68,
+ Hexagon::ExtensionHVXV67, Hexagon::ExtensionHVXV66,
+ Hexagon::ExtensionHVXV65, Hexagon::ExtensionHVXV62,
+ Hexagon::ExtensionHVXV60})
+ if (Features.test(Arch))
+ return Arch;
+ return {};
+}
+
+unsigned Hexagon_MC::getArchVersion(const FeatureBitset &Features) {
+ for (auto Arch :
+ {Hexagon::ArchV73, Hexagon::ArchV71, Hexagon::ArchV69, Hexagon::ArchV68,
+ Hexagon::ArchV67, Hexagon::ArchV66, Hexagon::ArchV65, Hexagon::ArchV62,
+ Hexagon::ArchV60, Hexagon::ArchV55, Hexagon::ArchV5})
+ if (Features.test(Arch))
+ return Arch;
+ llvm_unreachable("Expected arch v5-v73");
+ return 0;
+}
+
unsigned Hexagon_MC::GetELFFlags(const MCSubtargetInfo &STI) {
return StringSwitch<unsigned>(STI.getCPU())
.Case("generic", llvm::ELF::EF_HEXAGON_MACH_V5)
diff --git a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.h b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.h
index ffb81bca208df1..6110c7a93982ca 100644
--- a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.h
+++ b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.h
@@ -81,7 +81,11 @@ namespace Hexagon_MC {
unsigned GetELFFlags(const MCSubtargetInfo &STI);
llvm::ArrayRef<MCPhysReg> GetVectRegRev();
-}
+
+ std::optional<unsigned> getHVXVersion(const FeatureBitset &Features);
+
+ unsigned getArchVersion(const FeatureBitset &Features);
+ } // namespace Hexagon_MC
MCCodeEmitter *createHexagonMCCodeEmitter(const MCInstrInfo &MCII,
MCContext &MCT);
diff --git a/llvm/test/CodeGen/Hexagon/build-attributes.ll b/llvm/test/CodeGen/Hexagon/build-attributes.ll
new file mode 100644
index 00000000000000..48ee31a4d19bd6
--- /dev/null
+++ b/llvm/test/CodeGen/Hexagon/build-attributes.ll
@@ -0,0 +1,16 @@
+;; Generate build attributes from llc.
+
+; RUN: llc -mtriple=hexagon-unknown-elf \
+; RUN: -mattr=+hvxv73,+cabac,+v71,+hvx-ieee-fp,+hvx-length128b %s -o - | FileCheck %s
+
+; CHECK: .attribute 4, 71 // Tag_arch
+; CHECK-NEXT: .attribute 5, 73 // Tag_hvx_arch
+; CHECK-NEXT: .attribute 6, 1 // Tag_hvx_ieeefp
+; CHECK-NEXT: .attribute 7, 1 // Tag_hvx_qfloat
+; CHECK-NEXT: .attribute 8, 1 // Tag_zreg
+; CHECK-NEXT: .attribute 10, 1 // Tag_cabac
+
+define i32 @addi(i32 %a) {
+ %1 = add i32 %a, 1
+ ret i32 %1
+}
\ No newline at end of file
diff --git a/llvm/test/MC/Hexagon/directive-attribute-err.s b/llvm/test/MC/Hexagon/directive-attribute-err.s
new file mode 100644
index 00000000000000..fc44d1e2b4036b
--- /dev/null
+++ b/llvm/test/MC/Hexagon/directive-attribute-err.s
@@ -0,0 +1,24 @@
+/// attribute parsing error cases.
+
+// RUN: not llvm-mc -triple=hexagon -filetype=asm %s 2>&1 \
+// RUN: | FileCheck %s
+
+ .attribute Tag_unknown_name, 0
+// CHECK: error: attribute name not recognized: Tag_unknown_name
+// CHECK-NEXT: .attribute Tag_unknown_name
+
+ .attribute [non_constant_expression], 0
+// CHECK: error: expected numeric constant
+// CHECK-NEXT: .attribute [non_constant_expression], 0
+
+ .attribute 42, "forty two"
+// CHECK: error: expected numeric constant
+// CHECK-NEXT: .attribute 42, "forty two"
+
+ .attribute Tag_arch, "v75"
+// CHECK: error: expected numeric constant
+// CHECK-NEXT: .attribute Tag_arch, "v75"
+
+ .attribute 0
+// CHECK: :[[#@LINE-1]]:15: error: expected comma
+// CHECK-NEXT: .attribute 0
diff --git a/llvm/test/MC/Hexagon/directive-attribute.s b/llvm/test/MC/Hexagon/directive-attribute.s
new file mode 100644
index 00000000000000..d7c893061e18ab
--- /dev/null
+++ b/llvm/test/MC/Hexagon/directive-attribute.s
@@ -0,0 +1,41 @@
+/// Check .attribute parsing.
+
+// RUN: llvm-mc -triple=hexagon -filetype=obj %s | llvm-readelf -A - | \
+// RUN: FileCheck %s --match-full-lines --implicit-check-not={{.}}
+
+.attribute 4, 71 // Tag_arch
+.attribute Tag_cabac, 1
+.attribute Tag_hvx_arch, 68
+.attribute 7, 1 // Tag_hvx_qfloat
+
+// CHECK: BuildAttributes {
+// CHECK-NEXT: FormatVersion: 0x41
+// CHECK-NEXT: Section 1 {
+// CHECK-NEXT: SectionLength: 25
+// CHECK-NEXT: Vendor: hexagon
+// CHECK-NEXT: Tag: Tag_File (0x1)
+// CHECK-NEXT: Size: 13
+// CHECK-NEXT: FileAttributes {
+// CHECK-NEXT: Attribute {
+// CHECK-NEXT: Tag: 4
+// CHECK-NEXT: TagName: arch
+// CHECK-NEXT: Value: 71
+// CHECK-NEXT: }
+// CHECK-NEXT: Attribute {
+// CHECK-NEXT: Tag: 10
+// CHECK-NEXT: TagName: cabac
+// CHECK-NEXT: Value: 1
+// CHECK-NEXT: }
+// CHECK-NEXT: Attribute {
+// CHECK-NEXT: Tag: 5
+// CHECK-NEXT: TagName: hvx_arch
+// CHECK-NEXT: Value: 68
+// CHECK-NEXT: }
+// CHECK-NEXT: Attribute {
+// CHECK-NEXT: Tag: 7
+// CHECK-NEXT: TagName: hvx_qfloat
+// CHECK-NEXT: Value: 1
+// CHECK-NEXT: }
+// CHECK-NEXT: }
+// CHECK-NEXT: }
+// CHECK-NEXT: }
diff --git a/llvm/test/MC/Hexagon/hexagon_attributes.s b/llvm/test/MC/Hexagon/hexagon_attributes.s
new file mode 100644
index 00000000000000..e90536030d977f
--- /dev/null
+++ b/llvm/test/MC/Hexagon/hexagon_attributes.s
@@ -0,0 +1,94 @@
+/// Check that file attributes are recorded in a .hexagon.attributes section.
+
+q0&=vcmp.gt(v0.bf,v0.bf) // hvxv73, hvx-qfloat
+r3:2=cround(r1:0,#0x0) // v67, audio
+v3:0.w=vrmpyz(v0.b,r0.b) // hvxv73, zreg
+v1:0.sf=vadd(v0.bf,v0.bf) // hvxv73, hvx-ieee-fp
+
+// RUN: llvm-mc --mattr=+v67,+hvxv73,+hvx-qfloat,+hvx-ieee-fp,+zreg,+audio %s \
+// RUN: -triple=hexagon -filetype=obj --hexagon-add-build-attributes -o %t.o
+
+// RUN: llvm-readelf -A %t.o | \
+// RUN: FileCheck %s --match-full-lines --implicit-check-not={{.}} --check-prefix=READELF
+
+/// llvm-objudmp should be able to determine subtarget features
+/// without manually passing in features when an attribute section is present.
+// RUN: llvm-objdump -d %t.o | FileCheck %s --check-prefix=OBJDUMP
+
+// RUN: llvm-mc --mattr=+v67,+hvxv73,+hvx-qfloat,+hvx-ieee-fp,+zreg,+audio %s \
+// RUN: -triple=hexagon -filetype=asm --hexagon-add-build-attributes | \
+// RUN: FileCheck %s --match-full-lines --implicit-check-not={{.}} --check-prefix=ASM
+
+// READELF: BuildAttributes {
+// READELF-NEXT: FormatVersion: 0x41
+// READELF-NEXT: Section 1 {
+// READELF-NEXT: SectionLength: 31
+// READELF-NEXT: Vendor: hexagon
+// READELF-NEXT: Tag: Tag_File (0x1)
+// READELF-NEXT: Size: 19
+// READELF-NEXT: FileAttributes {
+// READELF-NEXT: Attribute {
+// READELF-NEXT: Tag: 4
+// READELF-NEXT: TagName: arch
+// READELF-NEXT: Value: 67
+// READELF-NEXT: }
+// READELF-NEXT: Attribute {
+// READELF-NEXT: Tag: 5
+// READELF-NEXT: TagName: hvx_arch
+// READELF-NEXT: Value: 73
+// READELF-NEXT: }
+// READELF-NEXT: Attribute {
+// READELF-NEXT: Tag: 6
+// READELF-NEXT: TagName: hvx_ieeefp
+// READELF-NEXT: Value: 1
+// READELF-NEXT: }
+// READELF-NEXT: Attribute {
+// READELF-NEXT: Tag: 7
+// READELF-NEXT: TagName: hvx_qfloat
+// READELF-NEXT: Value: 1
+// READELF-NEXT: }
+// READELF-NEXT: Attribute {
+// READELF-NEXT: Tag: 8
+// READELF-NEXT: TagName: zreg
+// READELF-NEXT: Value: 1
+// READELF-NEXT: }
+// READELF-NEXT: Attribute {
+// READELF-NEXT: Tag: 9
+// READELF-NEXT: TagName: audio
+// READELF-NEXT: Value: 1
+// READELF-NEXT: }
+// READELF-NEXT: Attribute {
+// READELF-NEXT: Tag: 10
+// READELF-NEXT: TagName: cabac
+// READELF-NEXT: Value: 1
+// READELF-NEXT: }
+// READELF-NEXT: }
+// READELF-NEXT: }
+// READELF-NEXT: }
+
+// OBJDUMP: 1c80e0d0 { q0 &= vcmp.gt(v0.bf,v0.bf) }
+// OBJDUMP-NEXT: 8ce0c042 { r3:2 = cround(r1:0,#0x0) }
+// OBJDUMP-NEXT: 19e8c000 { v3:0.w = vrmpyz(v0.b,r0.b) }
+// OBJDUMP-NEXT: 1d40e0c0 { v1:0.sf = vadd(v0.bf,v0.bf) }
+
+// ASM: .attribute 4, 67 // Tag_arch
+// ASM-NEXT: .attribute 5, 73 // Tag_hvx_arch
+// ASM-NEXT: .attribute 6, 1 // Tag_hvx_ieeefp
+// ASM-NEXT: .attribute 7, 1 // Tag_hvx_qfloat
+// ASM-NEXT: .attribute 8, 1 // Tag_zreg
+// ASM-NEXT: .attribute 9, 1 // Tag_audio
+// ASM-NEXT: .attribute 10, 1 // Tag_cabac
+// ASM-NEXT: .text
+// ASM-EMPTY:
+// ASM-NEXT: {
+// ASM-NEXT: q0 &= vcmp.gt(v0.bf,v0.bf)
+// ASM-NEXT: }
+// ASM-NEXT: {
+// ASM-NEXT: r3:2 = cround(r1:0,#0)
+// ASM-NEXT: }
+// ASM-NEXT: {
+// ASM-NEXT: v3:0.w = vrmpyz(v0.b,r0.b)
+// ASM-NEXT: }
+// ASM-NEXT: {
+// ASM-NEXT: v1:0.sf = vadd(v0.bf,v0.bf)
+// ASM-NEXT: }
diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index e78732353cc877..d1c05f437042de 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -49,6 +49,7 @@
#include "llvm/Support/Format.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/HexagonAttributeParser.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/MSP430AttributeParser.h"
#include "llvm/Support/MSP430Attributes.h"
@@ -2824,6 +2825,11 @@ template <typename ELFT> void ELFDumper<ELFT>::printLoadName() {
template <class ELFT> void ELFDumper<ELFT>::printArchSpecificInfo() {
switch (Obj.getHeader().e_machine) {
+ case EM_HEXAGON:
+ printAttributes(ELF::SHT_HEXAGON_ATTRIBUTES,
+ std::make_unique<HexagonAttributeParser>(&W),
+ llvm::endianness::little);
+ break;
case EM_ARM:
if (Obj.isLE())
printAttributes(ELF::SHT_ARM_ATTRIBUTES,
More information about the cfe-commits
mailing list