[llvm] 7aef993 - [MCStreamer] Move emission of attributes section into MCELFStreamer

Jonas Paulsson via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 30 14:02:05 PDT 2021


Author: Jonas Paulsson
Date: 2021-06-30T16:00:27-05:00
New Revision: 7aef99351ac3ff56a34de91ba5ad3d3d9815fa20

URL: https://github.com/llvm/llvm-project/commit/7aef99351ac3ff56a34de91ba5ad3d3d9815fa20
DIFF: https://github.com/llvm/llvm-project/commit/7aef99351ac3ff56a34de91ba5ad3d3d9815fa20.diff

LOG: [MCStreamer]  Move emission of attributes section into MCELFStreamer

Enable the emission of a GNU attributes section by reusing the code for
emitting the ARM build attributes section.

The GNU attributes follow the exact same section format as the ARM
BuildAttributes section, so this can be factored out and reused for GNU
attributes generally.

The immediate motivation for this is to emit a GNU attributes section for the
vector ABI on SystemZ (https://reviews.llvm.org/D105067).

Review: Logan Chien, Ulrich Weigand

Differential Revision: https://reviews.llvm.org/D102894

Added: 
    

Modified: 
    llvm/include/llvm/MC/MCELFStreamer.h
    llvm/include/llvm/MC/MCParser/MCAsmParser.h
    llvm/include/llvm/MC/MCStreamer.h
    llvm/lib/MC/MCAsmStreamer.cpp
    llvm/lib/MC/MCELFStreamer.cpp
    llvm/lib/MC/MCParser/MCAsmParser.cpp
    llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/MC/MCELFStreamer.h b/llvm/include/llvm/MC/MCELFStreamer.h
index 45179378e71c7..8c1e22a147025 100644
--- a/llvm/include/llvm/MC/MCELFStreamer.h
+++ b/llvm/include/llvm/MC/MCELFStreamer.h
@@ -10,6 +10,7 @@
 #define LLVM_MC_MCELFSTREAMER_H
 
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/BinaryFormat/ELF.h"
 #include "llvm/MC/MCDirectives.h"
 #include "llvm/MC/MCObjectStreamer.h"
 
@@ -79,6 +80,52 @@ class MCELFStreamer : public MCObjectStreamer {
   void emitBundleLock(bool AlignToEnd) override;
   void emitBundleUnlock() override;
 
+  /// ELF object attributes section emission support
+  struct AttributeItem {
+    // This structure holds all attributes, accounting for their string /
+    // numeric value, so we can later emit them in declaration order, keeping
+    // all in the same vector.
+    enum {
+      HiddenAttribute = 0,
+      NumericAttribute,
+      TextAttribute,
+      NumericAndTextAttributes
+    } Type;
+    unsigned Tag;
+    unsigned IntValue;
+    std::string StringValue;
+  };
+
+  // Attributes that are added and managed entirely by target.
+  SmallVector<AttributeItem, 64> Contents;
+  void setAttributeItem(unsigned Attribute, unsigned Value,
+                        bool OverwriteExisting);
+  void setAttributeItem(unsigned Attribute, StringRef Value,
+                        bool OverwriteExisting);
+  void setAttributeItems(unsigned Attribute, unsigned IntValue,
+                         StringRef StringValue, bool OverwriteExisting);
+  void emitAttributesSection(StringRef Vendor, const Twine &Section,
+                             unsigned Type, MCSection *&AttributeSection) {
+    createAttributesSection(Vendor, Section, Type, AttributeSection, Contents);
+  }
+
+private:
+  AttributeItem *getAttributeItem(unsigned Attribute);
+  size_t calculateContentSize(SmallVector<AttributeItem, 64> &AttrsVec);
+  void createAttributesSection(StringRef Vendor, const Twine &Section,
+                               unsigned Type, MCSection *&AttributeSection,
+                               SmallVector<AttributeItem, 64> &AttrsVec);
+
+  // GNU attributes that will get emitted at the end of the asm file.
+  SmallVector<AttributeItem, 64> GNUAttributes;
+
+public:
+  void emitGNUAttribute(unsigned Tag, unsigned Value) override {
+    AttributeItem Item = {AttributeItem::NumericAttribute, Tag, Value,
+                          std::string(StringRef(""))};
+    GNUAttributes.push_back(Item);
+  }
+
 private:
   bool isBundleLocked() const;
   void emitInstToFragment(const MCInst &Inst, const MCSubtargetInfo &) override;

diff  --git a/llvm/include/llvm/MC/MCParser/MCAsmParser.h b/llvm/include/llvm/MC/MCParser/MCAsmParser.h
index 2f7118b27d356..56188b7ebaec7 100644
--- a/llvm/include/llvm/MC/MCParser/MCAsmParser.h
+++ b/llvm/include/llvm/MC/MCParser/MCAsmParser.h
@@ -337,6 +337,9 @@ class MCAsmParser {
   /// \return - False on success.
   virtual bool parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res,
                                      SMLoc &EndLoc) = 0;
+
+  /// Parse a .gnu_attribute.
+  bool parseGNUAttribute(SMLoc L, int64_t &Tag, int64_t &IntegerValue);
 };
 
 /// Create an MCAsmParser instance for parsing assembly similar to gas syntax

diff  --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h
index 386726654c53e..d6ed2111ce8b4 100644
--- a/llvm/include/llvm/MC/MCStreamer.h
+++ b/llvm/include/llvm/MC/MCStreamer.h
@@ -618,6 +618,9 @@ class MCStreamer {
   /// \param Args - Arguments of the LOH.
   virtual void emitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) {}
 
+  /// Emit a .gnu_attribute directive.
+  virtual void emitGNUAttribute(unsigned Tag, unsigned Value) {}
+
   /// Emit a common symbol.
   ///
   /// \param Symbol - The common symbol to emit.

diff  --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp
index f9800a3e72255..f6d877c519f87 100644
--- a/llvm/lib/MC/MCAsmStreamer.cpp
+++ b/llvm/lib/MC/MCAsmStreamer.cpp
@@ -153,6 +153,8 @@ class MCAsmStreamer final : public MCStreamer {
 
   void emitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) override;
 
+  void emitGNUAttribute(unsigned Tag, unsigned Value) override;
+
   StringRef getMnemonic(MCInst &MI) override {
     return InstPrinter->getMnemonic(&MI).first;
   }
@@ -538,6 +540,10 @@ void MCAsmStreamer::emitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) {
   EmitEOL();
 }
 
+void MCAsmStreamer::emitGNUAttribute(unsigned Tag, unsigned Value) {
+  OS << "\t.gnu_attribute " << Tag << ", " << Value << "\n";
+}
+
 void MCAsmStreamer::emitAssemblerFlag(MCAssemblerFlag Flag) {
   switch (Flag) {
   case MCAF_SyntaxUnified:         OS << "\t.syntax unified"; break;

diff  --git a/llvm/lib/MC/MCELFStreamer.cpp b/llvm/lib/MC/MCELFStreamer.cpp
index 6c8bfeca17650..784d66805d63a 100644
--- a/llvm/lib/MC/MCELFStreamer.cpp
+++ b/llvm/lib/MC/MCELFStreamer.cpp
@@ -31,6 +31,7 @@
 #include "llvm/MC/MCSymbolELF.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/LEB128.h"
 #include "llvm/Support/TargetRegistry.h"
 #include "llvm/Support/raw_ostream.h"
 #include <cassert>
@@ -697,6 +698,13 @@ void MCELFStreamer::emitBundleUnlock() {
 }
 
 void MCELFStreamer::finishImpl() {
+  // Emit the .gnu attributes section if any attributes have been added.
+  if (!GNUAttributes.empty()) {
+    MCSection *DummyAttributeSection = nullptr;
+    createAttributesSection("gnu", ".gnu.attributes", ELF::SHT_GNU_ATTRIBUTES,
+                            DummyAttributeSection, GNUAttributes);
+  }
+
   // Ensure the last section gets aligned if necessary.
   MCSection *CurSection = getCurrentSectionOnly();
   setSectionAlignmentForBundling(getAssembler(), CurSection);
@@ -726,6 +734,156 @@ void MCELFStreamer::emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
   llvm_unreachable("ELF doesn't support this directive");
 }
 
+void MCELFStreamer::setAttributeItem(unsigned Attribute, unsigned Value,
+                                     bool OverwriteExisting) {
+  // Look for existing attribute item
+  if (AttributeItem *Item = getAttributeItem(Attribute)) {
+    if (!OverwriteExisting)
+      return;
+    Item->Type = AttributeItem::NumericAttribute;
+    Item->IntValue = Value;
+    return;
+  }
+
+  // Create new attribute item
+  AttributeItem Item = {AttributeItem::NumericAttribute, Attribute, Value,
+                        std::string(StringRef(""))};
+  Contents.push_back(Item);
+}
+
+void MCELFStreamer::setAttributeItem(unsigned Attribute, StringRef Value,
+                                     bool OverwriteExisting) {
+  // Look for existing attribute item
+  if (AttributeItem *Item = getAttributeItem(Attribute)) {
+    if (!OverwriteExisting)
+      return;
+    Item->Type = AttributeItem::TextAttribute;
+    Item->StringValue = std::string(Value);
+    return;
+  }
+
+  // Create new attribute item
+  AttributeItem Item = {AttributeItem::TextAttribute, Attribute, 0,
+                        std::string(Value)};
+  Contents.push_back(Item);
+}
+
+void MCELFStreamer::setAttributeItems(unsigned Attribute, unsigned IntValue,
+                                      StringRef StringValue,
+                                      bool OverwriteExisting) {
+  // Look for existing attribute item
+  if (AttributeItem *Item = getAttributeItem(Attribute)) {
+    if (!OverwriteExisting)
+      return;
+    Item->Type = AttributeItem::NumericAndTextAttributes;
+    Item->IntValue = IntValue;
+    Item->StringValue = std::string(StringValue);
+    return;
+  }
+
+  // Create new attribute item
+  AttributeItem Item = {AttributeItem::NumericAndTextAttributes, Attribute,
+                        IntValue, std::string(StringValue)};
+  Contents.push_back(Item);
+}
+
+MCELFStreamer::AttributeItem *
+MCELFStreamer::getAttributeItem(unsigned Attribute) {
+  for (size_t I = 0; I < Contents.size(); ++I)
+    if (Contents[I].Tag == Attribute)
+      return &Contents[I];
+  return nullptr;
+}
+
+size_t
+MCELFStreamer::calculateContentSize(SmallVector<AttributeItem, 64> &AttrsVec) {
+  size_t Result = 0;
+  for (size_t I = 0; I < AttrsVec.size(); ++I) {
+    AttributeItem Item = AttrsVec[I];
+    switch (Item.Type) {
+    case AttributeItem::HiddenAttribute:
+      break;
+    case AttributeItem::NumericAttribute:
+      Result += getULEB128Size(Item.Tag);
+      Result += getULEB128Size(Item.IntValue);
+      break;
+    case AttributeItem::TextAttribute:
+      Result += getULEB128Size(Item.Tag);
+      Result += Item.StringValue.size() + 1; // string + '\0'
+      break;
+    case AttributeItem::NumericAndTextAttributes:
+      Result += getULEB128Size(Item.Tag);
+      Result += getULEB128Size(Item.IntValue);
+      Result += Item.StringValue.size() + 1; // string + '\0';
+      break;
+    }
+  }
+  return Result;
+}
+
+void MCELFStreamer::createAttributesSection(
+    StringRef Vendor, const Twine &Section, unsigned Type,
+    MCSection *&AttributeSection, SmallVector<AttributeItem, 64> &AttrsVec) {
+  // <format-version>
+  // [ <section-length> "vendor-name"
+  // [ <file-tag> <size> <attribute>*
+  //   | <section-tag> <size> <section-number>* 0 <attribute>*
+  //   | <symbol-tag> <size> <symbol-number>* 0 <attribute>*
+  //   ]+
+  // ]*
+
+  // Switch section to AttributeSection or get/create the section.
+  if (AttributeSection) {
+    SwitchSection(AttributeSection);
+  } else {
+    AttributeSection = getContext().getELFSection(Section, Type, 0);
+    SwitchSection(AttributeSection);
+
+    // Format version
+    emitInt8(0x41);
+  }
+
+  // Vendor size + Vendor name + '\0'
+  const size_t VendorHeaderSize = 4 + Vendor.size() + 1;
+
+  // Tag + Tag Size
+  const size_t TagHeaderSize = 1 + 4;
+
+  const size_t ContentsSize = calculateContentSize(AttrsVec);
+
+  emitInt32(VendorHeaderSize + TagHeaderSize + ContentsSize);
+  emitBytes(Vendor);
+  emitInt8(0); // '\0'
+
+  emitInt8(ARMBuildAttrs::File);
+  emitInt32(TagHeaderSize + ContentsSize);
+
+  // Size should have been accounted for already, now
+  // emit each field as its type (ULEB or String)
+  for (size_t I = 0; I < AttrsVec.size(); ++I) {
+    AttributeItem Item = AttrsVec[I];
+    emitULEB128IntValue(Item.Tag);
+    switch (Item.Type) {
+    default:
+      llvm_unreachable("Invalid attribute type");
+    case AttributeItem::NumericAttribute:
+      emitULEB128IntValue(Item.IntValue);
+      break;
+    case AttributeItem::TextAttribute:
+      emitBytes(Item.StringValue);
+      emitInt8(0); // '\0'
+      break;
+    case AttributeItem::NumericAndTextAttributes:
+      emitULEB128IntValue(Item.IntValue);
+      emitBytes(Item.StringValue);
+      emitInt8(0); // '\0'
+      break;
+    }
+  }
+
+  AttrsVec.clear();
+}
+
 MCStreamer *llvm::createELFStreamer(MCContext &Context,
                                     std::unique_ptr<MCAsmBackend> &&MAB,
                                     std::unique_ptr<MCObjectWriter> &&OW,

diff  --git a/llvm/lib/MC/MCParser/MCAsmParser.cpp b/llvm/lib/MC/MCParser/MCAsmParser.cpp
index e3f46f201b48f..d797c2d3f2885 100644
--- a/llvm/lib/MC/MCParser/MCAsmParser.cpp
+++ b/llvm/lib/MC/MCParser/MCAsmParser.cpp
@@ -140,6 +140,25 @@ bool MCAsmParser::parseExpression(const MCExpr *&Res) {
   return parseExpression(Res, L);
 }
 
+bool MCAsmParser::parseGNUAttribute(SMLoc L, int64_t &Tag,
+                                    int64_t &IntegerValue) {
+  // Parse a .gnu_attribute with numerical tag and value.
+  StringRef S(L.getPointer());
+  SMLoc TagLoc;
+  TagLoc = getTok().getLoc();
+  const AsmToken &Tok = getTok();
+  if (Tok.isNot(AsmToken::Integer))
+    return false;
+  Tag = Tok.getIntVal();
+  Lex(); // Eat the Tag
+  Lex(); // Eat the comma
+  if (Tok.isNot(AsmToken::Integer))
+    return false;
+  IntegerValue = Tok.getIntVal();
+  Lex(); // Eat the IntegerValue
+  return true;
+}
+
 void MCParsedAsmOperand::dump() const {
   // Cannot completely remove virtual function even in release mode.
 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)

diff  --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp
index e294748e5ce7b..d6a32b4e967c0 100644
--- a/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp
+++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp
@@ -46,7 +46,6 @@
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/FormattedStream.h"
-#include "llvm/Support/LEB128.h"
 #include "llvm/Support/TargetParser.h"
 #include "llvm/Support/raw_ostream.h"
 #include <algorithm>
@@ -274,104 +273,13 @@ void ARMTargetAsmStreamer::emitUnwindRaw(int64_t Offset,
 
 class ARMTargetELFStreamer : public ARMTargetStreamer {
 private:
-  // This structure holds all attributes, accounting for
-  // their string/numeric value, so we can later emit them
-  // in declaration order, keeping all in the same vector
-  struct AttributeItem {
-    enum {
-      HiddenAttribute = 0,
-      NumericAttribute,
-      TextAttribute,
-      NumericAndTextAttributes
-    } Type;
-    unsigned Tag;
-    unsigned IntValue;
-    std::string StringValue;
-
-    static bool LessTag(const AttributeItem &LHS, const AttributeItem &RHS) {
-      // The conformance tag must be emitted first when serialised
-      // into an object file. Specifically, the addenda to the ARM ABI
-      // states that (2.3.7.4):
-      //
-      // "To simplify recognition by consumers in the common case of
-      // claiming conformity for the whole file, this tag should be
-      // emitted first in a file-scope sub-subsection of the first
-      // public subsection of the attributes section."
-      //
-      // So it is special-cased in this comparison predicate when the
-      // attributes are sorted in finishAttributeSection().
-      return (RHS.Tag != ARMBuildAttrs::conformance) &&
-             ((LHS.Tag == ARMBuildAttrs::conformance) || (LHS.Tag < RHS.Tag));
-    }
-  };
-
   StringRef CurrentVendor;
   unsigned FPU = ARM::FK_INVALID;
   ARM::ArchKind Arch = ARM::ArchKind::INVALID;
   ARM::ArchKind EmittedArch = ARM::ArchKind::INVALID;
-  SmallVector<AttributeItem, 64> Contents;
 
   MCSection *AttributeSection = nullptr;
 
-  AttributeItem *getAttributeItem(unsigned Attribute) {
-    for (size_t i = 0; i < Contents.size(); ++i)
-      if (Contents[i].Tag == Attribute)
-        return &Contents[i];
-    return nullptr;
-  }
-
-  void setAttributeItem(unsigned Attribute, unsigned Value,
-                        bool OverwriteExisting) {
-    // Look for existing attribute item
-    if (AttributeItem *Item = getAttributeItem(Attribute)) {
-      if (!OverwriteExisting)
-        return;
-      Item->Type = AttributeItem::NumericAttribute;
-      Item->IntValue = Value;
-      return;
-    }
-
-    // Create new attribute item
-    AttributeItem Item = {AttributeItem::NumericAttribute, Attribute, Value,
-                          std::string(StringRef(""))};
-    Contents.push_back(Item);
-  }
-
-  void setAttributeItem(unsigned Attribute, StringRef Value,
-                        bool OverwriteExisting) {
-    // Look for existing attribute item
-    if (AttributeItem *Item = getAttributeItem(Attribute)) {
-      if (!OverwriteExisting)
-        return;
-      Item->Type = AttributeItem::TextAttribute;
-      Item->StringValue = std::string(Value);
-      return;
-    }
-
-    // Create new attribute item
-    AttributeItem Item = {AttributeItem::TextAttribute, Attribute, 0,
-                          std::string(Value)};
-    Contents.push_back(Item);
-  }
-
-  void setAttributeItems(unsigned Attribute, unsigned IntValue,
-                         StringRef StringValue, bool OverwriteExisting) {
-    // Look for existing attribute item
-    if (AttributeItem *Item = getAttributeItem(Attribute)) {
-      if (!OverwriteExisting)
-        return;
-      Item->Type = AttributeItem::NumericAndTextAttributes;
-      Item->IntValue = IntValue;
-      Item->StringValue = std::string(StringValue);
-      return;
-    }
-
-    // Create new attribute item
-    AttributeItem Item = {AttributeItem::NumericAndTextAttributes, Attribute,
-                          IntValue, std::string(StringValue)};
-    Contents.push_back(Item);
-  }
-
   void emitArchDefaultAttributes();
   void emitFPUDefaultAttributes();
 
@@ -406,8 +314,6 @@ class ARMTargetELFStreamer : public ARMTargetStreamer {
   void AnnotateTLSDescriptorSequence(const MCSymbolRefExpr *SRE) override;
   void emitThumbSet(MCSymbol *Symbol, const MCExpr *Value) override;
 
-  size_t calculateContentSize() const;
-
   // Reset state between object emissions
   void reset() override;
 
@@ -777,26 +683,28 @@ void ARMTargetELFStreamer::switchVendor(StringRef Vendor) {
   if (!CurrentVendor.empty())
     finishAttributeSection();
 
-  assert(Contents.empty() &&
+  assert(getStreamer().Contents.empty() &&
          ".ARM.attributes should be flushed before changing vendor");
   CurrentVendor = Vendor;
 
 }
 
 void ARMTargetELFStreamer::emitAttribute(unsigned Attribute, unsigned Value) {
-  setAttributeItem(Attribute, Value, /* OverwriteExisting= */ true);
+  getStreamer().setAttributeItem(Attribute, Value,
+                                 /* OverwriteExisting= */ true);
 }
 
 void ARMTargetELFStreamer::emitTextAttribute(unsigned Attribute,
                                              StringRef Value) {
-  setAttributeItem(Attribute, Value, /* OverwriteExisting= */ true);
+  getStreamer().setAttributeItem(Attribute, Value,
+                                 /* OverwriteExisting= */ true);
 }
 
 void ARMTargetELFStreamer::emitIntTextAttribute(unsigned Attribute,
                                                 unsigned IntValue,
                                                 StringRef StringValue) {
-  setAttributeItems(Attribute, IntValue, StringValue,
-                    /* OverwriteExisting= */ true);
+  getStreamer().setAttributeItems(Attribute, IntValue, StringValue,
+                                  /* OverwriteExisting= */ true);
 }
 
 void ARMTargetELFStreamer::emitArch(ARM::ArchKind Value) {
@@ -809,19 +717,14 @@ void ARMTargetELFStreamer::emitObjectArch(ARM::ArchKind Value) {
 
 void ARMTargetELFStreamer::emitArchDefaultAttributes() {
   using namespace ARMBuildAttrs;
+  ARMELFStreamer &S = getStreamer();
 
-  setAttributeItem(CPU_name,
-                   ARM::getCPUAttr(Arch),
-                   false);
+  S.setAttributeItem(CPU_name, ARM::getCPUAttr(Arch), false);
 
   if (EmittedArch == ARM::ArchKind::INVALID)
-    setAttributeItem(CPU_arch,
-                     ARM::getArchAttr(Arch),
-                     false);
+    S.setAttributeItem(CPU_arch, ARM::getArchAttr(Arch), false);
   else
-    setAttributeItem(CPU_arch,
-                     ARM::getArchAttr(EmittedArch),
-                     false);
+    S.setAttributeItem(CPU_arch, ARM::getArchAttr(EmittedArch), false);
 
   switch (Arch) {
   case ARM::ArchKind::ARMV2:
@@ -829,7 +732,7 @@ void ARMTargetELFStreamer::emitArchDefaultAttributes() {
   case ARM::ArchKind::ARMV3:
   case ARM::ArchKind::ARMV3M:
   case ARM::ArchKind::ARMV4:
-    setAttributeItem(ARM_ISA_use, Allowed, false);
+    S.setAttributeItem(ARM_ISA_use, Allowed, false);
     break;
 
   case ARM::ArchKind::ARMV4T:
@@ -837,42 +740,42 @@ void ARMTargetELFStreamer::emitArchDefaultAttributes() {
   case ARM::ArchKind::XSCALE:
   case ARM::ArchKind::ARMV5TE:
   case ARM::ArchKind::ARMV6:
-    setAttributeItem(ARM_ISA_use, Allowed, false);
-    setAttributeItem(THUMB_ISA_use, Allowed, false);
+    S.setAttributeItem(ARM_ISA_use, Allowed, false);
+    S.setAttributeItem(THUMB_ISA_use, Allowed, false);
     break;
 
   case ARM::ArchKind::ARMV6T2:
-    setAttributeItem(ARM_ISA_use, Allowed, false);
-    setAttributeItem(THUMB_ISA_use, AllowThumb32, false);
+    S.setAttributeItem(ARM_ISA_use, Allowed, false);
+    S.setAttributeItem(THUMB_ISA_use, AllowThumb32, false);
     break;
 
   case ARM::ArchKind::ARMV6K:
   case ARM::ArchKind::ARMV6KZ:
-    setAttributeItem(ARM_ISA_use, Allowed, false);
-    setAttributeItem(THUMB_ISA_use, Allowed, false);
-    setAttributeItem(Virtualization_use, AllowTZ, false);
+    S.setAttributeItem(ARM_ISA_use, Allowed, false);
+    S.setAttributeItem(THUMB_ISA_use, Allowed, false);
+    S.setAttributeItem(Virtualization_use, AllowTZ, false);
     break;
 
   case ARM::ArchKind::ARMV6M:
-    setAttributeItem(THUMB_ISA_use, Allowed, false);
+    S.setAttributeItem(THUMB_ISA_use, Allowed, false);
     break;
 
   case ARM::ArchKind::ARMV7A:
-    setAttributeItem(CPU_arch_profile, ApplicationProfile, false);
-    setAttributeItem(ARM_ISA_use, Allowed, false);
-    setAttributeItem(THUMB_ISA_use, AllowThumb32, false);
+    S.setAttributeItem(CPU_arch_profile, ApplicationProfile, false);
+    S.setAttributeItem(ARM_ISA_use, Allowed, false);
+    S.setAttributeItem(THUMB_ISA_use, AllowThumb32, false);
     break;
 
   case ARM::ArchKind::ARMV7R:
-    setAttributeItem(CPU_arch_profile, RealTimeProfile, false);
-    setAttributeItem(ARM_ISA_use, Allowed, false);
-    setAttributeItem(THUMB_ISA_use, AllowThumb32, false);
+    S.setAttributeItem(CPU_arch_profile, RealTimeProfile, false);
+    S.setAttributeItem(ARM_ISA_use, Allowed, false);
+    S.setAttributeItem(THUMB_ISA_use, AllowThumb32, false);
     break;
 
   case ARM::ArchKind::ARMV7EM:
   case ARM::ArchKind::ARMV7M:
-    setAttributeItem(CPU_arch_profile, MicroControllerProfile, false);
-    setAttributeItem(THUMB_ISA_use, AllowThumb32, false);
+    S.setAttributeItem(CPU_arch_profile, MicroControllerProfile, false);
+    S.setAttributeItem(THUMB_ISA_use, AllowThumb32, false);
     break;
 
   case ARM::ArchKind::ARMV8A:
@@ -882,29 +785,29 @@ void ARMTargetELFStreamer::emitArchDefaultAttributes() {
   case ARM::ArchKind::ARMV8_4A:
   case ARM::ArchKind::ARMV8_5A:
   case ARM::ArchKind::ARMV8_6A:
-    setAttributeItem(CPU_arch_profile, ApplicationProfile, false);
-    setAttributeItem(ARM_ISA_use, Allowed, false);
-    setAttributeItem(THUMB_ISA_use, AllowThumb32, false);
-    setAttributeItem(MPextension_use, Allowed, false);
-    setAttributeItem(Virtualization_use, AllowTZVirtualization, false);
+    S.setAttributeItem(CPU_arch_profile, ApplicationProfile, false);
+    S.setAttributeItem(ARM_ISA_use, Allowed, false);
+    S.setAttributeItem(THUMB_ISA_use, AllowThumb32, false);
+    S.setAttributeItem(MPextension_use, Allowed, false);
+    S.setAttributeItem(Virtualization_use, AllowTZVirtualization, false);
     break;
 
   case ARM::ArchKind::ARMV8MBaseline:
   case ARM::ArchKind::ARMV8MMainline:
-    setAttributeItem(THUMB_ISA_use, AllowThumbDerived, false);
-    setAttributeItem(CPU_arch_profile, MicroControllerProfile, false);
+    S.setAttributeItem(THUMB_ISA_use, AllowThumbDerived, false);
+    S.setAttributeItem(CPU_arch_profile, MicroControllerProfile, false);
     break;
 
   case ARM::ArchKind::IWMMXT:
-    setAttributeItem(ARM_ISA_use, Allowed, false);
-    setAttributeItem(THUMB_ISA_use, Allowed, false);
-    setAttributeItem(WMMX_arch, AllowWMMXv1, false);
+    S.setAttributeItem(ARM_ISA_use, Allowed, false);
+    S.setAttributeItem(THUMB_ISA_use, Allowed, false);
+    S.setAttributeItem(WMMX_arch, AllowWMMXv1, false);
     break;
 
   case ARM::ArchKind::IWMMXT2:
-    setAttributeItem(ARM_ISA_use, Allowed, false);
-    setAttributeItem(THUMB_ISA_use, Allowed, false);
-    setAttributeItem(WMMX_arch, AllowWMMXv2, false);
+    S.setAttributeItem(ARM_ISA_use, Allowed, false);
+    S.setAttributeItem(THUMB_ISA_use, Allowed, false);
+    S.setAttributeItem(WMMX_arch, AllowWMMXv2, false);
     break;
 
   default:
@@ -918,123 +821,106 @@ void ARMTargetELFStreamer::emitFPU(unsigned Value) {
 }
 
 void ARMTargetELFStreamer::emitFPUDefaultAttributes() {
+  ARMELFStreamer &S = getStreamer();
+
   switch (FPU) {
   case ARM::FK_VFP:
   case ARM::FK_VFPV2:
-    setAttributeItem(ARMBuildAttrs::FP_arch,
-                     ARMBuildAttrs::AllowFPv2,
-                     /* OverwriteExisting= */ false);
+    S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv2,
+                       /* OverwriteExisting= */ false);
     break;
 
   case ARM::FK_VFPV3:
-    setAttributeItem(ARMBuildAttrs::FP_arch,
-                     ARMBuildAttrs::AllowFPv3A,
-                     /* OverwriteExisting= */ false);
+    S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv3A,
+                       /* OverwriteExisting= */ false);
     break;
 
   case ARM::FK_VFPV3_FP16:
-    setAttributeItem(ARMBuildAttrs::FP_arch,
-                     ARMBuildAttrs::AllowFPv3A,
-                     /* OverwriteExisting= */ false);
-    setAttributeItem(ARMBuildAttrs::FP_HP_extension,
-                     ARMBuildAttrs::AllowHPFP,
-                     /* OverwriteExisting= */ false);
+    S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv3A,
+                       /* OverwriteExisting= */ false);
+    S.setAttributeItem(ARMBuildAttrs::FP_HP_extension, ARMBuildAttrs::AllowHPFP,
+                       /* OverwriteExisting= */ false);
     break;
 
   case ARM::FK_VFPV3_D16:
-    setAttributeItem(ARMBuildAttrs::FP_arch,
-                     ARMBuildAttrs::AllowFPv3B,
-                     /* OverwriteExisting= */ false);
+    S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv3B,
+                       /* OverwriteExisting= */ false);
     break;
 
   case ARM::FK_VFPV3_D16_FP16:
-    setAttributeItem(ARMBuildAttrs::FP_arch,
-                     ARMBuildAttrs::AllowFPv3B,
-                     /* OverwriteExisting= */ false);
-    setAttributeItem(ARMBuildAttrs::FP_HP_extension,
-                     ARMBuildAttrs::AllowHPFP,
-                     /* OverwriteExisting= */ false);
+    S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv3B,
+                       /* OverwriteExisting= */ false);
+    S.setAttributeItem(ARMBuildAttrs::FP_HP_extension, ARMBuildAttrs::AllowHPFP,
+                       /* OverwriteExisting= */ false);
     break;
 
   case ARM::FK_VFPV3XD:
-    setAttributeItem(ARMBuildAttrs::FP_arch,
-                     ARMBuildAttrs::AllowFPv3B,
-                     /* OverwriteExisting= */ false);
+    S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv3B,
+                       /* OverwriteExisting= */ false);
     break;
   case ARM::FK_VFPV3XD_FP16:
-    setAttributeItem(ARMBuildAttrs::FP_arch,
-                     ARMBuildAttrs::AllowFPv3B,
-                     /* OverwriteExisting= */ false);
-    setAttributeItem(ARMBuildAttrs::FP_HP_extension,
-                     ARMBuildAttrs::AllowHPFP,
-                     /* OverwriteExisting= */ false);
+    S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv3B,
+                       /* OverwriteExisting= */ false);
+    S.setAttributeItem(ARMBuildAttrs::FP_HP_extension, ARMBuildAttrs::AllowHPFP,
+                       /* OverwriteExisting= */ false);
     break;
 
   case ARM::FK_VFPV4:
-    setAttributeItem(ARMBuildAttrs::FP_arch,
-                     ARMBuildAttrs::AllowFPv4A,
-                     /* OverwriteExisting= */ false);
+    S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv4A,
+                       /* OverwriteExisting= */ false);
     break;
 
   // ABI_HardFP_use is handled in ARMAsmPrinter, so _SP_D16 is treated the same
   // as _D16 here.
   case ARM::FK_FPV4_SP_D16:
   case ARM::FK_VFPV4_D16:
-    setAttributeItem(ARMBuildAttrs::FP_arch,
-                     ARMBuildAttrs::AllowFPv4B,
-                     /* OverwriteExisting= */ false);
+    S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv4B,
+                       /* OverwriteExisting= */ false);
     break;
 
   case ARM::FK_FP_ARMV8:
-    setAttributeItem(ARMBuildAttrs::FP_arch,
-                     ARMBuildAttrs::AllowFPARMv8A,
-                     /* OverwriteExisting= */ false);
+    S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPARMv8A,
+                       /* OverwriteExisting= */ false);
     break;
 
   // FPV5_D16 is identical to FP_ARMV8 except for the number of D registers, so
   // uses the FP_ARMV8_D16 build attribute.
   case ARM::FK_FPV5_SP_D16:
   case ARM::FK_FPV5_D16:
-    setAttributeItem(ARMBuildAttrs::FP_arch,
-                     ARMBuildAttrs::AllowFPARMv8B,
-                     /* OverwriteExisting= */ false);
+    S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPARMv8B,
+                       /* OverwriteExisting= */ false);
     break;
 
   case ARM::FK_NEON:
-    setAttributeItem(ARMBuildAttrs::FP_arch,
-                     ARMBuildAttrs::AllowFPv3A,
-                     /* OverwriteExisting= */ false);
-    setAttributeItem(ARMBuildAttrs::Advanced_SIMD_arch,
-                     ARMBuildAttrs::AllowNeon,
-                     /* OverwriteExisting= */ false);
+    S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv3A,
+                       /* OverwriteExisting= */ false);
+    S.setAttributeItem(ARMBuildAttrs::Advanced_SIMD_arch,
+                       ARMBuildAttrs::AllowNeon,
+                       /* OverwriteExisting= */ false);
     break;
 
   case ARM::FK_NEON_FP16:
-    setAttributeItem(ARMBuildAttrs::FP_arch,
-                     ARMBuildAttrs::AllowFPv3A,
-                     /* OverwriteExisting= */ false);
-    setAttributeItem(ARMBuildAttrs::Advanced_SIMD_arch,
-                     ARMBuildAttrs::AllowNeon,
-                     /* OverwriteExisting= */ false);
-    setAttributeItem(ARMBuildAttrs::FP_HP_extension,
-                     ARMBuildAttrs::AllowHPFP,
-                     /* OverwriteExisting= */ false);
+    S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv3A,
+                       /* OverwriteExisting= */ false);
+    S.setAttributeItem(ARMBuildAttrs::Advanced_SIMD_arch,
+                       ARMBuildAttrs::AllowNeon,
+                       /* OverwriteExisting= */ false);
+    S.setAttributeItem(ARMBuildAttrs::FP_HP_extension, ARMBuildAttrs::AllowHPFP,
+                       /* OverwriteExisting= */ false);
     break;
 
   case ARM::FK_NEON_VFPV4:
-    setAttributeItem(ARMBuildAttrs::FP_arch,
-                     ARMBuildAttrs::AllowFPv4A,
-                     /* OverwriteExisting= */ false);
-    setAttributeItem(ARMBuildAttrs::Advanced_SIMD_arch,
-                     ARMBuildAttrs::AllowNeon2,
-                     /* OverwriteExisting= */ false);
+    S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv4A,
+                       /* OverwriteExisting= */ false);
+    S.setAttributeItem(ARMBuildAttrs::Advanced_SIMD_arch,
+                       ARMBuildAttrs::AllowNeon2,
+                       /* OverwriteExisting= */ false);
     break;
 
   case ARM::FK_NEON_FP_ARMV8:
   case ARM::FK_CRYPTO_NEON_FP_ARMV8:
-    setAttributeItem(ARMBuildAttrs::FP_arch,
-                     ARMBuildAttrs::AllowFPARMv8A,
-                     /* OverwriteExisting= */ false);
+    S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPARMv8A,
+                       /* OverwriteExisting= */ false);
     // 'Advanced_SIMD_arch' must be emitted not here, but within
     // ARMAsmPrinter::emitAttributes(), depending on hasV8Ops() and hasV8_1a()
     break;
@@ -1049,39 +935,8 @@ void ARMTargetELFStreamer::emitFPUDefaultAttributes() {
   }
 }
 
-size_t ARMTargetELFStreamer::calculateContentSize() const {
-  size_t Result = 0;
-  for (size_t i = 0; i < Contents.size(); ++i) {
-    AttributeItem item = Contents[i];
-    switch (item.Type) {
-    case AttributeItem::HiddenAttribute:
-      break;
-    case AttributeItem::NumericAttribute:
-      Result += getULEB128Size(item.Tag);
-      Result += getULEB128Size(item.IntValue);
-      break;
-    case AttributeItem::TextAttribute:
-      Result += getULEB128Size(item.Tag);
-      Result += item.StringValue.size() + 1; // string + '\0'
-      break;
-    case AttributeItem::NumericAndTextAttributes:
-      Result += getULEB128Size(item.Tag);
-      Result += getULEB128Size(item.IntValue);
-      Result += item.StringValue.size() + 1; // string + '\0';
-      break;
-    }
-  }
-  return Result;
-}
-
 void ARMTargetELFStreamer::finishAttributeSection() {
-  // <format-version>
-  // [ <section-length> "vendor-name"
-  // [ <file-tag> <size> <attribute>*
-  //   | <section-tag> <size> <section-number>* 0 <attribute>*
-  //   | <symbol-tag> <size> <symbol-number>* 0 <attribute>*
-  //   ]+
-  // ]*
+  ARMELFStreamer &S = getStreamer();
 
   if (FPU != ARM::FK_INVALID)
     emitFPUDefaultAttributes();
@@ -1089,63 +944,30 @@ void ARMTargetELFStreamer::finishAttributeSection() {
   if (Arch != ARM::ArchKind::INVALID)
     emitArchDefaultAttributes();
 
-  if (Contents.empty())
+  if (S.Contents.empty())
     return;
 
-  llvm::sort(Contents, AttributeItem::LessTag);
-
-  ARMELFStreamer &Streamer = getStreamer();
-
-  // Switch to .ARM.attributes section
-  if (AttributeSection) {
-    Streamer.SwitchSection(AttributeSection);
-  } else {
-    AttributeSection = Streamer.getContext().getELFSection(
-        ".ARM.attributes", ELF::SHT_ARM_ATTRIBUTES, 0);
-    Streamer.SwitchSection(AttributeSection);
-
-    // Format version
-    Streamer.emitInt8(0x41);
-  }
-
-  // Vendor size + Vendor name + '\0'
-  const size_t VendorHeaderSize = 4 + CurrentVendor.size() + 1;
-
-  // Tag + Tag Size
-  const size_t TagHeaderSize = 1 + 4;
-
-  const size_t ContentsSize = calculateContentSize();
-
-  Streamer.emitInt32(VendorHeaderSize + TagHeaderSize + ContentsSize);
-  Streamer.emitBytes(CurrentVendor);
-  Streamer.emitInt8(0); // '\0'
-
-  Streamer.emitInt8(ARMBuildAttrs::File);
-  Streamer.emitInt32(TagHeaderSize + ContentsSize);
+  auto LessTag = [](const MCELFStreamer::AttributeItem &LHS,
+                    const MCELFStreamer::AttributeItem &RHS) -> bool {
+    // The conformance tag must be emitted first when serialised into an
+    // object file. Specifically, the addenda to the ARM ABI states that
+    // (2.3.7.4):
+    //
+    // "To simplify recognition by consumers in the common case of claiming
+    // conformity for the whole file, this tag should be emitted first in a
+    // file-scope sub-subsection of the first public subsection of the
+    // attributes section."
+    //
+    // So it is special-cased in this comparison predicate when the
+    // attributes are sorted in finishAttributeSection().
+    return (RHS.Tag != ARMBuildAttrs::conformance) &&
+           ((LHS.Tag == ARMBuildAttrs::conformance) || (LHS.Tag < RHS.Tag));
+  };
+  llvm::sort(S.Contents, LessTag);
 
-  // Size should have been accounted for already, now
-  // emit each field as its type (ULEB or String)
-  for (size_t i = 0; i < Contents.size(); ++i) {
-    AttributeItem item = Contents[i];
-    Streamer.emitULEB128IntValue(item.Tag);
-    switch (item.Type) {
-    default: llvm_unreachable("Invalid attribute type");
-    case AttributeItem::NumericAttribute:
-      Streamer.emitULEB128IntValue(item.IntValue);
-      break;
-    case AttributeItem::TextAttribute:
-      Streamer.emitBytes(item.StringValue);
-      Streamer.emitInt8(0); // '\0'
-      break;
-    case AttributeItem::NumericAndTextAttributes:
-      Streamer.emitULEB128IntValue(item.IntValue);
-      Streamer.emitBytes(item.StringValue);
-      Streamer.emitInt8(0); // '\0'
-      break;
-    }
-  }
+  S.emitAttributesSection(CurrentVendor, ".ARM.attributes",
+                          ELF::SHT_ARM_ATTRIBUTES, AttributeSection);
 
-  Contents.clear();
   FPU = ARM::FK_INVALID;
 }
 


        


More information about the llvm-commits mailing list