[llvm] [LLVM][Clang][AArch64] Implement AArch64 build attributes (PR #118771)

via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 5 01:14:10 PST 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-hexagon

Author: SivanShani-Arm (sivan-shani)

<details>
<summary>Changes</summary>

- Added support for AArch64-specific build attributes.
- Print AArch64 build attributes to assembly.
- Emit AArch64 build attributes to ELF.

Specification: https://github.com/ARM-software/abi-aa/blob/654a64cbac041fc3bff617800998d40b5068f592/buildattr64/buildattr64.rst#aeabi-feature-and-bits-subsection

---

Patch is 43.42 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/118771.diff


11 Files Affected:

- (modified) llvm/include/llvm/BinaryFormat/ELF.h (+2) 
- (modified) llvm/include/llvm/MC/MCELFStreamer.h (+22-5) 
- (modified) llvm/include/llvm/Support/ARMBuildAttributes.h (+63) 
- (modified) llvm/lib/MC/MCELFStreamer.cpp (+67-9) 
- (modified) llvm/lib/Support/ARMBuildAttrs.cpp (+55-4) 
- (modified) llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp (+58-16) 
- (modified) llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp (+121-1) 
- (modified) llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h (+22-1) 
- (modified) llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp (+58-58) 
- (modified) llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp (+1-1) 
- (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp (+3-3) 


``````````diff
diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h
index fd32a6ec19652b..dd64647c5c0334 100644
--- a/llvm/include/llvm/BinaryFormat/ELF.h
+++ b/llvm/include/llvm/BinaryFormat/ELF.h
@@ -1150,6 +1150,8 @@ enum : unsigned {
   SHT_ARM_ATTRIBUTES = 0x70000003U,
   SHT_ARM_DEBUGOVERLAY = 0x70000004U,
   SHT_ARM_OVERLAYSECTION = 0x70000005U,
+  // Support for AArch64 build attributes
+  SHT_AARCH64_ATTRIBUTES = 0x70000003U,
   // Special aarch64-specific section for MTE support, as described in:
   // https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#section-types
   SHT_AARCH64_AUTH_RELR = 0x70000004U,
diff --git a/llvm/include/llvm/MC/MCELFStreamer.h b/llvm/include/llvm/MC/MCELFStreamer.h
index 94d14088d0f5d2..351c7ddd3b7380 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/ADT/StringRef.h"
 #include "llvm/MC/MCDirectives.h"
 #include "llvm/MC/MCObjectStreamer.h"
 
@@ -107,25 +108,41 @@ class MCELFStreamer : public MCObjectStreamer {
     std::string StringValue;
   };
 
+  /// ELF object attributes subsection support
+  struct AttributeSubSection {
+    // [<uint32: subsection-length> NTBS: vendor-name <bytes: vendor-data>]*
+    StringRef Vendor;
+    // <uint8: optional> <uint8: parameter type> <attribute>*
+    unsigned IsMandatory;  // SubsectionMandatory::REQUIRED (0), SubsectionMandatory::OPTIONAL (1)
+    unsigned ParameterType; // SubsectionType::ULEB128 (0), SubsectionType::NTBS (1)
+    SmallVector<AttributeItem, 64> Content;
+  };
+
   // Attributes that are added and managed entirely by target.
   SmallVector<AttributeItem, 64> Contents;
   void setAttributeItem(unsigned Attribute, unsigned Value,
-                        bool OverwriteExisting);
+                        bool OverwriteExisting, SmallVector<AttributeItem, 64> &Attributes);
   void setAttributeItem(unsigned Attribute, StringRef Value,
-                        bool OverwriteExisting);
+                        bool OverwriteExisting, SmallVector<AttributeItem, 64> &Attributes);
   void setAttributeItems(unsigned Attribute, unsigned IntValue,
-                         StringRef StringValue, bool OverwriteExisting);
+                         StringRef StringValue, bool OverwriteExisting, SmallVector<AttributeItem, 64> &Attributes);
   void emitAttributesSection(StringRef Vendor, const Twine &Section,
                              unsigned Type, MCSection *&AttributeSection) {
     createAttributesSection(Vendor, Section, Type, AttributeSection, Contents);
   }
+  void emitAttributesSection(MCSection *&AttributeSection,
+  const Twine &Section, unsigned Type, SmallVector<AttributeSubSection, 64> &SubSectionVec) {
+    createAttributesSection(AttributeSection, Section, Type, SubSectionVec);
+  }
 
 private:
-  AttributeItem *getAttributeItem(unsigned Attribute);
-  size_t calculateContentSize(SmallVector<AttributeItem, 64> &AttrsVec);
+  AttributeItem *getAttributeItem(unsigned Attribute, SmallVector<AttributeItem, 64> &Attributes);
+  size_t calculateContentSize(SmallVector<AttributeItem, 64> &AttrsVec) const;
   void createAttributesSection(StringRef Vendor, const Twine &Section,
                                unsigned Type, MCSection *&AttributeSection,
                                SmallVector<AttributeItem, 64> &AttrsVec);
+  void createAttributesSection(MCSection *&AttributeSection, const Twine & Section,
+                               unsigned Type, SmallVector<AttributeSubSection, 64> &SubSectionVec);
 
   // GNU attributes that will get emitted at the end of the asm file.
   SmallVector<AttributeItem, 64> GNUAttributes;
diff --git a/llvm/include/llvm/Support/ARMBuildAttributes.h b/llvm/include/llvm/Support/ARMBuildAttributes.h
index 35f8992ca93296..5e17ccf835190f 100644
--- a/llvm/include/llvm/Support/ARMBuildAttributes.h
+++ b/llvm/include/llvm/Support/ARMBuildAttributes.h
@@ -21,10 +21,58 @@
 #include "llvm/Support/ELFAttributes.h"
 
 namespace llvm {
+class StringRef;
+
 namespace ARMBuildAttrs {
 
 const TagNameMap &getARMAttributeTags();
 
+/// AArch64 build attributes vendors (=subsection name)
+enum Vendor : unsigned {
+  AEBI_FEATURE_AND_BITS = 0,
+  AEBI_PAUTHABI = 1
+};
+
+inline StringRef vendorToStr(unsigned Vendor) {
+  switch(Vendor) {
+    default:
+      llvm_unreachable("unknown AArch64 vendor name");
+      return "";
+    case AEBI_FEATURE_AND_BITS:
+      return "aeabi-feature-and-bits";
+    case AEBI_PAUTHABI:
+      return "aeabi-pauthabi";
+  }
+}
+
+enum SubsectionMandatory : unsigned {
+  OPTIONAL = 0,
+  REQUIRED = 1
+};
+
+enum SubsectionType : unsigned {
+  ULEB128 = 0,
+  NTBS = 1
+};
+
+enum FeatureAndBitsTags : unsigned {
+  Tag_PAuth_Platform = 1,
+  Tag_PAuth_Schema = 2
+};
+
+enum PauthabiTags : unsigned {
+  Tag_Feature_BTI = 0,
+  Tag_Feature_PAC = 1,
+  Tag_Feature_GCS = 2
+};
+
+enum PauthabiTagsFlag : unsigned {
+  Feature_BTI_Flag = 1 << 0,
+  Feature_PAC_Flag = 1 << 1,
+  Feature_GCS_Flag = 1 << 2
+};
+/// ---
+
 enum SpecialAttr {
   // This is for the .cpu asm attr. It translates into one or more
   // AttrType (below) entries in the .ARM.attributes section in the ELF.
@@ -88,6 +136,21 @@ enum AttrType : unsigned {
   MPextension_use_old = 70   // recoded to MPextension_use (ABI r2.08)
 };
 
+enum AVAttr {
+  AV_cpp_exceptions         = 6,
+  AV_eba                    = 16
+};
+
+StringRef AttrTypeAsString(StringRef Vendor, unsigned Attr, bool HasTagPrefix = true);
+StringRef AttrTypeAsString(AttrType Attr, bool HasTagPrefix = true);
+StringRef AttrTypeAsString(AVAttr Attr, bool HasTagPrefix = true);
+int AttrTypeFromString(StringRef Vendor, StringRef Tag);
+
+// Magic numbers for .ARM.attributes
+enum AttrMagic {
+  Format_Version  = 0x41
+};
+
 // Legal Values for CPU_arch, (=6), uleb128
 enum CPUArch {
   Pre_v4 = 0,
diff --git a/llvm/lib/MC/MCELFStreamer.cpp b/llvm/lib/MC/MCELFStreamer.cpp
index 64ab2b2ab58f5b..34a7367a18f44c 100644
--- a/llvm/lib/MC/MCELFStreamer.cpp
+++ b/llvm/lib/MC/MCELFStreamer.cpp
@@ -636,9 +636,9 @@ void MCELFStreamer::emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
 }
 
 void MCELFStreamer::setAttributeItem(unsigned Attribute, unsigned Value,
-                                     bool OverwriteExisting) {
+                                     bool OverwriteExisting, SmallVector<AttributeItem, 64> &Attributes) {
   // Look for existing attribute item
-  if (AttributeItem *Item = getAttributeItem(Attribute)) {
+  if (AttributeItem *Item = getAttributeItem(Attribute, Attributes)) {
     if (!OverwriteExisting)
       return;
     Item->Type = AttributeItem::NumericAttribute;
@@ -653,9 +653,9 @@ void MCELFStreamer::setAttributeItem(unsigned Attribute, unsigned Value,
 }
 
 void MCELFStreamer::setAttributeItem(unsigned Attribute, StringRef Value,
-                                     bool OverwriteExisting) {
+                                     bool OverwriteExisting, SmallVector<AttributeItem, 64> &Attributes) {
   // Look for existing attribute item
-  if (AttributeItem *Item = getAttributeItem(Attribute)) {
+  if (AttributeItem *Item = getAttributeItem(Attribute, Attributes)) {
     if (!OverwriteExisting)
       return;
     Item->Type = AttributeItem::TextAttribute;
@@ -671,9 +671,9 @@ void MCELFStreamer::setAttributeItem(unsigned Attribute, StringRef Value,
 
 void MCELFStreamer::setAttributeItems(unsigned Attribute, unsigned IntValue,
                                       StringRef StringValue,
-                                      bool OverwriteExisting) {
+                                      bool OverwriteExisting, SmallVector<AttributeItem, 64> &Attributes) {
   // Look for existing attribute item
-  if (AttributeItem *Item = getAttributeItem(Attribute)) {
+  if (AttributeItem *Item = getAttributeItem(Attribute, Attributes)) {
     if (!OverwriteExisting)
       return;
     Item->Type = AttributeItem::NumericAndTextAttributes;
@@ -689,15 +689,15 @@ void MCELFStreamer::setAttributeItems(unsigned Attribute, unsigned IntValue,
 }
 
 MCELFStreamer::AttributeItem *
-MCELFStreamer::getAttributeItem(unsigned Attribute) {
-  for (AttributeItem &Item : Contents)
+MCELFStreamer::getAttributeItem(unsigned Attribute, SmallVector<AttributeItem, 64> &Attributes) {
+  for (AttributeItem &Item : Attributes)
     if (Item.Tag == Attribute)
       return &Item;
   return nullptr;
 }
 
 size_t
-MCELFStreamer::calculateContentSize(SmallVector<AttributeItem, 64> &AttrsVec) {
+MCELFStreamer::calculateContentSize(SmallVector<AttributeItem, 64> &AttrsVec) const {
   size_t Result = 0;
   for (const AttributeItem &Item : AttrsVec) {
     switch (Item.Type) {
@@ -783,6 +783,64 @@ void MCELFStreamer::createAttributesSection(
   AttrsVec.clear();
 }
 
+void MCELFStreamer::createAttributesSection(MCSection *&AttributeSection,
+  const Twine &Section, unsigned Type, SmallVector<AttributeSubSection, 64> &SubSectionVec) {
+// <format-version: 'A'>
+// [ <uint32: subsection-length> NTBS: vendor-name
+//   <bytes: vendor-data>
+// ]*
+// vendor-data expends to:
+// <uint8: optional> <uint8: parameter type> <attribute>*
+  if (SubSectionVec.size() == 0) {
+    return;
+  }
+
+  // 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);
+  }
+
+  for (AttributeSubSection &SubSection : SubSectionVec) {
+    // subsection-length + vendor-name + '\0'
+    const size_t VendorHeaderSize = 4 + SubSection.Vendor.size() + 1;
+    // optional + parameter-type
+    const size_t VendorParameters = 1 + 1;
+    const size_t ContentsSize = calculateContentSize(SubSection.Content);
+
+    emitInt32(VendorHeaderSize + VendorParameters + ContentsSize);
+    emitBytes(SubSection.Vendor);
+    emitInt8(SubSection.IsMandatory);
+    emitInt8(SubSection.ParameterType);
+
+    for (AttributeItem &Item : SubSection.Content) {
+      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;
+      }
+    }
+  }
+  SubSectionVec.clear();
+}
+
 MCStreamer *llvm::createELFStreamer(MCContext &Context,
                                     std::unique_ptr<MCAsmBackend> &&MAB,
                                     std::unique_ptr<MCObjectWriter> &&OW,
diff --git a/llvm/lib/Support/ARMBuildAttrs.cpp b/llvm/lib/Support/ARMBuildAttrs.cpp
index 815cfc62a4b0e3..96d0f312d734ce 100644
--- a/llvm/lib/Support/ARMBuildAttrs.cpp
+++ b/llvm/lib/Support/ARMBuildAttrs.cpp
@@ -6,11 +6,13 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "llvm/ADT/StringRef.h"
 #include "llvm/Support/ARMBuildAttributes.h"
 
 using namespace llvm;
 
-static const TagNameItem tagData[] = {
+namespace {
+const TagNameItem ARMAttributeTags[] = {
     {ARMBuildAttrs::File, "Tag_File"},
     {ARMBuildAttrs::Section, "Tag_Section"},
     {ARMBuildAttrs::Symbol, "Tag_Symbol"},
@@ -67,7 +69,56 @@ static const TagNameItem tagData[] = {
     {ARMBuildAttrs::ABI_align_preserved, "Tag_ABI_align8_preserved"},
 };
 
-constexpr TagNameMap ARMAttributeTags{tagData};
-const TagNameMap &llvm::ARMBuildAttrs::getARMAttributeTags() {
-  return ARMAttributeTags;
+const TagNameItem AVAttributeTags[] = {
+  { ARMBuildAttrs::AV_cpp_exceptions, "Tag_AV_cpp_exceptions" },
+  { ARMBuildAttrs::AV_eba, "Tag_AV_eba" },
+};
+
+template<typename T, size_t N> int FromString(T (&Table)[N], StringRef Tag) {
+  bool HasTagPrefix = Tag.starts_with("Tag_");
+  for (unsigned TI = 0;  TI < N; ++TI)
+    if (Table[TI].tagName.drop_front(HasTagPrefix ? 0 : 4) == Tag)
+      return Table[TI].attr;
+  return -1;
+}
+
+template<typename T, size_t N, typename A>
+StringRef AsString(T (&Table)[N], A Attr, bool HasTagPrefix) {
+  for (unsigned TI = 0; TI < N; ++TI)
+    if (Table[TI].attr == Attr)
+      return Table[TI].tagName.drop_front(HasTagPrefix ? 0 : 4);
+  return StringRef();
+}
+}
+
+namespace llvm {
+namespace ARMBuildAttrs {
+StringRef AttrTypeAsString(StringRef Vendor, unsigned Attr, bool HasTagPrefix) {
+  if (Vendor.equals_insensitive("aeabi") || Vendor.equals_insensitive("eabi"))
+    return AsString(ARMAttributeTags, static_cast<AttrType>(Attr),
+                    HasTagPrefix);
+  else if (Vendor.equals_insensitive("arm"))
+    return AsString(AVAttributeTags, static_cast<AVAttr>(Attr), HasTagPrefix);
+  return StringRef();
+}
+
+StringRef AttrTypeAsString(AttrType Attr, bool HasTagPrefix) {
+  return AsString(ARMAttributeTags, static_cast<AttrType>(Attr), HasTagPrefix);
+}
+
+StringRef AttrTypeAsString(AVAttr Attr, bool HasTagPrefix) {
+  return AsString(AVAttributeTags, static_cast<AVAttr>(Attr), HasTagPrefix);
+}
+
+int AttrTypeFromString(StringRef Vendor, StringRef Tag) {
+  if (Vendor.equals_insensitive("aeabi") || Vendor.equals_insensitive("eabi"))
+    return FromString(ARMAttributeTags, Tag);
+  else if (Vendor.equals_insensitive("arm"))
+    return FromString(AVAttributeTags, Tag);
+  return -1;
+}
+
+static constexpr TagNameMap tagNameMap(ARMAttributeTags);
+const TagNameMap &getARMAttributeTags() { return tagNameMap; }
+}
 }
diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index 4fd6b0d4311a54..f5e6a580fcd6ad 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -54,6 +54,7 @@
 #include "llvm/MC/MCStreamer.h"
 #include "llvm/MC/MCSymbol.h"
 #include "llvm/MC/TargetRegistry.h"
+#include "llvm/Support/ARMBuildAttributes.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/ErrorHandling.h"
@@ -200,6 +201,9 @@ class AArch64AsmPrinter : public AsmPrinter {
   /// pseudo instructions.
   bool lowerPseudoInstExpansion(const MachineInstr *MI, MCInst &Inst);
 
+  // Emit Build Attributes
+  void emitAttributes(unsigned Flags, uint64_t PAuthABIPlatform, uint64_t PAuthABIVersion, AArch64TargetStreamer* TS);
+
   void EmitToStreamer(MCStreamer &S, const MCInst &Inst);
   void EmitToStreamer(const MCInst &Inst) {
     EmitToStreamer(*OutStreamer, Inst);
@@ -332,36 +336,51 @@ void AArch64AsmPrinter::emitStartOfAsmFile(Module &M) {
   if (!TT.isOSBinFormatELF())
     return;
 
-  // Assemble feature flags that may require creation of a note section.
-  unsigned Flags = 0;
+  // For emitting build attributes and .note.gnu.property section
+  auto *TS = static_cast<AArch64TargetStreamer *>(OutStreamer->getTargetStreamer());
+  // Assemble feature flags that may require creation of build attributes and a note section.
+  unsigned BAFlags = 0;
+  unsigned GNUFlags = 0;
   if (const auto *BTE = mdconst::extract_or_null<ConstantInt>(
-          M.getModuleFlag("branch-target-enforcement")))
-    if (!BTE->isZero())
-      Flags |= ELF::GNU_PROPERTY_AARCH64_FEATURE_1_BTI;
+          M.getModuleFlag("branch-target-enforcement"))) {
+    if (!BTE->isZero()) {
+      BAFlags |= ARMBuildAttrs::PauthabiTagsFlag::Feature_BTI_Flag;
+      GNUFlags |= ELF::GNU_PROPERTY_AARCH64_FEATURE_1_BTI;
+    }
+  }
 
   if (const auto *GCS = mdconst::extract_or_null<ConstantInt>(
-          M.getModuleFlag("guarded-control-stack")))
-    if (!GCS->isZero())
-      Flags |= ELF::GNU_PROPERTY_AARCH64_FEATURE_1_GCS;
+          M.getModuleFlag("guarded-control-stack"))) {
+    if (!GCS->isZero()) {
+      BAFlags |= ARMBuildAttrs::PauthabiTagsFlag::Feature_GCS_Flag;
+      GNUFlags |= ELF::GNU_PROPERTY_AARCH64_FEATURE_1_GCS;
+    }
+  }
 
   if (const auto *Sign = mdconst::extract_or_null<ConstantInt>(
-          M.getModuleFlag("sign-return-address")))
-    if (!Sign->isZero())
-      Flags |= ELF::GNU_PROPERTY_AARCH64_FEATURE_1_PAC;
+          M.getModuleFlag("sign-return-address"))) {
+    if (!Sign->isZero()) {
+      BAFlags |= ARMBuildAttrs::PauthabiTagsFlag::Feature_PAC_Flag;
+      GNUFlags |= ELF::GNU_PROPERTY_AARCH64_FEATURE_1_PAC;
+    }
+  }
 
   uint64_t PAuthABIPlatform = -1;
   if (const auto *PAP = mdconst::extract_or_null<ConstantInt>(
-          M.getModuleFlag("aarch64-elf-pauthabi-platform")))
+          M.getModuleFlag("aarch64-elf-pauthabi-platform"))) {
     PAuthABIPlatform = PAP->getZExtValue();
+  }
+
   uint64_t PAuthABIVersion = -1;
   if (const auto *PAV = mdconst::extract_or_null<ConstantInt>(
-          M.getModuleFlag("aarch64-elf-pauthabi-version")))
+          M.getModuleFlag("aarch64-elf-pauthabi-version"))) {
     PAuthABIVersion = PAV->getZExtValue();
+  }
 
+  // Emit AArch64 Build Attributes
+  emitAttributes(BAFlags, PAuthABIPlatform, PAuthABIVersion, TS);
   // Emit a .note.gnu.property section with the flags.
-  auto *TS =
-      static_cast<AArch64TargetStreamer *>(OutStreamer->getTargetStreamer());
-  TS->emitNoteSection(Flags, PAuthABIPlatform, PAuthABIVersion);
+  TS->emitNoteSection(GNUFlags, PAuthABIPlatform, PAuthABIVersion);
 }
 
 void AArch64AsmPrinter::emitFunctionHeaderComment() {
@@ -434,6 +453,29 @@ void AArch64AsmPrinter::emitSled(const MachineInstr &MI, SledKind Kind) {
   recordSled(CurSled, MI, Kind, 2);
 }
 
+void AArch64AsmPrinter::emitAttributes(unsigned Flags, uint64_t PAuthABIPlatform, uint64_t PAuthABIVersion, AArch64TargetStreamer* TS) {
+
+  PAuthABIPlatform = (PAuthABIPlatform == uint64_t(-1)) ? 0 : PAuthABIPlatform;
+  PAuthABIVersion = (PAuthABIVersion == uint64_t(-1)) ? 0 : PAuthABIVersion;
+
+  if(PAuthABIPlatform || PAuthABIVersion) {
+    TS->emitSubsection(ARMBuildAttrs::AEBI_PAUTHABI, 0, 0);
+    TS->emitAttribute(ARMBuildAttrs::AEBI_PAUTHABI, ARMBuildAttrs::Tag_PAuth_Platform, PAuthABIPlatform, false);
+    TS->emitAttribute(ARMBuildAttrs::AEBI_PAUTHABI, ARMBuildAttrs::Tag_PAuth_Schema, PAuthABIVersion, false);
+  }
+
+  unsigned BTIValue = (Flags & ARMBuildAttrs::Feature_BTI_Flag) ? 1 : 0;
+  unsigned PACValue = (Flags & ARMBuildAttrs::Feature_PAC_Flag) ? 1 : 0;
+  unsigned GCSValue = (Flags & ARMBuildAttrs::Feature_GCS_Flag) ? 1 : 0;
+
+  if(BTIValue || PACValue || GCSValue) {
+    TS->emitSubsection(ARMBuildAttrs::AEBI_FEATURE_AND_BITS, 1, 0);
+    TS->emitAttribute(ARMBuildAttrs::AEBI_FEATURE_AND_BITS, ARMBuildAttrs::Tag_Feature_BTI, BTIValue, false);
+    TS->emitAttribute(ARMBuildAttrs::AEBI_FEATURE_AND_BITS, ARMBuildAttrs::Tag_Feature_PAC, PACValue, false);
+    TS->emitAttribute(ARMBuildAttrs::AEBI_FEATURE_AND_BITS, ARMBuildAttrs::Tag_Feature_GCS, GCSValue, false);
+  }
+}
+
 // Emit the following code for Intrinsic::{xray_customevent,xray_typedevent}
 // (built-in functions __xray_customevent/__xray_typedevent).
 //
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp
index 5bae846824548b..e57b0703137382 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp
@@ -33,6 +33,7 @@
 #include "llvm/MC/MCSymbolELF.h"
 #include "llvm/MC/MCTargetOptions.h"
 #include "llvm/MC/MCWinCOFFStreamer.h"
+#include "llvm/Support/ARMBuildAttributes.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/FormattedStream.h"
 #include "llvm/Support/raw_ostream.h"
@@ -45,6 +46,8 @@ class AArch64ELFStreamer;
 
 class AArch64TargetAsmStreamer : public AArch64TargetStreamer {
   formatted_raw_ostream &OS;
+  std::string VendorTag;
+  bool IsVerboseAsm;
 
   void emitInst(uint32_t Inst) override;
 
@@ -148,13 +151,80 @@ class AArch64TargetAsmStreamer : public AArch64TargetStreamer {
     OS << "\t.seh_save_any_reg_px\tq" << Reg << ", " << Offset << "\n";
   }
 
+  void emitAttribute(unsigned Vendor, unsigned Tag, unsigned Value, bool Override) override {
+    // AArch64 build attributes for assembly attribute form:
+    // .aeabi_attribute tag, value
+
+    switch(Vendor) {
+      default: llvm...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/118771


More information about the llvm-commits mailing list