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

via llvm-commits llvm-commits at lists.llvm.org
Wed Dec 18 09:22:52 PST 2024


https://github.com/sivan-shani updated https://github.com/llvm/llvm-project/pull/118771

>From a10af4639c827bd44ff25bd60b820186b5bec74f Mon Sep 17 00:00:00 2001
From: Sivan Shani <sivan.shani at arm.com>
Date: Wed, 4 Dec 2024 20:08:20 +0000
Subject: [PATCH 01/12] [LLVM][Clang][AArch64] Implement AArch64 build
 attributes

- 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
---
 llvm/include/llvm/BinaryFormat/ELF.h          |   2 +
 llvm/include/llvm/MC/MCELFStreamer.h          |  27 +++-
 .../include/llvm/Support/ARMBuildAttributes.h |  63 +++++++++
 llvm/lib/MC/MCELFStreamer.cpp                 |  76 +++++++++--
 llvm/lib/Support/ARMBuildAttrs.cpp            |  59 ++++++++-
 llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp |  74 ++++++++---
 .../MCTargetDesc/AArch64ELFStreamer.cpp       | 122 +++++++++++++++++-
 .../MCTargetDesc/AArch64TargetStreamer.h      |  23 +++-
 .../ARM/MCTargetDesc/ARMELFStreamer.cpp       | 116 ++++++++---------
 .../MCTargetDesc/HexagonMCTargetDesc.cpp      |   2 +-
 .../RISCV/MCTargetDesc/RISCVELFStreamer.cpp   |   6 +-
 11 files changed, 472 insertions(+), 98 deletions(-)

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_unreachable("unknown AArch64 build attributes subsection name");
+
+      case ARMBuildAttrs::AEBI_FEATURE_AND_BITS:
+        switch(Tag) {
+          default: llvm_unreachable("unknown tag for the feature-and-bits subsection");
+          case ARMBuildAttrs::Tag_Feature_BTI:
+            OS << "\t.aeabi_attribute\t" << "Tag_Feature_BTI" << ", " << Value;
+            break;
+          case ARMBuildAttrs::Tag_Feature_GCS:
+            OS << "\t.aeabi_attribute\t" << "Tag_Feature_GCS" << ", " << Value;
+            break;
+          case ARMBuildAttrs::Tag_Feature_PAC:
+            OS << "\t.aeabi_attribute\t" << "Tag_Feature_PAC" << ", " << Value;
+            break;
+        }
+        break;
+
+      case ARMBuildAttrs::AEBI_PAUTHABI:
+        switch(Tag) {
+          default: llvm_unreachable("unknown tag for the feature-and-bits subsection");
+          case ARMBuildAttrs::Tag_PAuth_Platform:
+            OS << "\t.aeabi_attribute\t" << "Tag_PAuth_Platform" << ", " << Value;
+            break;
+          case ARMBuildAttrs::Tag_PAuth_Schema:
+            OS << "\t.aeabi_attribute\t" << "Tag_PAuth_Schema" << ", " << Value;
+            break;
+        break;
+        }
+    }
+    OS << "\n";
+  }
+
+  void emitSubsection(unsigned SubsectionName, unsigned Optional, unsigned ParameterType) override {
+    // The AArch64 build attributes assembly subsection header format:
+    // ".aeabi_subsection name, optional, parameter type"
+    // optional: required (0) optional (1)
+    // parameter type: uleb128 or ULEB128 (0) ntbs or NTBS (1)
+
+    assert((Optional == 0 || Optional == 1) && "unsupported parameter for Optional");
+    assert((ParameterType == 0 || ParameterType == 1) && "unsupported parameter for ParameterType");
+
+    StringRef OptionalStr = Optional ? "optional" : "required";
+    StringRef ParameterStr = ParameterType ? "NTBS" : "ULEB128";
+
+    switch(SubsectionName) {
+      default: llvm_unreachable("unknown AArch64 build attributes subsection name");
+
+      case ARMBuildAttrs::AEBI_FEATURE_AND_BITS:
+        assert(Optional == 1 && "subsection .aeabi-feature-and-bits should be marked as optional and not as mandatory");
+        assert(ParameterType == 0 && "subsection .aeabi-feature-and-bits should be marked as uleb128 and not as ntbs");
+        OS << "\t.aeabi_subsection\t" << ".aeabi-feature-and-bits" << ", " << OptionalStr << ", " << ParameterStr;
+        break;
+
+      case ARMBuildAttrs::AEBI_PAUTHABI:
+        assert(Optional == 0 && "subsection .aeabi-pauthabi should be marked as mandatory and not as optional");
+        assert(ParameterType == 0 && "subsection .aeabi-pauthabi should be marked as uleb128 and not as ntbs");
+        OS << "\t.aeabi_subsection\t" << ".aeabi-pauthabi" << ", " << OptionalStr << ", " << ParameterStr;
+        break;
+    }
+    OS << "\n";
+  }
+
 public:
   AArch64TargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS);
 };
 
 AArch64TargetAsmStreamer::AArch64TargetAsmStreamer(MCStreamer &S,
                                                    formatted_raw_ostream &OS)
-  : AArch64TargetStreamer(S), OS(OS) {}
+  : AArch64TargetStreamer(S), OS(OS), VendorTag("eabi"), IsVerboseAsm(S.isVerboseAsm()) {}
 
 void AArch64TargetAsmStreamer::emitInst(uint32_t Inst) {
   OS << "\t.inst\t0x" << Twine::utohexstr(Inst) << "\n";
@@ -294,6 +364,53 @@ AArch64ELFStreamer &AArch64TargetELFStreamer::getStreamer() {
   return static_cast<AArch64ELFStreamer &>(Streamer);
 }
 
+void AArch64TargetELFStreamer::emitSubsection(unsigned Vendor, unsigned IsMandatory, unsigned ParameterType) {
+  StringRef VendorAsStr = ARMBuildAttrs::vendorToStr(Vendor);
+
+  // If exists, return.
+  for (MCELFStreamer::AttributeSubSection &SubSection : AttributeSubSections) {
+    if (SubSection.Vendor == VendorAsStr) {
+      llvm_unreachable("AArch64 build attributes subsection already exists");
+      return;
+    }
+  }
+  // else, add the subsection
+  MCELFStreamer::AttributeSubSection AttSubSection;
+  AttSubSection.Vendor = VendorAsStr;
+  AttSubSection.IsMandatory = IsMandatory;
+  AttSubSection.ParameterType = ParameterType;
+  AttributeSubSections.push_back(AttSubSection);
+}
+
+void AArch64TargetELFStreamer::emitAttribute(unsigned Vendor, unsigned Tag, unsigned Value, bool Override) {
+  StringRef VendorAsStr = ARMBuildAttrs::vendorToStr(Vendor);
+
+  if (AttributeSubSections.size() == 0) {
+    llvm_unreachable("Attribute can not be added unless the required AArch64 build attributes subsection exists");
+    return;
+  }
+
+  for (MCELFStreamer::AttributeSubSection &SubSection : AttributeSubSections) {
+    if (SubSection.Vendor == VendorAsStr) {
+      for (MCELFStreamer::AttributeItem &Item : SubSection.Content) {
+        if (Item.Tag == Tag) {
+          if (!Override) {
+            llvm_unreachable("Attribute exists but override is set to false");
+            return;
+          }
+        }
+      }
+      MCELFStreamer::AttributeItem AttItem;
+      AttItem.Type = AttItem.NumericAttribute;
+      AttItem.Tag = Tag;
+      AttItem.IntValue = Value;
+      SubSection.Content.push_back(AttItem);
+      return;
+    }
+  }
+  llvm_unreachable("Attribute can not be added unless the required AArch64 build attributes subsection exists");
+}
+
 void AArch64TargetELFStreamer::emitInst(uint32_t Inst) {
   getStreamer().emitInst(Inst);
 }
@@ -309,6 +426,9 @@ void AArch64TargetELFStreamer::finish() {
   MCContext &Ctx = S.getContext();
   auto &Asm = S.getAssembler();
 
+  S.emitAttributesSection(AttributeSection, ".ARM.attributes",
+                          ELF::SHT_AARCH64_ATTRIBUTES, AttributeSubSections);
+
   // If ImplicitMapSyms is specified, ensure that text sections end with
   // the A64 state while non-text sections end with the data state. When
   // sections are combined by the linker, the subsequent section will start with
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h
index ac441ae3b603ff..7d90759cfc6e10 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h
@@ -9,7 +9,15 @@
 #ifndef LLVM_LIB_TARGET_AARCH64_MCTARGETDESC_AARCH64TARGETSTREAMER_H
 #define LLVM_LIB_TARGET_AARCH64_MCTARGETDESC_AARCH64TARGETSTREAMER_H
 
+#include "llvm/ADT/StringRef.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/MC/MCELFStreamer.h"
 #include "llvm/MC/MCStreamer.h"
+#include "llvm/Support/ARMBuildAttributes.h"
+#include "llvm/TableGen/Record.h"
+#include <cstddef>
+#include <cstdint>
+#include <utility>
 
 namespace {
 class AArch64ELFStreamer;
@@ -83,20 +91,33 @@ class AArch64TargetStreamer : public MCTargetStreamer {
   virtual void emitARM64WinCFISaveAnyRegQX(unsigned Reg, int Offset) {}
   virtual void emitARM64WinCFISaveAnyRegQPX(unsigned Reg, int Offset) {}
 
+  /// Build attributes implementation
+  virtual void emitSubsection(unsigned Vendor, unsigned IsMandatory, unsigned ParameterType) {}
+  virtual void emitAttribute(unsigned Vendor, unsigned Tag, unsigned Value, bool Override) {}
+
 private:
   std::unique_ptr<AssemblerConstantPools> ConstantPools;
 };
 
 class AArch64TargetELFStreamer : public AArch64TargetStreamer {
 private:
+  StringRef CurrentVendor;
   AArch64ELFStreamer &getStreamer();
 
+  MCSection *AttributeSection = nullptr;
+  SmallVector<MCELFStreamer::AttributeSubSection, 64> AttributeSubSections;
+
+  /// Build attributes implementation
+  void emitSubsection(unsigned Vendor, unsigned IsMandatory, unsigned ParameterType) override;
+  void emitAttribute(unsigned Vendor, unsigned Tag, unsigned Value, bool Override) override;
+
   void emitInst(uint32_t Inst) override;
   void emitDirectiveVariantPCS(MCSymbol *Symbol) override;
   void finish() override;
 
 public:
-  AArch64TargetELFStreamer(MCStreamer &S) : AArch64TargetStreamer(S) {}
+  AArch64TargetELFStreamer(MCStreamer &S)
+    : AArch64TargetStreamer(S), CurrentVendor("aeabi") {}
 };
 
 class AArch64TargetWinCOFFStreamer : public llvm::AArch64TargetStreamer {
diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp
index c528526382a2b4..b6a16de748d9b0 100644
--- a/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp
+++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp
@@ -793,20 +793,20 @@ void ARMTargetELFStreamer::switchVendor(StringRef Vendor) {
 
 void ARMTargetELFStreamer::emitAttribute(unsigned Attribute, unsigned Value) {
   getStreamer().setAttributeItem(Attribute, Value,
-                                 /* OverwriteExisting= */ true);
+                                 /* OverwriteExisting= */ true, getStreamer().Contents);
 }
 
 void ARMTargetELFStreamer::emitTextAttribute(unsigned Attribute,
                                              StringRef Value) {
   getStreamer().setAttributeItem(Attribute, Value,
-                                 /* OverwriteExisting= */ true);
+                                 /* OverwriteExisting= */ true, getStreamer().Contents);
 }
 
 void ARMTargetELFStreamer::emitIntTextAttribute(unsigned Attribute,
                                                 unsigned IntValue,
                                                 StringRef StringValue) {
   getStreamer().setAttributeItems(Attribute, IntValue, StringValue,
-                                  /* OverwriteExisting= */ true);
+                                  /* OverwriteExisting= */ true, getStreamer().Contents);
 }
 
 void ARMTargetELFStreamer::emitArch(ARM::ArchKind Value) {
@@ -821,16 +821,16 @@ void ARMTargetELFStreamer::emitArchDefaultAttributes() {
   using namespace ARMBuildAttrs;
   ARMELFStreamer &S = getStreamer();
 
-  S.setAttributeItem(CPU_name, ARM::getCPUAttr(Arch), false);
+  S.setAttributeItem(CPU_name, ARM::getCPUAttr(Arch), false, getStreamer().Contents);
 
   if (EmittedArch == ARM::ArchKind::INVALID)
-    S.setAttributeItem(CPU_arch, ARM::getArchAttr(Arch), false);
+    S.setAttributeItem(CPU_arch, ARM::getArchAttr(Arch), false, getStreamer().Contents);
   else
-    S.setAttributeItem(CPU_arch, ARM::getArchAttr(EmittedArch), false);
+    S.setAttributeItem(CPU_arch, ARM::getArchAttr(EmittedArch), false, getStreamer().Contents);
 
   switch (Arch) {
   case ARM::ArchKind::ARMV4:
-    S.setAttributeItem(ARM_ISA_use, Allowed, false);
+    S.setAttributeItem(ARM_ISA_use, Allowed, false, getStreamer().Contents);
     break;
 
   case ARM::ArchKind::ARMV4T:
@@ -838,42 +838,42 @@ void ARMTargetELFStreamer::emitArchDefaultAttributes() {
   case ARM::ArchKind::XSCALE:
   case ARM::ArchKind::ARMV5TE:
   case ARM::ArchKind::ARMV6:
-    S.setAttributeItem(ARM_ISA_use, Allowed, false);
-    S.setAttributeItem(THUMB_ISA_use, Allowed, false);
+    S.setAttributeItem(ARM_ISA_use, Allowed, false, getStreamer().Contents);
+    S.setAttributeItem(THUMB_ISA_use, Allowed, false, getStreamer().Contents);
     break;
 
   case ARM::ArchKind::ARMV6T2:
-    S.setAttributeItem(ARM_ISA_use, Allowed, false);
-    S.setAttributeItem(THUMB_ISA_use, AllowThumb32, false);
+    S.setAttributeItem(ARM_ISA_use, Allowed, false,getStreamer().Contents);
+    S.setAttributeItem(THUMB_ISA_use, AllowThumb32, false, getStreamer().Contents);
     break;
 
   case ARM::ArchKind::ARMV6K:
   case ARM::ArchKind::ARMV6KZ:
-    S.setAttributeItem(ARM_ISA_use, Allowed, false);
-    S.setAttributeItem(THUMB_ISA_use, Allowed, false);
-    S.setAttributeItem(Virtualization_use, AllowTZ, false);
+    S.setAttributeItem(ARM_ISA_use, Allowed, false, getStreamer().Contents);
+    S.setAttributeItem(THUMB_ISA_use, Allowed, false, getStreamer().Contents);
+    S.setAttributeItem(Virtualization_use, AllowTZ, false, getStreamer().Contents);
     break;
 
   case ARM::ArchKind::ARMV6M:
-    S.setAttributeItem(THUMB_ISA_use, Allowed, false);
+    S.setAttributeItem(THUMB_ISA_use, Allowed, false, getStreamer().Contents);
     break;
 
   case ARM::ArchKind::ARMV7A:
-    S.setAttributeItem(CPU_arch_profile, ApplicationProfile, false);
-    S.setAttributeItem(ARM_ISA_use, Allowed, false);
-    S.setAttributeItem(THUMB_ISA_use, AllowThumb32, false);
+    S.setAttributeItem(CPU_arch_profile, ApplicationProfile, false, getStreamer().Contents);
+    S.setAttributeItem(ARM_ISA_use, Allowed, false, getStreamer().Contents);
+    S.setAttributeItem(THUMB_ISA_use, AllowThumb32, false, getStreamer().Contents);
     break;
 
   case ARM::ArchKind::ARMV7R:
-    S.setAttributeItem(CPU_arch_profile, RealTimeProfile, false);
-    S.setAttributeItem(ARM_ISA_use, Allowed, false);
-    S.setAttributeItem(THUMB_ISA_use, AllowThumb32, false);
+    S.setAttributeItem(CPU_arch_profile, RealTimeProfile, false, getStreamer().Contents);
+    S.setAttributeItem(ARM_ISA_use, Allowed, false, getStreamer().Contents);
+    S.setAttributeItem(THUMB_ISA_use, AllowThumb32, false, getStreamer().Contents);
     break;
 
   case ARM::ArchKind::ARMV7EM:
   case ARM::ArchKind::ARMV7M:
-    S.setAttributeItem(CPU_arch_profile, MicroControllerProfile, false);
-    S.setAttributeItem(THUMB_ISA_use, AllowThumb32, false);
+    S.setAttributeItem(CPU_arch_profile, MicroControllerProfile, false, getStreamer().Contents);
+    S.setAttributeItem(THUMB_ISA_use, AllowThumb32, false, getStreamer().Contents);
     break;
 
   case ARM::ArchKind::ARMV8A:
@@ -893,29 +893,29 @@ void ARMTargetELFStreamer::emitArchDefaultAttributes() {
   case ARM::ArchKind::ARMV9_4A:
   case ARM::ArchKind::ARMV9_5A:
   case ARM::ArchKind::ARMV9_6A:
-    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);
+    S.setAttributeItem(CPU_arch_profile, ApplicationProfile, false, getStreamer().Contents);
+    S.setAttributeItem(ARM_ISA_use, Allowed, false, getStreamer().Contents);
+    S.setAttributeItem(THUMB_ISA_use, AllowThumb32, false, getStreamer().Contents);
+    S.setAttributeItem(MPextension_use, Allowed, false, getStreamer().Contents);
+    S.setAttributeItem(Virtualization_use, AllowTZVirtualization, false, getStreamer().Contents);
     break;
 
   case ARM::ArchKind::ARMV8MBaseline:
   case ARM::ArchKind::ARMV8MMainline:
-    S.setAttributeItem(THUMB_ISA_use, AllowThumbDerived, false);
-    S.setAttributeItem(CPU_arch_profile, MicroControllerProfile, false);
+    S.setAttributeItem(THUMB_ISA_use, AllowThumbDerived, false, getStreamer().Contents);
+    S.setAttributeItem(CPU_arch_profile, MicroControllerProfile, false, getStreamer().Contents);
     break;
 
   case ARM::ArchKind::IWMMXT:
-    S.setAttributeItem(ARM_ISA_use, Allowed, false);
-    S.setAttributeItem(THUMB_ISA_use, Allowed, false);
-    S.setAttributeItem(WMMX_arch, AllowWMMXv1, false);
+    S.setAttributeItem(ARM_ISA_use, Allowed, false, getStreamer().Contents);
+    S.setAttributeItem(THUMB_ISA_use, Allowed, false, getStreamer().Contents);
+    S.setAttributeItem(WMMX_arch, AllowWMMXv1, false, getStreamer().Contents);
     break;
 
   case ARM::ArchKind::IWMMXT2:
-    S.setAttributeItem(ARM_ISA_use, Allowed, false);
-    S.setAttributeItem(THUMB_ISA_use, Allowed, false);
-    S.setAttributeItem(WMMX_arch, AllowWMMXv2, false);
+    S.setAttributeItem(ARM_ISA_use, Allowed, false, getStreamer().Contents);
+    S.setAttributeItem(THUMB_ISA_use, Allowed, false, getStreamer().Contents);
+    S.setAttributeItem(WMMX_arch, AllowWMMXv2, false, getStreamer().Contents);
     break;
 
   default:
@@ -933,47 +933,47 @@ void ARMTargetELFStreamer::emitFPUDefaultAttributes() {
   case ARM::FK_VFP:
   case ARM::FK_VFPV2:
     S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv2,
-                       /* OverwriteExisting= */ false);
+                       /* OverwriteExisting= */ false, getStreamer().Contents);
     break;
 
   case ARM::FK_VFPV3:
     S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv3A,
-                       /* OverwriteExisting= */ false);
+                       /* OverwriteExisting= */ false, getStreamer().Contents);
     break;
 
   case ARM::FK_VFPV3_FP16:
     S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv3A,
-                       /* OverwriteExisting= */ false);
+                       /* OverwriteExisting= */ false, getStreamer().Contents);
     S.setAttributeItem(ARMBuildAttrs::FP_HP_extension, ARMBuildAttrs::AllowHPFP,
-                       /* OverwriteExisting= */ false);
+                       /* OverwriteExisting= */ false, getStreamer().Contents);
     break;
 
   case ARM::FK_VFPV3_D16:
     S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv3B,
-                       /* OverwriteExisting= */ false);
+                       /* OverwriteExisting= */ false, getStreamer().Contents);
     break;
 
   case ARM::FK_VFPV3_D16_FP16:
     S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv3B,
-                       /* OverwriteExisting= */ false);
+                       /* OverwriteExisting= */ false, getStreamer().Contents);
     S.setAttributeItem(ARMBuildAttrs::FP_HP_extension, ARMBuildAttrs::AllowHPFP,
-                       /* OverwriteExisting= */ false);
+                       /* OverwriteExisting= */ false, getStreamer().Contents);
     break;
 
   case ARM::FK_VFPV3XD:
     S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv3B,
-                       /* OverwriteExisting= */ false);
+                       /* OverwriteExisting= */ false, getStreamer().Contents);
     break;
   case ARM::FK_VFPV3XD_FP16:
     S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv3B,
-                       /* OverwriteExisting= */ false);
+                       /* OverwriteExisting= */ false, getStreamer().Contents);
     S.setAttributeItem(ARMBuildAttrs::FP_HP_extension, ARMBuildAttrs::AllowHPFP,
-                       /* OverwriteExisting= */ false);
+                       /* OverwriteExisting= */ false, getStreamer().Contents);
     break;
 
   case ARM::FK_VFPV4:
     S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv4A,
-                       /* OverwriteExisting= */ false);
+                       /* OverwriteExisting= */ false, getStreamer().Contents);
     break;
 
   // ABI_HardFP_use is handled in ARMAsmPrinter, so _SP_D16 is treated the same
@@ -981,12 +981,12 @@ void ARMTargetELFStreamer::emitFPUDefaultAttributes() {
   case ARM::FK_FPV4_SP_D16:
   case ARM::FK_VFPV4_D16:
     S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv4B,
-                       /* OverwriteExisting= */ false);
+                       /* OverwriteExisting= */ false, getStreamer().Contents);
     break;
 
   case ARM::FK_FP_ARMV8:
     S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPARMv8A,
-                       /* OverwriteExisting= */ false);
+                       /* OverwriteExisting= */ false, getStreamer().Contents);
     break;
 
   // FPV5_D16 is identical to FP_ARMV8 except for the number of D registers, so
@@ -998,39 +998,39 @@ void ARMTargetELFStreamer::emitFPUDefaultAttributes() {
   case ARM::FK_FP_ARMV8_FULLFP16_SP_D16:
   case ARM::FK_FP_ARMV8_FULLFP16_D16:
     S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPARMv8B,
-                       /* OverwriteExisting= */ false);
+                       /* OverwriteExisting= */ false, getStreamer().Contents);
     break;
 
   case ARM::FK_NEON:
     S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv3A,
-                       /* OverwriteExisting= */ false);
+                       /* OverwriteExisting= */ false, getStreamer().Contents);
     S.setAttributeItem(ARMBuildAttrs::Advanced_SIMD_arch,
                        ARMBuildAttrs::AllowNeon,
-                       /* OverwriteExisting= */ false);
+                       /* OverwriteExisting= */ false, getStreamer().Contents);
     break;
 
   case ARM::FK_NEON_FP16:
     S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv3A,
-                       /* OverwriteExisting= */ false);
+                       /* OverwriteExisting= */ false, getStreamer().Contents);
     S.setAttributeItem(ARMBuildAttrs::Advanced_SIMD_arch,
                        ARMBuildAttrs::AllowNeon,
-                       /* OverwriteExisting= */ false);
+                       /* OverwriteExisting= */ false, getStreamer().Contents);
     S.setAttributeItem(ARMBuildAttrs::FP_HP_extension, ARMBuildAttrs::AllowHPFP,
-                       /* OverwriteExisting= */ false);
+                       /* OverwriteExisting= */ false, getStreamer().Contents);
     break;
 
   case ARM::FK_NEON_VFPV4:
     S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv4A,
-                       /* OverwriteExisting= */ false);
+                       /* OverwriteExisting= */ false, getStreamer().Contents);
     S.setAttributeItem(ARMBuildAttrs::Advanced_SIMD_arch,
                        ARMBuildAttrs::AllowNeon2,
-                       /* OverwriteExisting= */ false);
+                       /* OverwriteExisting= */ false, getStreamer().Contents);
     break;
 
   case ARM::FK_NEON_FP_ARMV8:
   case ARM::FK_CRYPTO_NEON_FP_ARMV8:
     S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPARMv8A,
-                       /* OverwriteExisting= */ false);
+                       /* OverwriteExisting= */ false, getStreamer().Contents);
     // 'Advanced_SIMD_arch' must be emitted not here, but within
     // ARMAsmPrinter::emitAttributes(), depending on hasV8Ops() and hasV8_1a()
     break;
diff --git a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp
index aa86b2df856296..d8a177a90a7a3d 100644
--- a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp
+++ b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp
@@ -330,7 +330,7 @@ class HexagonTargetELFStreamer : public HexagonTargetStreamer {
 
   void emitAttribute(uint32_t Attribute, uint32_t Value) override {
     getStreamer().setAttributeItem(Attribute, Value,
-                                   /*OverwriteExisting=*/true);
+                                   /*OverwriteExisting=*/true, getStreamer().Contents);
   }
 };
 
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp
index ea0e9fcde21cf9..ae536accb399a2 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp
@@ -57,19 +57,19 @@ void RISCVTargetELFStreamer::emitDirectiveOptionRelax() {}
 void RISCVTargetELFStreamer::emitDirectiveOptionNoRelax() {}
 
 void RISCVTargetELFStreamer::emitAttribute(unsigned Attribute, unsigned Value) {
-  getStreamer().setAttributeItem(Attribute, Value, /*OverwriteExisting=*/true);
+  getStreamer().setAttributeItem(Attribute, Value, /*OverwriteExisting=*/true, getStreamer().Contents);
 }
 
 void RISCVTargetELFStreamer::emitTextAttribute(unsigned Attribute,
                                                StringRef String) {
-  getStreamer().setAttributeItem(Attribute, String, /*OverwriteExisting=*/true);
+  getStreamer().setAttributeItem(Attribute, String, /*OverwriteExisting=*/true, getStreamer().Contents);
 }
 
 void RISCVTargetELFStreamer::emitIntTextAttribute(unsigned Attribute,
                                                   unsigned IntValue,
                                                   StringRef StringValue) {
   getStreamer().setAttributeItems(Attribute, IntValue, StringValue,
-                                  /*OverwriteExisting=*/true);
+                                  /*OverwriteExisting=*/true, getStreamer().Contents);
 }
 
 void RISCVTargetELFStreamer::finishAttributeSection() {

>From c1c4c469b3e46e8777d3c9ca2d8ada5838e82b6b Mon Sep 17 00:00:00 2001
From: Sivan Shani <sivan.shani at arm.com>
Date: Thu, 5 Dec 2024 10:53:07 +0000
Subject: [PATCH 02/12] Formatting

---
 llvm/include/llvm/MC/MCELFStreamer.h          |  30 +++--
 .../include/llvm/Support/ARMBuildAttributes.h |  43 +++----
 llvm/lib/MC/MCELFStreamer.cpp                 |  68 +++++-----
 llvm/lib/Support/ARMBuildAttrs.cpp            |  16 +--
 llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp |  34 +++--
 .../MCTargetDesc/AArch64ELFStreamer.cpp       | 116 ++++++++++--------
 .../MCTargetDesc/AArch64TargetStreamer.h      |  14 ++-
 .../ARM/MCTargetDesc/ARMELFStreamer.cpp       |  59 ++++++---
 .../MCTargetDesc/HexagonMCTargetDesc.cpp      |   3 +-
 .../RISCV/MCTargetDesc/RISCVELFStreamer.cpp   |   9 +-
 10 files changed, 226 insertions(+), 166 deletions(-)

diff --git a/llvm/include/llvm/MC/MCELFStreamer.h b/llvm/include/llvm/MC/MCELFStreamer.h
index 351c7ddd3b7380..0e37948d3d2b7f 100644
--- a/llvm/include/llvm/MC/MCELFStreamer.h
+++ b/llvm/include/llvm/MC/MCELFStreamer.h
@@ -113,36 +113,46 @@ class MCELFStreamer : public MCObjectStreamer {
     // [<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)
+    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, SmallVector<AttributeItem, 64> &Attributes);
+                        bool OverwriteExisting,
+                        SmallVector<AttributeItem, 64> &Attributes);
   void setAttributeItem(unsigned Attribute, StringRef Value,
-                        bool OverwriteExisting, SmallVector<AttributeItem, 64> &Attributes);
+                        bool OverwriteExisting,
+                        SmallVector<AttributeItem, 64> &Attributes);
   void setAttributeItems(unsigned Attribute, unsigned IntValue,
-                         StringRef StringValue, bool OverwriteExisting, SmallVector<AttributeItem, 64> &Attributes);
+                         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) {
+  void
+  emitAttributesSection(MCSection *&AttributeSection, const Twine &Section,
+                        unsigned Type,
+                        SmallVector<AttributeSubSection, 64> &SubSectionVec) {
     createAttributesSection(AttributeSection, Section, Type, SubSectionVec);
   }
 
 private:
-  AttributeItem *getAttributeItem(unsigned Attribute, SmallVector<AttributeItem, 64> &Attributes);
+  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);
+  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 5e17ccf835190f..788d72977d6f05 100644
--- a/llvm/include/llvm/Support/ARMBuildAttributes.h
+++ b/llvm/include/llvm/Support/ARMBuildAttributes.h
@@ -28,32 +28,23 @@ namespace ARMBuildAttrs {
 const TagNameMap &getARMAttributeTags();
 
 /// AArch64 build attributes vendors (=subsection name)
-enum Vendor : unsigned {
-  AEBI_FEATURE_AND_BITS = 0,
-  AEBI_PAUTHABI = 1
-};
+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";
+  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 SubsectionMandatory : unsigned { OPTIONAL = 0, REQUIRED = 1 };
 
-enum SubsectionType : unsigned {
-  ULEB128 = 0,
-  NTBS = 1
-};
+enum SubsectionType : unsigned { ULEB128 = 0, NTBS = 1 };
 
 enum FeatureAndBitsTags : unsigned {
   Tag_PAuth_Platform = 1,
@@ -136,20 +127,16 @@ enum AttrType : unsigned {
   MPextension_use_old = 70   // recoded to MPextension_use (ABI r2.08)
 };
 
-enum AVAttr {
-  AV_cpp_exceptions         = 6,
-  AV_eba                    = 16
-};
+enum AVAttr { AV_cpp_exceptions = 6, AV_eba = 16 };
 
-StringRef AttrTypeAsString(StringRef Vendor, unsigned Attr, bool HasTagPrefix = true);
+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
-};
+enum AttrMagic { Format_Version = 0x41 };
 
 // Legal Values for CPU_arch, (=6), uleb128
 enum CPUArch {
diff --git a/llvm/lib/MC/MCELFStreamer.cpp b/llvm/lib/MC/MCELFStreamer.cpp
index 34a7367a18f44c..576d4997a3dea7 100644
--- a/llvm/lib/MC/MCELFStreamer.cpp
+++ b/llvm/lib/MC/MCELFStreamer.cpp
@@ -635,8 +635,9 @@ void MCELFStreamer::emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
   llvm_unreachable("ELF doesn't support this directive");
 }
 
-void MCELFStreamer::setAttributeItem(unsigned Attribute, unsigned Value,
-                                     bool OverwriteExisting, SmallVector<AttributeItem, 64> &Attributes) {
+void MCELFStreamer::setAttributeItem(
+    unsigned Attribute, unsigned Value, bool OverwriteExisting,
+    SmallVector<AttributeItem, 64> &Attributes) {
   // Look for existing attribute item
   if (AttributeItem *Item = getAttributeItem(Attribute, Attributes)) {
     if (!OverwriteExisting)
@@ -652,8 +653,9 @@ void MCELFStreamer::setAttributeItem(unsigned Attribute, unsigned Value,
   Contents.push_back(Item);
 }
 
-void MCELFStreamer::setAttributeItem(unsigned Attribute, StringRef Value,
-                                     bool OverwriteExisting, SmallVector<AttributeItem, 64> &Attributes) {
+void MCELFStreamer::setAttributeItem(
+    unsigned Attribute, StringRef Value, bool OverwriteExisting,
+    SmallVector<AttributeItem, 64> &Attributes) {
   // Look for existing attribute item
   if (AttributeItem *Item = getAttributeItem(Attribute, Attributes)) {
     if (!OverwriteExisting)
@@ -669,9 +671,9 @@ void MCELFStreamer::setAttributeItem(unsigned Attribute, StringRef Value,
   Contents.push_back(Item);
 }
 
-void MCELFStreamer::setAttributeItems(unsigned Attribute, unsigned IntValue,
-                                      StringRef StringValue,
-                                      bool OverwriteExisting, SmallVector<AttributeItem, 64> &Attributes) {
+void MCELFStreamer::setAttributeItems(
+    unsigned Attribute, unsigned IntValue, StringRef StringValue,
+    bool OverwriteExisting, SmallVector<AttributeItem, 64> &Attributes) {
   // Look for existing attribute item
   if (AttributeItem *Item = getAttributeItem(Attribute, Attributes)) {
     if (!OverwriteExisting)
@@ -689,15 +691,16 @@ void MCELFStreamer::setAttributeItems(unsigned Attribute, unsigned IntValue,
 }
 
 MCELFStreamer::AttributeItem *
-MCELFStreamer::getAttributeItem(unsigned Attribute, SmallVector<AttributeItem, 64> &Attributes) {
+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) const {
+size_t MCELFStreamer::calculateContentSize(
+    SmallVector<AttributeItem, 64> &AttrsVec) const {
   size_t Result = 0;
   for (const AttributeItem &Item : AttrsVec) {
     switch (Item.Type) {
@@ -783,14 +786,15 @@ 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>*
+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;
   }
@@ -821,20 +825,20 @@ void MCELFStreamer::createAttributesSection(MCSection *&AttributeSection,
     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;
+      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;
       }
     }
   }
diff --git a/llvm/lib/Support/ARMBuildAttrs.cpp b/llvm/lib/Support/ARMBuildAttrs.cpp
index 96d0f312d734ce..457e7d66a7e87a 100644
--- a/llvm/lib/Support/ARMBuildAttrs.cpp
+++ b/llvm/lib/Support/ARMBuildAttrs.cpp
@@ -70,26 +70,26 @@ const TagNameItem ARMAttributeTags[] = {
 };
 
 const TagNameItem AVAttributeTags[] = {
-  { ARMBuildAttrs::AV_cpp_exceptions, "Tag_AV_cpp_exceptions" },
-  { ARMBuildAttrs::AV_eba, "Tag_AV_eba" },
+    {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) {
+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)
+  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>
+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
 
 namespace llvm {
 namespace ARMBuildAttrs {
@@ -120,5 +120,5 @@ int AttrTypeFromString(StringRef Vendor, StringRef Tag) {
 
 static constexpr TagNameMap tagNameMap(ARMAttributeTags);
 const TagNameMap &getARMAttributeTags() { return tagNameMap; }
-}
-}
+} // namespace ARMBuildAttrs
+} // namespace llvm
diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index f5e6a580fcd6ad..ca60e249e14214 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -202,7 +202,8 @@ class AArch64AsmPrinter : public AsmPrinter {
   bool lowerPseudoInstExpansion(const MachineInstr *MI, MCInst &Inst);
 
   // Emit Build Attributes
-  void emitAttributes(unsigned Flags, uint64_t PAuthABIPlatform, uint64_t PAuthABIVersion, AArch64TargetStreamer* TS);
+  void emitAttributes(unsigned Flags, uint64_t PAuthABIPlatform,
+                      uint64_t PAuthABIVersion, AArch64TargetStreamer *TS);
 
   void EmitToStreamer(MCStreamer &S, const MCInst &Inst);
   void EmitToStreamer(const MCInst &Inst) {
@@ -337,8 +338,10 @@ void AArch64AsmPrinter::emitStartOfAsmFile(Module &M) {
     return;
 
   // 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.
+  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>(
@@ -453,26 +456,35 @@ 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) {
+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) {
+  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);
+    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) {
+  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);
+    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);
   }
 }
 
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp
index e57b0703137382..cb594785a09d2f 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp
@@ -151,69 +151,83 @@ 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 {
+  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_unreachable("unknown AArch64 build attributes subsection name");
-
-      case ARMBuildAttrs::AEBI_FEATURE_AND_BITS:
-        switch(Tag) {
-          default: llvm_unreachable("unknown tag for the feature-and-bits subsection");
-          case ARMBuildAttrs::Tag_Feature_BTI:
-            OS << "\t.aeabi_attribute\t" << "Tag_Feature_BTI" << ", " << Value;
-            break;
-          case ARMBuildAttrs::Tag_Feature_GCS:
-            OS << "\t.aeabi_attribute\t" << "Tag_Feature_GCS" << ", " << Value;
-            break;
-          case ARMBuildAttrs::Tag_Feature_PAC:
-            OS << "\t.aeabi_attribute\t" << "Tag_Feature_PAC" << ", " << Value;
-            break;
-        }
+    switch (Vendor) {
+    default:
+      llvm_unreachable("unknown AArch64 build attributes subsection name");
+
+    case ARMBuildAttrs::AEBI_FEATURE_AND_BITS:
+      switch (Tag) {
+      default:
+        llvm_unreachable("unknown tag for the feature-and-bits subsection");
+      case ARMBuildAttrs::Tag_Feature_BTI:
+        OS << "\t.aeabi_attribute\t" << "Tag_Feature_BTI" << ", " << Value;
+        break;
+      case ARMBuildAttrs::Tag_Feature_GCS:
+        OS << "\t.aeabi_attribute\t" << "Tag_Feature_GCS" << ", " << Value;
+        break;
+      case ARMBuildAttrs::Tag_Feature_PAC:
+        OS << "\t.aeabi_attribute\t" << "Tag_Feature_PAC" << ", " << Value;
         break;
+      }
+      break;
 
-      case ARMBuildAttrs::AEBI_PAUTHABI:
-        switch(Tag) {
-          default: llvm_unreachable("unknown tag for the feature-and-bits subsection");
-          case ARMBuildAttrs::Tag_PAuth_Platform:
-            OS << "\t.aeabi_attribute\t" << "Tag_PAuth_Platform" << ", " << Value;
-            break;
-          case ARMBuildAttrs::Tag_PAuth_Schema:
-            OS << "\t.aeabi_attribute\t" << "Tag_PAuth_Schema" << ", " << Value;
-            break;
+    case ARMBuildAttrs::AEBI_PAUTHABI:
+      switch (Tag) {
+      default:
+        llvm_unreachable("unknown tag for the feature-and-bits subsection");
+      case ARMBuildAttrs::Tag_PAuth_Platform:
+        OS << "\t.aeabi_attribute\t" << "Tag_PAuth_Platform" << ", " << Value;
         break;
-        }
+      case ARMBuildAttrs::Tag_PAuth_Schema:
+        OS << "\t.aeabi_attribute\t" << "Tag_PAuth_Schema" << ", " << Value;
+        break;
+        break;
+      }
     }
     OS << "\n";
   }
 
-  void emitSubsection(unsigned SubsectionName, unsigned Optional, unsigned ParameterType) override {
+  void emitSubsection(unsigned SubsectionName, unsigned Optional,
+                      unsigned ParameterType) override {
     // The AArch64 build attributes assembly subsection header format:
     // ".aeabi_subsection name, optional, parameter type"
     // optional: required (0) optional (1)
     // parameter type: uleb128 or ULEB128 (0) ntbs or NTBS (1)
 
-    assert((Optional == 0 || Optional == 1) && "unsupported parameter for Optional");
-    assert((ParameterType == 0 || ParameterType == 1) && "unsupported parameter for ParameterType");
+    assert((Optional == 0 || Optional == 1) &&
+           "unsupported parameter for Optional");
+    assert((ParameterType == 0 || ParameterType == 1) &&
+           "unsupported parameter for ParameterType");
 
     StringRef OptionalStr = Optional ? "optional" : "required";
     StringRef ParameterStr = ParameterType ? "NTBS" : "ULEB128";
 
-    switch(SubsectionName) {
-      default: llvm_unreachable("unknown AArch64 build attributes subsection name");
-
-      case ARMBuildAttrs::AEBI_FEATURE_AND_BITS:
-        assert(Optional == 1 && "subsection .aeabi-feature-and-bits should be marked as optional and not as mandatory");
-        assert(ParameterType == 0 && "subsection .aeabi-feature-and-bits should be marked as uleb128 and not as ntbs");
-        OS << "\t.aeabi_subsection\t" << ".aeabi-feature-and-bits" << ", " << OptionalStr << ", " << ParameterStr;
-        break;
+    switch (SubsectionName) {
+    default:
+      llvm_unreachable("unknown AArch64 build attributes subsection name");
+
+    case ARMBuildAttrs::AEBI_FEATURE_AND_BITS:
+      assert(Optional == 1 && "subsection .aeabi-feature-and-bits should be "
+                              "marked as optional and not as mandatory");
+      assert(ParameterType == 0 && "subsection .aeabi-feature-and-bits should "
+                                   "be marked as uleb128 and not as ntbs");
+      OS << "\t.aeabi_subsection\t" << ".aeabi-feature-and-bits" << ", "
+         << OptionalStr << ", " << ParameterStr;
+      break;
 
-      case ARMBuildAttrs::AEBI_PAUTHABI:
-        assert(Optional == 0 && "subsection .aeabi-pauthabi should be marked as mandatory and not as optional");
-        assert(ParameterType == 0 && "subsection .aeabi-pauthabi should be marked as uleb128 and not as ntbs");
-        OS << "\t.aeabi_subsection\t" << ".aeabi-pauthabi" << ", " << OptionalStr << ", " << ParameterStr;
-        break;
+    case ARMBuildAttrs::AEBI_PAUTHABI:
+      assert(Optional == 0 && "subsection .aeabi-pauthabi should be marked as "
+                              "mandatory and not as optional");
+      assert(ParameterType == 0 && "subsection .aeabi-pauthabi should be "
+                                   "marked as uleb128 and not as ntbs");
+      OS << "\t.aeabi_subsection\t" << ".aeabi-pauthabi" << ", " << OptionalStr
+         << ", " << ParameterStr;
+      break;
     }
     OS << "\n";
   }
@@ -224,7 +238,8 @@ class AArch64TargetAsmStreamer : public AArch64TargetStreamer {
 
 AArch64TargetAsmStreamer::AArch64TargetAsmStreamer(MCStreamer &S,
                                                    formatted_raw_ostream &OS)
-  : AArch64TargetStreamer(S), OS(OS), VendorTag("eabi"), IsVerboseAsm(S.isVerboseAsm()) {}
+    : AArch64TargetStreamer(S), OS(OS), VendorTag("eabi"),
+      IsVerboseAsm(S.isVerboseAsm()) {}
 
 void AArch64TargetAsmStreamer::emitInst(uint32_t Inst) {
   OS << "\t.inst\t0x" << Twine::utohexstr(Inst) << "\n";
@@ -364,7 +379,9 @@ AArch64ELFStreamer &AArch64TargetELFStreamer::getStreamer() {
   return static_cast<AArch64ELFStreamer &>(Streamer);
 }
 
-void AArch64TargetELFStreamer::emitSubsection(unsigned Vendor, unsigned IsMandatory, unsigned ParameterType) {
+void AArch64TargetELFStreamer::emitSubsection(unsigned Vendor,
+                                              unsigned IsMandatory,
+                                              unsigned ParameterType) {
   StringRef VendorAsStr = ARMBuildAttrs::vendorToStr(Vendor);
 
   // If exists, return.
@@ -382,11 +399,13 @@ void AArch64TargetELFStreamer::emitSubsection(unsigned Vendor, unsigned IsMandat
   AttributeSubSections.push_back(AttSubSection);
 }
 
-void AArch64TargetELFStreamer::emitAttribute(unsigned Vendor, unsigned Tag, unsigned Value, bool Override) {
+void AArch64TargetELFStreamer::emitAttribute(unsigned Vendor, unsigned Tag,
+                                             unsigned Value, bool Override) {
   StringRef VendorAsStr = ARMBuildAttrs::vendorToStr(Vendor);
 
   if (AttributeSubSections.size() == 0) {
-    llvm_unreachable("Attribute can not be added unless the required AArch64 build attributes subsection exists");
+    llvm_unreachable("Attribute can not be added unless the required AArch64 "
+                     "build attributes subsection exists");
     return;
   }
 
@@ -408,7 +427,8 @@ void AArch64TargetELFStreamer::emitAttribute(unsigned Vendor, unsigned Tag, unsi
       return;
     }
   }
-  llvm_unreachable("Attribute can not be added unless the required AArch64 build attributes subsection exists");
+  llvm_unreachable("Attribute can not be added unless the required AArch64 "
+                   "build attributes subsection exists");
 }
 
 void AArch64TargetELFStreamer::emitInst(uint32_t Inst) {
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h
index 7d90759cfc6e10..913754af6f2668 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h
@@ -92,8 +92,10 @@ class AArch64TargetStreamer : public MCTargetStreamer {
   virtual void emitARM64WinCFISaveAnyRegQPX(unsigned Reg, int Offset) {}
 
   /// Build attributes implementation
-  virtual void emitSubsection(unsigned Vendor, unsigned IsMandatory, unsigned ParameterType) {}
-  virtual void emitAttribute(unsigned Vendor, unsigned Tag, unsigned Value, bool Override) {}
+  virtual void emitSubsection(unsigned Vendor, unsigned IsMandatory,
+                              unsigned ParameterType) {}
+  virtual void emitAttribute(unsigned Vendor, unsigned Tag, unsigned Value,
+                             bool Override) {}
 
 private:
   std::unique_ptr<AssemblerConstantPools> ConstantPools;
@@ -108,8 +110,10 @@ class AArch64TargetELFStreamer : public AArch64TargetStreamer {
   SmallVector<MCELFStreamer::AttributeSubSection, 64> AttributeSubSections;
 
   /// Build attributes implementation
-  void emitSubsection(unsigned Vendor, unsigned IsMandatory, unsigned ParameterType) override;
-  void emitAttribute(unsigned Vendor, unsigned Tag, unsigned Value, bool Override) override;
+  void emitSubsection(unsigned Vendor, unsigned IsMandatory,
+                      unsigned ParameterType) override;
+  void emitAttribute(unsigned Vendor, unsigned Tag, unsigned Value,
+                     bool Override) override;
 
   void emitInst(uint32_t Inst) override;
   void emitDirectiveVariantPCS(MCSymbol *Symbol) override;
@@ -117,7 +121,7 @@ class AArch64TargetELFStreamer : public AArch64TargetStreamer {
 
 public:
   AArch64TargetELFStreamer(MCStreamer &S)
-    : AArch64TargetStreamer(S), CurrentVendor("aeabi") {}
+      : AArch64TargetStreamer(S), CurrentVendor("aeabi") {}
 };
 
 class AArch64TargetWinCOFFStreamer : public llvm::AArch64TargetStreamer {
diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp
index b6a16de748d9b0..8c7fc4e7a17713 100644
--- a/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp
+++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp
@@ -793,20 +793,23 @@ void ARMTargetELFStreamer::switchVendor(StringRef Vendor) {
 
 void ARMTargetELFStreamer::emitAttribute(unsigned Attribute, unsigned Value) {
   getStreamer().setAttributeItem(Attribute, Value,
-                                 /* OverwriteExisting= */ true, getStreamer().Contents);
+                                 /* OverwriteExisting= */ true,
+                                 getStreamer().Contents);
 }
 
 void ARMTargetELFStreamer::emitTextAttribute(unsigned Attribute,
                                              StringRef Value) {
   getStreamer().setAttributeItem(Attribute, Value,
-                                 /* OverwriteExisting= */ true, getStreamer().Contents);
+                                 /* OverwriteExisting= */ true,
+                                 getStreamer().Contents);
 }
 
 void ARMTargetELFStreamer::emitIntTextAttribute(unsigned Attribute,
                                                 unsigned IntValue,
                                                 StringRef StringValue) {
   getStreamer().setAttributeItems(Attribute, IntValue, StringValue,
-                                  /* OverwriteExisting= */ true, getStreamer().Contents);
+                                  /* OverwriteExisting= */ true,
+                                  getStreamer().Contents);
 }
 
 void ARMTargetELFStreamer::emitArch(ARM::ArchKind Value) {
@@ -821,12 +824,15 @@ void ARMTargetELFStreamer::emitArchDefaultAttributes() {
   using namespace ARMBuildAttrs;
   ARMELFStreamer &S = getStreamer();
 
-  S.setAttributeItem(CPU_name, ARM::getCPUAttr(Arch), false, getStreamer().Contents);
+  S.setAttributeItem(CPU_name, ARM::getCPUAttr(Arch), false,
+                     getStreamer().Contents);
 
   if (EmittedArch == ARM::ArchKind::INVALID)
-    S.setAttributeItem(CPU_arch, ARM::getArchAttr(Arch), false, getStreamer().Contents);
+    S.setAttributeItem(CPU_arch, ARM::getArchAttr(Arch), false,
+                       getStreamer().Contents);
   else
-    S.setAttributeItem(CPU_arch, ARM::getArchAttr(EmittedArch), false, getStreamer().Contents);
+    S.setAttributeItem(CPU_arch, ARM::getArchAttr(EmittedArch), false,
+                       getStreamer().Contents);
 
   switch (Arch) {
   case ARM::ArchKind::ARMV4:
@@ -843,15 +849,17 @@ void ARMTargetELFStreamer::emitArchDefaultAttributes() {
     break;
 
   case ARM::ArchKind::ARMV6T2:
-    S.setAttributeItem(ARM_ISA_use, Allowed, false,getStreamer().Contents);
-    S.setAttributeItem(THUMB_ISA_use, AllowThumb32, false, getStreamer().Contents);
+    S.setAttributeItem(ARM_ISA_use, Allowed, false, getStreamer().Contents);
+    S.setAttributeItem(THUMB_ISA_use, AllowThumb32, false,
+                       getStreamer().Contents);
     break;
 
   case ARM::ArchKind::ARMV6K:
   case ARM::ArchKind::ARMV6KZ:
     S.setAttributeItem(ARM_ISA_use, Allowed, false, getStreamer().Contents);
     S.setAttributeItem(THUMB_ISA_use, Allowed, false, getStreamer().Contents);
-    S.setAttributeItem(Virtualization_use, AllowTZ, false, getStreamer().Contents);
+    S.setAttributeItem(Virtualization_use, AllowTZ, false,
+                       getStreamer().Contents);
     break;
 
   case ARM::ArchKind::ARMV6M:
@@ -859,21 +867,27 @@ void ARMTargetELFStreamer::emitArchDefaultAttributes() {
     break;
 
   case ARM::ArchKind::ARMV7A:
-    S.setAttributeItem(CPU_arch_profile, ApplicationProfile, false, getStreamer().Contents);
+    S.setAttributeItem(CPU_arch_profile, ApplicationProfile, false,
+                       getStreamer().Contents);
     S.setAttributeItem(ARM_ISA_use, Allowed, false, getStreamer().Contents);
-    S.setAttributeItem(THUMB_ISA_use, AllowThumb32, false, getStreamer().Contents);
+    S.setAttributeItem(THUMB_ISA_use, AllowThumb32, false,
+                       getStreamer().Contents);
     break;
 
   case ARM::ArchKind::ARMV7R:
-    S.setAttributeItem(CPU_arch_profile, RealTimeProfile, false, getStreamer().Contents);
+    S.setAttributeItem(CPU_arch_profile, RealTimeProfile, false,
+                       getStreamer().Contents);
     S.setAttributeItem(ARM_ISA_use, Allowed, false, getStreamer().Contents);
-    S.setAttributeItem(THUMB_ISA_use, AllowThumb32, false, getStreamer().Contents);
+    S.setAttributeItem(THUMB_ISA_use, AllowThumb32, false,
+                       getStreamer().Contents);
     break;
 
   case ARM::ArchKind::ARMV7EM:
   case ARM::ArchKind::ARMV7M:
-    S.setAttributeItem(CPU_arch_profile, MicroControllerProfile, false, getStreamer().Contents);
-    S.setAttributeItem(THUMB_ISA_use, AllowThumb32, false, getStreamer().Contents);
+    S.setAttributeItem(CPU_arch_profile, MicroControllerProfile, false,
+                       getStreamer().Contents);
+    S.setAttributeItem(THUMB_ISA_use, AllowThumb32, false,
+                       getStreamer().Contents);
     break;
 
   case ARM::ArchKind::ARMV8A:
@@ -893,17 +907,22 @@ void ARMTargetELFStreamer::emitArchDefaultAttributes() {
   case ARM::ArchKind::ARMV9_4A:
   case ARM::ArchKind::ARMV9_5A:
   case ARM::ArchKind::ARMV9_6A:
-    S.setAttributeItem(CPU_arch_profile, ApplicationProfile, false, getStreamer().Contents);
+    S.setAttributeItem(CPU_arch_profile, ApplicationProfile, false,
+                       getStreamer().Contents);
     S.setAttributeItem(ARM_ISA_use, Allowed, false, getStreamer().Contents);
-    S.setAttributeItem(THUMB_ISA_use, AllowThumb32, false, getStreamer().Contents);
+    S.setAttributeItem(THUMB_ISA_use, AllowThumb32, false,
+                       getStreamer().Contents);
     S.setAttributeItem(MPextension_use, Allowed, false, getStreamer().Contents);
-    S.setAttributeItem(Virtualization_use, AllowTZVirtualization, false, getStreamer().Contents);
+    S.setAttributeItem(Virtualization_use, AllowTZVirtualization, false,
+                       getStreamer().Contents);
     break;
 
   case ARM::ArchKind::ARMV8MBaseline:
   case ARM::ArchKind::ARMV8MMainline:
-    S.setAttributeItem(THUMB_ISA_use, AllowThumbDerived, false, getStreamer().Contents);
-    S.setAttributeItem(CPU_arch_profile, MicroControllerProfile, false, getStreamer().Contents);
+    S.setAttributeItem(THUMB_ISA_use, AllowThumbDerived, false,
+                       getStreamer().Contents);
+    S.setAttributeItem(CPU_arch_profile, MicroControllerProfile, false,
+                       getStreamer().Contents);
     break;
 
   case ARM::ArchKind::IWMMXT:
diff --git a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp
index d8a177a90a7a3d..4bc205e3f4b6d8 100644
--- a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp
+++ b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp
@@ -330,7 +330,8 @@ class HexagonTargetELFStreamer : public HexagonTargetStreamer {
 
   void emitAttribute(uint32_t Attribute, uint32_t Value) override {
     getStreamer().setAttributeItem(Attribute, Value,
-                                   /*OverwriteExisting=*/true, getStreamer().Contents);
+                                   /*OverwriteExisting=*/true,
+                                   getStreamer().Contents);
   }
 };
 
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp
index ae536accb399a2..b5e2338f379b6b 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp
@@ -57,19 +57,22 @@ void RISCVTargetELFStreamer::emitDirectiveOptionRelax() {}
 void RISCVTargetELFStreamer::emitDirectiveOptionNoRelax() {}
 
 void RISCVTargetELFStreamer::emitAttribute(unsigned Attribute, unsigned Value) {
-  getStreamer().setAttributeItem(Attribute, Value, /*OverwriteExisting=*/true, getStreamer().Contents);
+  getStreamer().setAttributeItem(Attribute, Value, /*OverwriteExisting=*/true,
+                                 getStreamer().Contents);
 }
 
 void RISCVTargetELFStreamer::emitTextAttribute(unsigned Attribute,
                                                StringRef String) {
-  getStreamer().setAttributeItem(Attribute, String, /*OverwriteExisting=*/true, getStreamer().Contents);
+  getStreamer().setAttributeItem(Attribute, String, /*OverwriteExisting=*/true,
+                                 getStreamer().Contents);
 }
 
 void RISCVTargetELFStreamer::emitIntTextAttribute(unsigned Attribute,
                                                   unsigned IntValue,
                                                   StringRef StringValue) {
   getStreamer().setAttributeItems(Attribute, IntValue, StringValue,
-                                  /*OverwriteExisting=*/true, getStreamer().Contents);
+                                  /*OverwriteExisting=*/true,
+                                  getStreamer().Contents);
 }
 
 void RISCVTargetELFStreamer::finishAttributeSection() {

>From 8bc5b42531321f7ec8337dafa09305b9e5b7a257 Mon Sep 17 00:00:00 2001
From: Sivan Shani <sivan.shani at arm.com>
Date: Fri, 6 Dec 2024 13:00:42 +0000
Subject: [PATCH 03/12] Fixing according to some comments: - make use of the
 enums - s/AEBI/AEABI/ - change function name (createAttributesSection) -
 remove AVAttribute code

---
 llvm/include/llvm/MC/MCELFStreamer.h          | 17 +++---
 .../include/llvm/Support/ARMBuildAttributes.h | 17 +-----
 llvm/lib/MC/MCELFStreamer.cpp                 |  2 +-
 llvm/lib/Support/ARMBuildAttrs.cpp            | 59 ++-----------------
 llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp | 18 +++---
 .../MCTargetDesc/AArch64ELFStreamer.cpp       | 19 +++---
 .../MCTargetDesc/AArch64TargetStreamer.h      | 10 ++--
 7 files changed, 43 insertions(+), 99 deletions(-)

diff --git a/llvm/include/llvm/MC/MCELFStreamer.h b/llvm/include/llvm/MC/MCELFStreamer.h
index 0e37948d3d2b7f..f32e8d323935ee 100644
--- a/llvm/include/llvm/MC/MCELFStreamer.h
+++ b/llvm/include/llvm/MC/MCELFStreamer.h
@@ -13,6 +13,7 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/MC/MCDirectives.h"
 #include "llvm/MC/MCObjectStreamer.h"
+#include "llvm/Support/ARMBuildAttributes.h"
 
 namespace llvm {
 
@@ -113,10 +114,8 @@ class MCELFStreamer : public MCObjectStreamer {
     // [<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)
+    ARMBuildAttrs::SubsectionMandatory IsMandatory;
+    ARMBuildAttrs::SubsectionType ParameterType;
     SmallVector<AttributeItem, 64> Content;
   };
 
@@ -139,7 +138,8 @@ class MCELFStreamer : public MCObjectStreamer {
   emitAttributesSection(MCSection *&AttributeSection, const Twine &Section,
                         unsigned Type,
                         SmallVector<AttributeSubSection, 64> &SubSectionVec) {
-    createAttributesSection(AttributeSection, Section, Type, SubSectionVec);
+    createAArch64AttributesSection(AttributeSection, Section, Type,
+                                   SubSectionVec);
   }
 
 private:
@@ -149,10 +149,9 @@ class MCELFStreamer : public MCObjectStreamer {
   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);
+  void createAArch64AttributesSection(
+      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 788d72977d6f05..2c940fb20485ee 100644
--- a/llvm/include/llvm/Support/ARMBuildAttributes.h
+++ b/llvm/include/llvm/Support/ARMBuildAttributes.h
@@ -28,16 +28,16 @@ namespace ARMBuildAttrs {
 const TagNameMap &getARMAttributeTags();
 
 /// AArch64 build attributes vendors (=subsection name)
-enum Vendor : unsigned { AEBI_FEATURE_AND_BITS = 0, AEBI_PAUTHABI = 1 };
+enum Vendor : unsigned { AEABI_FEATURE_AND_BITS = 0, AEABI_PAUTHABI = 1 };
 
 inline StringRef vendorToStr(unsigned Vendor) {
   switch (Vendor) {
   default:
     llvm_unreachable("unknown AArch64 vendor name");
     return "";
-  case AEBI_FEATURE_AND_BITS:
+  case AEABI_FEATURE_AND_BITS:
     return "aeabi-feature-and-bits";
-  case AEBI_PAUTHABI:
+  case AEABI_PAUTHABI:
     return "aeabi-pauthabi";
   }
 }
@@ -127,17 +127,6 @@ 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 576d4997a3dea7..0f49d042233f0b 100644
--- a/llvm/lib/MC/MCELFStreamer.cpp
+++ b/llvm/lib/MC/MCELFStreamer.cpp
@@ -786,7 +786,7 @@ void MCELFStreamer::createAttributesSection(
   AttrsVec.clear();
 }
 
-void MCELFStreamer::createAttributesSection(
+void MCELFStreamer::createAArch64AttributesSection(
     MCSection *&AttributeSection, const Twine &Section, unsigned Type,
     SmallVector<AttributeSubSection, 64> &SubSectionVec) {
   // <format-version: 'A'>
diff --git a/llvm/lib/Support/ARMBuildAttrs.cpp b/llvm/lib/Support/ARMBuildAttrs.cpp
index 457e7d66a7e87a..815cfc62a4b0e3 100644
--- a/llvm/lib/Support/ARMBuildAttrs.cpp
+++ b/llvm/lib/Support/ARMBuildAttrs.cpp
@@ -6,13 +6,11 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "llvm/ADT/StringRef.h"
 #include "llvm/Support/ARMBuildAttributes.h"
 
 using namespace llvm;
 
-namespace {
-const TagNameItem ARMAttributeTags[] = {
+static const TagNameItem tagData[] = {
     {ARMBuildAttrs::File, "Tag_File"},
     {ARMBuildAttrs::Section, "Tag_Section"},
     {ARMBuildAttrs::Symbol, "Tag_Symbol"},
@@ -69,56 +67,7 @@ const TagNameItem ARMAttributeTags[] = {
     {ARMBuildAttrs::ABI_align_preserved, "Tag_ABI_align8_preserved"},
 };
 
-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();
+constexpr TagNameMap ARMAttributeTags{tagData};
+const TagNameMap &llvm::ARMBuildAttrs::getARMAttributeTags() {
+  return ARMAttributeTags;
 }
-} // namespace
-
-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; }
-} // namespace ARMBuildAttrs
-} // namespace llvm
diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index ca60e249e14214..a12d41e22fb3dc 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -465,11 +465,13 @@ void AArch64AsmPrinter::emitAttributes(unsigned Flags,
   PAuthABIVersion = (PAuthABIVersion == uint64_t(-1)) ? 0 : PAuthABIVersion;
 
   if (PAuthABIPlatform || PAuthABIVersion) {
-    TS->emitSubsection(ARMBuildAttrs::AEBI_PAUTHABI, 0, 0);
-    TS->emitAttribute(ARMBuildAttrs::AEBI_PAUTHABI,
+    TS->emitSubsection(ARMBuildAttrs::AEABI_PAUTHABI,
+                       ARMBuildAttrs::SubsectionMandatory::OPTIONAL,
+                       ARMBuildAttrs::SubsectionType::ULEB128);
+    TS->emitAttribute(ARMBuildAttrs::AEABI_PAUTHABI,
                       ARMBuildAttrs::Tag_PAuth_Platform, PAuthABIPlatform,
                       false);
-    TS->emitAttribute(ARMBuildAttrs::AEBI_PAUTHABI,
+    TS->emitAttribute(ARMBuildAttrs::AEABI_PAUTHABI,
                       ARMBuildAttrs::Tag_PAuth_Schema, PAuthABIVersion, false);
   }
 
@@ -478,12 +480,14 @@ void AArch64AsmPrinter::emitAttributes(unsigned Flags,
   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,
+    TS->emitSubsection(ARMBuildAttrs::AEABI_FEATURE_AND_BITS,
+                       ARMBuildAttrs::SubsectionMandatory::REQUIRED,
+                       ARMBuildAttrs::SubsectionType::ULEB128);
+    TS->emitAttribute(ARMBuildAttrs::AEABI_FEATURE_AND_BITS,
                       ARMBuildAttrs::Tag_Feature_BTI, BTIValue, false);
-    TS->emitAttribute(ARMBuildAttrs::AEBI_FEATURE_AND_BITS,
+    TS->emitAttribute(ARMBuildAttrs::AEABI_FEATURE_AND_BITS,
                       ARMBuildAttrs::Tag_Feature_PAC, PACValue, false);
-    TS->emitAttribute(ARMBuildAttrs::AEBI_FEATURE_AND_BITS,
+    TS->emitAttribute(ARMBuildAttrs::AEABI_FEATURE_AND_BITS,
                       ARMBuildAttrs::Tag_Feature_GCS, GCSValue, false);
   }
 }
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp
index cb594785a09d2f..b9c70177436df4 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp
@@ -160,7 +160,7 @@ class AArch64TargetAsmStreamer : public AArch64TargetStreamer {
     default:
       llvm_unreachable("unknown AArch64 build attributes subsection name");
 
-    case ARMBuildAttrs::AEBI_FEATURE_AND_BITS:
+    case ARMBuildAttrs::AEABI_FEATURE_AND_BITS:
       switch (Tag) {
       default:
         llvm_unreachable("unknown tag for the feature-and-bits subsection");
@@ -176,7 +176,7 @@ class AArch64TargetAsmStreamer : public AArch64TargetStreamer {
       }
       break;
 
-    case ARMBuildAttrs::AEBI_PAUTHABI:
+    case ARMBuildAttrs::AEABI_PAUTHABI:
       switch (Tag) {
       default:
         llvm_unreachable("unknown tag for the feature-and-bits subsection");
@@ -192,8 +192,9 @@ class AArch64TargetAsmStreamer : public AArch64TargetStreamer {
     OS << "\n";
   }
 
-  void emitSubsection(unsigned SubsectionName, unsigned Optional,
-                      unsigned ParameterType) override {
+  void emitSubsection(unsigned SubsectionName,
+                      ARMBuildAttrs::SubsectionMandatory Optional,
+                      ARMBuildAttrs::SubsectionType ParameterType) override {
     // The AArch64 build attributes assembly subsection header format:
     // ".aeabi_subsection name, optional, parameter type"
     // optional: required (0) optional (1)
@@ -211,7 +212,7 @@ class AArch64TargetAsmStreamer : public AArch64TargetStreamer {
     default:
       llvm_unreachable("unknown AArch64 build attributes subsection name");
 
-    case ARMBuildAttrs::AEBI_FEATURE_AND_BITS:
+    case ARMBuildAttrs::AEABI_FEATURE_AND_BITS:
       assert(Optional == 1 && "subsection .aeabi-feature-and-bits should be "
                               "marked as optional and not as mandatory");
       assert(ParameterType == 0 && "subsection .aeabi-feature-and-bits should "
@@ -220,7 +221,7 @@ class AArch64TargetAsmStreamer : public AArch64TargetStreamer {
          << OptionalStr << ", " << ParameterStr;
       break;
 
-    case ARMBuildAttrs::AEBI_PAUTHABI:
+    case ARMBuildAttrs::AEABI_PAUTHABI:
       assert(Optional == 0 && "subsection .aeabi-pauthabi should be marked as "
                               "mandatory and not as optional");
       assert(ParameterType == 0 && "subsection .aeabi-pauthabi should be "
@@ -379,9 +380,9 @@ AArch64ELFStreamer &AArch64TargetELFStreamer::getStreamer() {
   return static_cast<AArch64ELFStreamer &>(Streamer);
 }
 
-void AArch64TargetELFStreamer::emitSubsection(unsigned Vendor,
-                                              unsigned IsMandatory,
-                                              unsigned ParameterType) {
+void AArch64TargetELFStreamer::emitSubsection(
+    unsigned Vendor, ARMBuildAttrs::SubsectionMandatory IsMandatory,
+    ARMBuildAttrs::SubsectionType ParameterType) {
   StringRef VendorAsStr = ARMBuildAttrs::vendorToStr(Vendor);
 
   // If exists, return.
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h
index 913754af6f2668..1aa207b40a9326 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h
@@ -92,8 +92,9 @@ class AArch64TargetStreamer : public MCTargetStreamer {
   virtual void emitARM64WinCFISaveAnyRegQPX(unsigned Reg, int Offset) {}
 
   /// Build attributes implementation
-  virtual void emitSubsection(unsigned Vendor, unsigned IsMandatory,
-                              unsigned ParameterType) {}
+  virtual void emitSubsection(unsigned Vendor,
+                              ARMBuildAttrs::SubsectionMandatory IsMandatory,
+                              ARMBuildAttrs::SubsectionType ParameterType) {}
   virtual void emitAttribute(unsigned Vendor, unsigned Tag, unsigned Value,
                              bool Override) {}
 
@@ -110,8 +111,9 @@ class AArch64TargetELFStreamer : public AArch64TargetStreamer {
   SmallVector<MCELFStreamer::AttributeSubSection, 64> AttributeSubSections;
 
   /// Build attributes implementation
-  void emitSubsection(unsigned Vendor, unsigned IsMandatory,
-                      unsigned ParameterType) override;
+  void emitSubsection(unsigned Vendor,
+                      ARMBuildAttrs::SubsectionMandatory IsMandatory,
+                      ARMBuildAttrs::SubsectionType ParameterType) override;
   void emitAttribute(unsigned Vendor, unsigned Tag, unsigned Value,
                      bool Override) override;
 

>From 6e09e352dd559bd54b4000593bfe913d5f78d1fe Mon Sep 17 00:00:00 2001
From: Sivan Shani <sivan.shani at arm.com>
Date: Fri, 6 Dec 2024 16:35:55 +0000
Subject: [PATCH 04/12] Add test files

---
 ...ld-attributes-aeabi-feature-and-bits-ASM.c | 30 +++++++++++++++++++
 ...ld-attributes-aeabi-feature-and-bits-ELF.c | 30 +++++++++++++++++++
 2 files changed, 60 insertions(+)
 create mode 100644 clang/test/CodeGen/AArch64/aarch64-build-attributes-aeabi-feature-and-bits-ASM.c
 create mode 100644 clang/test/CodeGen/AArch64/aarch64-build-attributes-aeabi-feature-and-bits-ELF.c

diff --git a/clang/test/CodeGen/AArch64/aarch64-build-attributes-aeabi-feature-and-bits-ASM.c b/clang/test/CodeGen/AArch64/aarch64-build-attributes-aeabi-feature-and-bits-ASM.c
new file mode 100644
index 00000000000000..2a64274b3f4f1e
--- /dev/null
+++ b/clang/test/CodeGen/AArch64/aarch64-build-attributes-aeabi-feature-and-bits-ASM.c
@@ -0,0 +1,30 @@
+// Test AArch64 build attributes to assmebly: 'aeabi-feature-and-bits'
+
+// RUN: %clang --target=aarch64-none-elf -mbranch-protection=bti+pac-ret+gcs -S -o- %s | FileCheck %s -check-prefix=ALL
+// RUN: %clang --target=aarch64-none-elf -mbranch-protection=bti -S -o- %s | FileCheck %s -check-prefix=BTI
+// RUN: %clang --target=aarch64-none-elf -mbranch-protection=pac-ret -S -o- %s | FileCheck %s -check-prefix=PAC
+// RUN: %clang --target=aarch64-none-elf -mbranch-protection=gcs -S -o- %s | FileCheck %s -check-prefix=GCS
+
+// ALL: .text
+// ALL-NEXT: .aeabi_subsection .aeabi-feature-and-bits, optional, ULEB128
+// ALL-NEXT: .aeabi_attribute Tag_Feature_BTI, 1
+// ALL-NEXT: .aeabi_attribute Tag_Feature_PAC, 1
+// ALL-NEXT: .aeabi_attribute Tag_Feature_GCS, 1
+
+// BTI: .text
+// BTI-NEXT: .aeabi_subsection .aeabi-feature-and-bits, optional, ULEB128
+// BTI-NEXT: .aeabi_attribute Tag_Feature_BTI, 1
+// BTI-NEXT: .aeabi_attribute Tag_Feature_PAC, 0
+// BTI-NEXT: .aeabi_attribute Tag_Feature_GCS, 0
+
+// PAC: .text
+// PAC-NEXT: .aeabi_subsection .aeabi-feature-and-bits, optional, ULEB128
+// PAC-NEXT: .aeabi_attribute Tag_Feature_BTI, 0
+// PAC-NEXT: .aeabi_attribute Tag_Feature_PAC, 1
+// PAC-NEXT: .aeabi_attribute Tag_Feature_GCS, 0
+
+// GCS: .text
+// GCS-NEXT: .aeabi_subsection .aeabi-feature-and-bits, optional, ULEB128
+// GCS-NEXT: .aeabi_attribute Tag_Feature_BTI, 0
+// GCS-NEXT: .aeabi_attribute Tag_Feature_PAC, 0
+// GCS-NEXT: .aeabi_attribute Tag_Feature_GCS, 1
\ No newline at end of file
diff --git a/clang/test/CodeGen/AArch64/aarch64-build-attributes-aeabi-feature-and-bits-ELF.c b/clang/test/CodeGen/AArch64/aarch64-build-attributes-aeabi-feature-and-bits-ELF.c
new file mode 100644
index 00000000000000..b4191a340128d9
--- /dev/null
+++ b/clang/test/CodeGen/AArch64/aarch64-build-attributes-aeabi-feature-and-bits-ELF.c
@@ -0,0 +1,30 @@
+// Test AArch64 build attributes to ELF: 'aeabi-feature-and-bits'
+
+// RUN: %clang -c --target=aarch64-none-elf -mbranch-protection=bti+pac-ret+gcs %s -o %t
+// RUN: llvm-readelf --hex-dump=.ARM.attributes %t | FileCheck %s -check-prefix=ALL
+// RUN: %clang -c --target=aarch64-none-elf -mbranch-protection=bti %s  -o %t
+// RUN: llvm-readelf --hex-dump=.ARM.attributes %t | FileCheck %s -check-prefix=BTI
+// RUN: %clang -c --target=aarch64-none-elf -mbranch-protection=pac-ret %s  -o %t
+// RUN: llvm-readelf --hex-dump=.ARM.attributes %t | FileCheck %s -check-prefix=PAC
+// RUN: %clang -c --target=aarch64-none-elf -mbranch-protection=gcs %s  -o %t
+// RUN: llvm-readelf --hex-dump=.ARM.attributes %t | FileCheck %s -check-prefix=GCS
+
+// ALL: Hex dump of section '.ARM.attributes':
+// ALL-NEXT: 0x00000000 41230000 00616561 62692d66 65617475 A#...aeabi-featu
+// ALL-NEXT: 0x00000010 72652d61 6e642d62 69747301 00000101 re-and-bits.....
+// ALL-NEXT: 0x00000020 010201
+
+// BTI: Hex dump of section '.ARM.attributes':
+// BTI-NEXT: 0x00000000 41230000 00616561 62692d66 65617475 A#...aeabi-featu
+// BTI-NEXT: 0x00000010 72652d61 6e642d62 69747301 00000101 re-and-bits.....
+// BTI-NEXT: 0x00000020 000200
+
+// PAC: Hex dump of section '.ARM.attributes':
+// PAC-NEXT: 0x00000000 41230000 00616561 62692d66 65617475 A#...aeabi-featu
+// PAC-NEXT: 0x00000010 72652d61 6e642d62 69747301 00000001 re-and-bits.....
+// PAC-NEXT: 0x00000020 010200
+
+// GCS: Hex dump of section '.ARM.attributes':
+// GCS-NEXT: 0x00000000 41230000 00616561 62692d66 65617475 A#...aeabi-featu
+// GCS-NEXT: 0x00000010 72652d61 6e642d62 69747301 00000001 re-and-bits.....
+// GCS-NEXT: 0x00000020 000201
\ No newline at end of file

>From 3450b3503c1db65fd88ea09d6d08dfb8864a177b Mon Sep 17 00:00:00 2001
From: Sivan Shani <sivan.shani at arm.com>
Date: Tue, 17 Dec 2024 12:20:12 +0000
Subject: [PATCH 05/12] Add Asm parsing Add some fixes

---
 ...ld-attributes-aeabi-feature-and-bits-ASM.c |  10 +-
 ...ld-attributes-aeabi-feature-and-bits-ELF.c |  26 +--
 llvm/include/llvm/MC/MCELFStreamer.h          |   8 +-
 .../include/llvm/Support/ARMBuildAttributes.h |  77 +++++---
 llvm/lib/MC/MCELFStreamer.cpp                 |  12 +-
 llvm/lib/Support/ARMBuildAttrs.cpp            | 133 +++++++++++++
 llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp |  24 +--
 .../AArch64/AsmParser/AArch64AsmParser.cpp    | 183 +++++++++++++++++-
 .../MCTargetDesc/AArch64ELFStreamer.cpp       | 148 ++++++++------
 .../MCTargetDesc/AArch64TargetStreamer.h      |  25 ++-
 10 files changed, 502 insertions(+), 144 deletions(-)

diff --git a/clang/test/CodeGen/AArch64/aarch64-build-attributes-aeabi-feature-and-bits-ASM.c b/clang/test/CodeGen/AArch64/aarch64-build-attributes-aeabi-feature-and-bits-ASM.c
index 2a64274b3f4f1e..a2c3229b3d86df 100644
--- a/clang/test/CodeGen/AArch64/aarch64-build-attributes-aeabi-feature-and-bits-ASM.c
+++ b/clang/test/CodeGen/AArch64/aarch64-build-attributes-aeabi-feature-and-bits-ASM.c
@@ -1,4 +1,4 @@
-// Test AArch64 build attributes to assmebly: 'aeabi-feature-and-bits'
+// Test AArch64 build attributes to assmebly: 'aeabi_feature_and_bits'
 
 // RUN: %clang --target=aarch64-none-elf -mbranch-protection=bti+pac-ret+gcs -S -o- %s | FileCheck %s -check-prefix=ALL
 // RUN: %clang --target=aarch64-none-elf -mbranch-protection=bti -S -o- %s | FileCheck %s -check-prefix=BTI
@@ -6,25 +6,25 @@
 // RUN: %clang --target=aarch64-none-elf -mbranch-protection=gcs -S -o- %s | FileCheck %s -check-prefix=GCS
 
 // ALL: .text
-// ALL-NEXT: .aeabi_subsection .aeabi-feature-and-bits, optional, ULEB128
+// ALL-NEXT: .aeabi_subsection aeabi_feature_and_bits, optional, uleb128
 // ALL-NEXT: .aeabi_attribute Tag_Feature_BTI, 1
 // ALL-NEXT: .aeabi_attribute Tag_Feature_PAC, 1
 // ALL-NEXT: .aeabi_attribute Tag_Feature_GCS, 1
 
 // BTI: .text
-// BTI-NEXT: .aeabi_subsection .aeabi-feature-and-bits, optional, ULEB128
+// BTI-NEXT: .aeabi_subsection aeabi_feature_and_bits, optional, uleb128
 // BTI-NEXT: .aeabi_attribute Tag_Feature_BTI, 1
 // BTI-NEXT: .aeabi_attribute Tag_Feature_PAC, 0
 // BTI-NEXT: .aeabi_attribute Tag_Feature_GCS, 0
 
 // PAC: .text
-// PAC-NEXT: .aeabi_subsection .aeabi-feature-and-bits, optional, ULEB128
+// PAC-NEXT: .aeabi_subsection aeabi_feature_and_bits, optional, uleb128
 // PAC-NEXT: .aeabi_attribute Tag_Feature_BTI, 0
 // PAC-NEXT: .aeabi_attribute Tag_Feature_PAC, 1
 // PAC-NEXT: .aeabi_attribute Tag_Feature_GCS, 0
 
 // GCS: .text
-// GCS-NEXT: .aeabi_subsection .aeabi-feature-and-bits, optional, ULEB128
+// GCS-NEXT: .aeabi_subsection aeabi_feature_and_bits, optional, uleb128
 // GCS-NEXT: .aeabi_attribute Tag_Feature_BTI, 0
 // GCS-NEXT: .aeabi_attribute Tag_Feature_PAC, 0
 // GCS-NEXT: .aeabi_attribute Tag_Feature_GCS, 1
\ No newline at end of file
diff --git a/clang/test/CodeGen/AArch64/aarch64-build-attributes-aeabi-feature-and-bits-ELF.c b/clang/test/CodeGen/AArch64/aarch64-build-attributes-aeabi-feature-and-bits-ELF.c
index b4191a340128d9..64cd4f9e995894 100644
--- a/clang/test/CodeGen/AArch64/aarch64-build-attributes-aeabi-feature-and-bits-ELF.c
+++ b/clang/test/CodeGen/AArch64/aarch64-build-attributes-aeabi-feature-and-bits-ELF.c
@@ -1,4 +1,4 @@
-// Test AArch64 build attributes to ELF: 'aeabi-feature-and-bits'
+// Test AArch64 build attributes to ELF: 'aeabi_feature_and_bits'
 
 // RUN: %clang -c --target=aarch64-none-elf -mbranch-protection=bti+pac-ret+gcs %s -o %t
 // RUN: llvm-readelf --hex-dump=.ARM.attributes %t | FileCheck %s -check-prefix=ALL
@@ -10,21 +10,21 @@
 // RUN: llvm-readelf --hex-dump=.ARM.attributes %t | FileCheck %s -check-prefix=GCS
 
 // ALL: Hex dump of section '.ARM.attributes':
-// ALL-NEXT: 0x00000000 41230000 00616561 62692d66 65617475 A#...aeabi-featu
-// ALL-NEXT: 0x00000010 72652d61 6e642d62 69747301 00000101 re-and-bits.....
-// ALL-NEXT: 0x00000020 010201
+// ALL-NEXT: 0x00000000 41230000 00616561 62695f66 65617475 A#...aeabi_featu
+// ALL-NEXT: 0x00000010 72655f61 6e645f62 69747300 01000001 re_and_bits.....
+// ALL-NEXT: 0x00000020 01010201
 
 // BTI: Hex dump of section '.ARM.attributes':
-// BTI-NEXT: 0x00000000 41230000 00616561 62692d66 65617475 A#...aeabi-featu
-// BTI-NEXT: 0x00000010 72652d61 6e642d62 69747301 00000101 re-and-bits.....
-// BTI-NEXT: 0x00000020 000200
+// BTI-NEXT: 0x00000000 41230000 00616561 62695f66 65617475 A#...aeabi_featu
+// BTI-NEXT: 0x00000010 72655f61 6e645f62 69747300 01000001 re_and_bits.....
+// BTI-NEXT: 0x00000020 01000200
 
 // PAC: Hex dump of section '.ARM.attributes':
-// PAC-NEXT: 0x00000000 41230000 00616561 62692d66 65617475 A#...aeabi-featu
-// PAC-NEXT: 0x00000010 72652d61 6e642d62 69747301 00000001 re-and-bits.....
-// PAC-NEXT: 0x00000020 010200
+// PAC-NEXT: 0x00000000 41230000 00616561 62695f66 65617475 A#...aeabi_featu
+// PAC-NEXT: 0x00000010 72655f61 6e645f62 69747300 01000000 re_and_bits.....
+// PAC-NEXT: 0x00000020 01010200
 
 // GCS: Hex dump of section '.ARM.attributes':
-// GCS-NEXT: 0x00000000 41230000 00616561 62692d66 65617475 A#...aeabi-featu
-// GCS-NEXT: 0x00000010 72652d61 6e642d62 69747301 00000001 re-and-bits.....
-// GCS-NEXT: 0x00000020 000201
\ No newline at end of file
+// GCS-NEXT: 0x00000000 41230000 00616561 62695f66 65617475 A#...aeabi_featu
+// GCS-NEXT: 0x00000010 72655f61 6e645f62 69747300 01000000 re_and_bits.....
+// GCS-NEXT: 0x00000020 01000201
\ No newline at end of file
diff --git a/llvm/include/llvm/MC/MCELFStreamer.h b/llvm/include/llvm/MC/MCELFStreamer.h
index f32e8d323935ee..80742e8c52fc3f 100644
--- a/llvm/include/llvm/MC/MCELFStreamer.h
+++ b/llvm/include/llvm/MC/MCELFStreamer.h
@@ -98,7 +98,7 @@ class MCELFStreamer : public MCObjectStreamer {
     // 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 {
+    enum Types {
       HiddenAttribute = 0,
       NumericAttribute,
       TextAttribute,
@@ -107,14 +107,16 @@ class MCELFStreamer : public MCObjectStreamer {
     unsigned Tag;
     unsigned IntValue;
     std::string StringValue;
+    AttributeItem(Types Ty, unsigned Tg, unsigned IV, std::string SV) : Type(Ty), Tag(Tg), IntValue(IV), StringValue(SV) {}
   };
 
   /// ELF object attributes subsection support
   struct AttributeSubSection {
+    bool IsActive; // Indicates whether the section is the active section, required for assembly parsing
     // [<uint32: subsection-length> NTBS: vendor-name <bytes: vendor-data>]*
-    StringRef Vendor;
+    StringRef VendorName;
     // <uint8: optional> <uint8: parameter type> <attribute>*
-    ARMBuildAttrs::SubsectionMandatory IsMandatory;
+    ARMBuildAttrs::SubsectionOptional IsOptional;
     ARMBuildAttrs::SubsectionType ParameterType;
     SmallVector<AttributeItem, 64> Content;
   };
diff --git a/llvm/include/llvm/Support/ARMBuildAttributes.h b/llvm/include/llvm/Support/ARMBuildAttributes.h
index 2c940fb20485ee..2cb5f72d927332 100644
--- a/llvm/include/llvm/Support/ARMBuildAttributes.h
+++ b/llvm/include/llvm/Support/ARMBuildAttributes.h
@@ -19,50 +19,65 @@
 #define LLVM_SUPPORT_ARMBUILDATTRIBUTES_H
 
 #include "llvm/Support/ELFAttributes.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/TableGen/Record.h"
 
 namespace llvm {
 class StringRef;
 
 namespace ARMBuildAttrs {
-
-const TagNameMap &getARMAttributeTags();
-
-/// AArch64 build attributes vendors (=subsection name)
-enum Vendor : unsigned { AEABI_FEATURE_AND_BITS = 0, AEABI_PAUTHABI = 1 };
-
-inline StringRef vendorToStr(unsigned Vendor) {
-  switch (Vendor) {
-  default:
-    llvm_unreachable("unknown AArch64 vendor name");
-    return "";
-  case AEABI_FEATURE_AND_BITS:
-    return "aeabi-feature-and-bits";
-  case AEABI_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
+// AArch64 build attributes
+StringRef getSubsectionTag();
+StringRef getAttrTag();
+
+/// AArch64 build attributes vendors IDs (a.k.a subsection name)
+enum VendorID : unsigned { AEABI_FEATURE_AND_BITS = 0, AEABI_PAUTHABI = 1, VENDOR_NOT_FOUND = 404 };
+static const StringRef VendorName[] = { "aeabi_feature_and_bits", "aeabi_pauthabi" };
+StringRef getVendorName(unsigned const Vendor);
+VendorID getVendorID(StringRef const Vendor);
+StringRef getSubsectionUnknownError();
+
+enum SubsectionOptional : unsigned { REQUIRED = 0, OPTIONAL = 1, OPTIONAL_NOT_FOUND = 404 };
+static const StringRef OptionalStr[] = { "required", "optional"};
+StringRef getOptionalStr(unsigned Optional);
+SubsectionOptional getOptionalID(StringRef Optional);
+StringRef getSubsectionOptionalUnknownError();
+
+enum SubsectionType : unsigned { ULEB128 = 0, NTBS = 1, TYPE_NOT_FOUND = 404 };
+static const StringRef TypeStr[] = { "uleb128", "ntbs" };
+StringRef getTypeStr(unsigned Type);
+SubsectionType getTypeID(StringRef Type);
+StringRef getSubsectionTypeUnknownError();
+
+enum PauthABITags : unsigned {
+  TAG_PAUTH_PLATFORM = 1,
+  TAG_PAUTH_SCHEMA = 2,
+  PAUTHABI_TAG_NOT_FOUND = 404
 };
+static const StringRef PauthABITagsStr[] = { "Tag_PAuth_Platform", "Tag_PAuth_Schema"};
+StringRef getPauthABITagsStr(unsigned PauthABITag);
+PauthABITags getPauthABITagsID(StringRef PauthABITag);
+StringRef getPauthabiTagError();
 
-enum PauthabiTags : unsigned {
-  Tag_Feature_BTI = 0,
-  Tag_Feature_PAC = 1,
-  Tag_Feature_GCS = 2
+enum FeatureAndBitsTags : unsigned {
+  TAG_FEATURE_BTI = 0,
+  TAG_FEATURE_PAC = 1,
+  TAG_FEATURE_GCS = 2,
+  FEATURE_AND_BITS_TAG_NOT_FOUND = 404
 };
+static const StringRef FeatureAndBitsTagsStr[] = { "Tag_Feature_BTI", "Tag_Feature_PAC", "Tag_Feature_GCS"};
+StringRef getFeatureAndBitsTagsStr(unsigned FeatureAndBitsTag);
+FeatureAndBitsTags getFeatureAndBitsTagsID(StringRef FeatureAndBitsTag);
+StringRef getFeatureAndBitsTagError();
 
-enum PauthabiTagsFlag : unsigned {
+enum FeatureAndBitsFlag : unsigned {
   Feature_BTI_Flag = 1 << 0,
   Feature_PAC_Flag = 1 << 1,
   Feature_GCS_Flag = 1 << 2
 };
-/// ---
+///--- AArch64 build attributes
+
+const TagNameMap &getARMAttributeTags();
 
 enum SpecialAttr {
   // This is for the .cpu asm attr. It translates into one or more
diff --git a/llvm/lib/MC/MCELFStreamer.cpp b/llvm/lib/MC/MCELFStreamer.cpp
index 0f49d042233f0b..b8cb24f3bdf212 100644
--- a/llvm/lib/MC/MCELFStreamer.cpp
+++ b/llvm/lib/MC/MCELFStreamer.cpp
@@ -795,7 +795,7 @@ void MCELFStreamer::createAArch64AttributesSection(
   // ]*
   // vendor-data expends to:
   // <uint8: optional> <uint8: parameter type> <attribute>*
-  if (SubSectionVec.size() == 0) {
+  if (0 == SubSectionVec.size()) {
     return;
   }
 
@@ -812,21 +812,23 @@ void MCELFStreamer::createAArch64AttributesSection(
 
   for (AttributeSubSection &SubSection : SubSectionVec) {
     // subsection-length + vendor-name + '\0'
-    const size_t VendorHeaderSize = 4 + SubSection.Vendor.size() + 1;
+    const size_t VendorHeaderSize = 4 + SubSection.VendorName.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);
+    emitBytes(SubSection.VendorName);
+    emitInt8(0); // '\0'
+    emitInt8(SubSection.IsOptional);
     emitInt8(SubSection.ParameterType);
 
     for (AttributeItem &Item : SubSection.Content) {
       emitULEB128IntValue(Item.Tag);
       switch (Item.Type) {
       default:
-        llvm_unreachable("Invalid attribute type");
+        assert(0 && "Invalid attribute type");
+        break;
       case AttributeItem::NumericAttribute:
         emitULEB128IntValue(Item.IntValue);
         break;
diff --git a/llvm/lib/Support/ARMBuildAttrs.cpp b/llvm/lib/Support/ARMBuildAttrs.cpp
index 815cfc62a4b0e3..eb4ee5f6d15e09 100644
--- a/llvm/lib/Support/ARMBuildAttrs.cpp
+++ b/llvm/lib/Support/ARMBuildAttrs.cpp
@@ -8,6 +8,139 @@
 
 #include "llvm/Support/ARMBuildAttributes.h"
 
+
+namespace llvm {
+  class StringRef;
+  namespace ARMBuildAttrs {
+    // AArch64 build attributes
+    StringRef getSubsectionTag() { return "aeabi_subsection"; }
+    StringRef getAttrTag() { return "aeabi_attribute"; }
+
+    StringRef getVendorName(unsigned Vendor) {
+      switch (Vendor) {
+      case AEABI_FEATURE_AND_BITS:
+        return VendorName[AEABI_FEATURE_AND_BITS];
+      case AEABI_PAUTHABI:
+        return VendorName[AEABI_PAUTHABI];
+      case VENDOR_NOT_FOUND:
+      [[fallthrough]];
+      default:
+        assert(0 && "unknown AArch64 vendor");
+        return "";
+      }
+    }
+    VendorID getVendorID(StringRef Vendor) {
+      if(Vendor == VendorName[AEABI_FEATURE_AND_BITS]) {
+        return AEABI_FEATURE_AND_BITS;
+      }
+      if(Vendor == VendorName[AEABI_PAUTHABI]) {
+        return AEABI_PAUTHABI;
+      }
+      assert(0 && "unknown AArch64 vendor");
+      return VENDOR_NOT_FOUND;
+    }
+    StringRef getSubsectionUnknownError() { return "unknown AArch64 build attributes subsection"; }
+
+    StringRef getOptionalStr(unsigned Optional) {
+      switch (Optional) {
+      case REQUIRED:
+        return OptionalStr[REQUIRED];
+      case OPTIONAL:
+        return OptionalStr[OPTIONAL];
+      case OPTIONAL_NOT_FOUND:
+      [[fallthrough]];
+      default:
+        assert(0 && "unknown AArch64 Optional option");
+        return "";
+      }
+    }
+    SubsectionOptional getOptionalID(StringRef Optional) {
+      if(Optional == OptionalStr[REQUIRED])
+        return REQUIRED;
+      if(Optional == OptionalStr[OPTIONAL])
+        return OPTIONAL;
+      assert(0 && "unknown AArch64 Optional option");
+      return OPTIONAL_NOT_FOUND;
+    }
+    StringRef getSubsectionOptionalUnknownError() { return "unknown AArch64 build attributes optionality, expecting required|optional"; }
+
+    StringRef getTypeStr(unsigned Type) {
+      switch (Type) {
+      case ULEB128:
+        return TypeStr[ULEB128];
+      case NTBS:
+        return TypeStr[NTBS];
+      case TYPE_NOT_FOUND:
+      [[fallthrough]];
+      default:
+        assert(0 && "unknown AArch64 subsection type");
+        return "";
+      }
+    }
+    SubsectionType getTypeID(StringRef Type) {
+      if(Type == TypeStr[ULEB128] || Type == (TypeStr[ULEB128].upper()))
+        return ULEB128;
+      if(Type == TypeStr[NTBS]|| Type == (TypeStr[NTBS].upper()))
+        return NTBS;
+      assert(0 && "unknown AArch64 subsection type");
+      return TYPE_NOT_FOUND;
+    }
+    StringRef getSubsectionTypeUnknownError() { return "unknown AArch64 build attributes type, expecting uleb128 or ntbs"; }
+
+    StringRef getPauthABITagsStr(unsigned PauthABITag) {
+      switch(PauthABITag) {
+        case TAG_PAUTH_PLATFORM:
+          return PauthABITagsStr[TAG_PAUTH_PLATFORM - 1]; // Tag_PAuth_Platform = 1 in accordance with the spec
+        case TAG_PAUTH_SCHEMA:
+          return PauthABITagsStr[TAG_PAUTH_SCHEMA - 1]; // Tag_PAuth_Schema = 2 in accordance with the spec
+        case PAUTHABI_TAG_NOT_FOUND:
+          [[fallthrough]];
+        default:
+          assert(0 && "unknown pauthabi tag");
+          return "";
+      }
+    }
+    PauthABITags getPauthABITagsID(StringRef PauthABITag) {
+      if(PauthABITag == PauthABITagsStr[TAG_PAUTH_PLATFORM - 1])
+        return TAG_PAUTH_PLATFORM;
+      if(PauthABITag == PauthABITagsStr[TAG_PAUTH_SCHEMA - 1])
+        return TAG_PAUTH_SCHEMA;
+      assert(0 && "unknown FPauthABI tag");
+      return PAUTHABI_TAG_NOT_FOUND;
+    }
+    StringRef getPauthabiTagError() { return "unknown tag for the AArch64 Pauthabi subsection"; }
+
+    StringRef getFeatureAndBitsTagsStr(unsigned FeatureAndBitsTag) {
+      switch(FeatureAndBitsTag) {
+        case TAG_FEATURE_BTI:
+          return FeatureAndBitsTagsStr[TAG_FEATURE_BTI];
+        case TAG_FEATURE_PAC:
+          return FeatureAndBitsTagsStr[TAG_FEATURE_PAC];
+        case TAG_FEATURE_GCS:
+          return FeatureAndBitsTagsStr[TAG_FEATURE_GCS];
+        case FEATURE_AND_BITS_TAG_NOT_FOUND:
+          [[fallthrough]];
+        default:
+          assert(0 && "unknown feature and bits tag");
+          return "";
+      }
+    }
+    FeatureAndBitsTags getFeatureAndBitsTagsID(StringRef FeatureAndBitsTag) {
+      if(FeatureAndBitsTag == FeatureAndBitsTagsStr[TAG_FEATURE_BTI])
+        return TAG_FEATURE_BTI;
+      if(FeatureAndBitsTag == FeatureAndBitsTagsStr[TAG_FEATURE_PAC])
+        return TAG_FEATURE_PAC;
+      if(FeatureAndBitsTag == FeatureAndBitsTagsStr[TAG_FEATURE_GCS])
+        return TAG_FEATURE_GCS;
+      assert(0 && "unknown Feature and Bits tag");
+      return FEATURE_AND_BITS_TAG_NOT_FOUND;
+    }
+    StringRef getFeatureAndBitsTagError() { return "unknown tag for the AArch64 Feature And Bits subsection"; }
+    ///--- AArch64 build attributes
+  } // namespace ARMBuildAttrs
+} // namespace llvm
+
+
 using namespace llvm;
 
 static const TagNameItem tagData[] = {
diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index a12d41e22fb3dc..c78b2f3196f1a8 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -347,7 +347,7 @@ void AArch64AsmPrinter::emitStartOfAsmFile(Module &M) {
   if (const auto *BTE = mdconst::extract_or_null<ConstantInt>(
           M.getModuleFlag("branch-target-enforcement"))) {
     if (!BTE->isZero()) {
-      BAFlags |= ARMBuildAttrs::PauthabiTagsFlag::Feature_BTI_Flag;
+      BAFlags |= ARMBuildAttrs::FeatureAndBitsFlag::Feature_BTI_Flag;
       GNUFlags |= ELF::GNU_PROPERTY_AARCH64_FEATURE_1_BTI;
     }
   }
@@ -355,7 +355,7 @@ void AArch64AsmPrinter::emitStartOfAsmFile(Module &M) {
   if (const auto *GCS = mdconst::extract_or_null<ConstantInt>(
           M.getModuleFlag("guarded-control-stack"))) {
     if (!GCS->isZero()) {
-      BAFlags |= ARMBuildAttrs::PauthabiTagsFlag::Feature_GCS_Flag;
+      BAFlags |= ARMBuildAttrs::FeatureAndBitsFlag::Feature_GCS_Flag;
       GNUFlags |= ELF::GNU_PROPERTY_AARCH64_FEATURE_1_GCS;
     }
   }
@@ -363,7 +363,7 @@ void AArch64AsmPrinter::emitStartOfAsmFile(Module &M) {
   if (const auto *Sign = mdconst::extract_or_null<ConstantInt>(
           M.getModuleFlag("sign-return-address"))) {
     if (!Sign->isZero()) {
-      BAFlags |= ARMBuildAttrs::PauthabiTagsFlag::Feature_PAC_Flag;
+      BAFlags |= ARMBuildAttrs::FeatureAndBitsFlag::Feature_PAC_Flag;
       GNUFlags |= ELF::GNU_PROPERTY_AARCH64_FEATURE_1_PAC;
     }
   }
@@ -461,18 +461,18 @@ void AArch64AsmPrinter::emitAttributes(unsigned Flags,
                                        uint64_t PAuthABIVersion,
                                        AArch64TargetStreamer *TS) {
 
-  PAuthABIPlatform = (PAuthABIPlatform == uint64_t(-1)) ? 0 : PAuthABIPlatform;
-  PAuthABIVersion = (PAuthABIVersion == uint64_t(-1)) ? 0 : PAuthABIVersion;
+  PAuthABIPlatform = (uint64_t(-1) == PAuthABIPlatform) ? 0 : PAuthABIPlatform;
+  PAuthABIVersion = (uint64_t(-1) == PAuthABIVersion) ? 0 : PAuthABIVersion;
 
   if (PAuthABIPlatform || PAuthABIVersion) {
     TS->emitSubsection(ARMBuildAttrs::AEABI_PAUTHABI,
-                       ARMBuildAttrs::SubsectionMandatory::OPTIONAL,
+                       ARMBuildAttrs::SubsectionOptional::REQUIRED,
                        ARMBuildAttrs::SubsectionType::ULEB128);
     TS->emitAttribute(ARMBuildAttrs::AEABI_PAUTHABI,
-                      ARMBuildAttrs::Tag_PAuth_Platform, PAuthABIPlatform,
+                      ARMBuildAttrs::TAG_PAUTH_PLATFORM, PAuthABIPlatform,
                       false);
     TS->emitAttribute(ARMBuildAttrs::AEABI_PAUTHABI,
-                      ARMBuildAttrs::Tag_PAuth_Schema, PAuthABIVersion, false);
+                      ARMBuildAttrs::TAG_PAUTH_SCHEMA, PAuthABIVersion, false);
   }
 
   unsigned BTIValue = (Flags & ARMBuildAttrs::Feature_BTI_Flag) ? 1 : 0;
@@ -481,14 +481,14 @@ void AArch64AsmPrinter::emitAttributes(unsigned Flags,
 
   if (BTIValue || PACValue || GCSValue) {
     TS->emitSubsection(ARMBuildAttrs::AEABI_FEATURE_AND_BITS,
-                       ARMBuildAttrs::SubsectionMandatory::REQUIRED,
+                       ARMBuildAttrs::SubsectionOptional::OPTIONAL,
                        ARMBuildAttrs::SubsectionType::ULEB128);
     TS->emitAttribute(ARMBuildAttrs::AEABI_FEATURE_AND_BITS,
-                      ARMBuildAttrs::Tag_Feature_BTI, BTIValue, false);
+                      ARMBuildAttrs::TAG_FEATURE_BTI, BTIValue, false);
     TS->emitAttribute(ARMBuildAttrs::AEABI_FEATURE_AND_BITS,
-                      ARMBuildAttrs::Tag_Feature_PAC, PACValue, false);
+                      ARMBuildAttrs::TAG_FEATURE_PAC, PACValue, false);
     TS->emitAttribute(ARMBuildAttrs::AEABI_FEATURE_AND_BITS,
-                      ARMBuildAttrs::Tag_Feature_GCS, GCSValue, false);
+                      ARMBuildAttrs::TAG_FEATURE_GCS, GCSValue, false);
   }
 }
 
diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index a9ba35899160c0..c17e24e44f3ae3 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -42,6 +42,7 @@
 #include "llvm/MC/MCTargetOptions.h"
 #include "llvm/MC/MCValue.h"
 #include "llvm/MC/TargetRegistry.h"
+#include "llvm/Support/ARMBuildAttributes.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/ErrorHandling.h"
@@ -228,6 +229,8 @@ class AArch64AsmParser : public MCTargetAsmParser {
   bool parseDirectiveSEHClearUnwoundToCall(SMLoc L);
   bool parseDirectiveSEHPACSignLR(SMLoc L);
   bool parseDirectiveSEHSaveAnyReg(SMLoc L, bool Paired, bool Writeback);
+  bool parseDirectiveAeabiSubSectionHeader(SMLoc L);
+  bool parseDirectiveAeabiAArch64Attr(SMLoc L);
 
   bool validateInstruction(MCInst &Inst, SMLoc &IDLoc,
                            SmallVectorImpl<SMLoc> &Loc);
@@ -7064,8 +7067,12 @@ bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
       parseDirectiveSEHSaveAnyReg(Loc, true, true);
     else
       return true;
-  } else
-    return true;
+  } else if (!IsMachO && !IsCOFF) {
+      if (IDVal == ".aeabi_subsection")
+        parseDirectiveAeabiSubSectionHeader(Loc);
+      else if (IDVal == ".aeabi_attribute")
+        parseDirectiveAeabiAArch64Attr(Loc);
+  } else return true;
   return false;
 }
 
@@ -7800,6 +7807,178 @@ bool AArch64AsmParser::parseDirectiveSEHSaveAnyReg(SMLoc L, bool Paired,
   return false;
 }
 
+bool AArch64AsmParser::parseDirectiveAeabiSubSectionHeader(SMLoc L) {
+  // Expecting 3 AsmToken::Identifier after '.aeabi_subsection', a name and 2 parameters, e.g.:
+  // .aeabi_subsection (1)aeabi_feature_and_bits, (2)optional, (3)uleb128
+  // separated by 2 commas.
+  MCAsmParser &Parser = getParser();
+
+  // Consume the name (subsection name)
+  StringRef SubsectionName;
+  ARMBuildAttrs::VendorID SubsectionNameID;
+  if (Parser.getTok().is(AsmToken::Identifier)) {
+    StringRef SubsectionName = Parser.getTok().getIdentifier();
+    SubsectionNameID = ARMBuildAttrs::getVendorID(SubsectionName);
+    if (ARMBuildAttrs::VENDOR_NOT_FOUND == SubsectionNameID) {
+      Error(Parser.getTok().getLoc(), ARMBuildAttrs::getSubsectionUnknownError() + ": " + SubsectionName);
+    }
+  } else {
+      Error(Parser.getTok().getLoc(), "Expecting subsection name");
+      return true;
+  }
+  Parser.Lex();
+  // consume a comma
+  // parseComma() return *false* on success, and call Lex(), no need to call Lex() again.
+  if (Parser.parseComma()) {
+    Error(Parser.getTok().getLoc(), "expected ','");
+    return true;
+  }
+
+  // Consume the first parameter (optionality parameter)
+  ARMBuildAttrs::SubsectionOptional IsOptional;
+  // options: optional/required
+  if (Parser.getTok().is(AsmToken::Identifier)) {
+    StringRef Name = Parser.getTok().getIdentifier();
+    IsOptional = ARMBuildAttrs::getOptionalID(Name);
+    if (ARMBuildAttrs::OPTIONAL_NOT_FOUND == IsOptional) {
+      Error(Parser.getTok().getLoc(), ARMBuildAttrs::getSubsectionOptionalUnknownError() + ": " + Name);
+      return true;
+    }
+  } else {
+      Error(Parser.getTok().getLoc(), "Expecitng optionality parameter \n Hint: use 'optional' | 'required'");
+      return true;
+  }
+  // Check for possible IsOptional unaccepted values for known subsections
+  if (ARMBuildAttrs::AEABI_FEATURE_AND_BITS == SubsectionNameID) {
+    if (ARMBuildAttrs::REQUIRED == IsOptional) {
+        Error(Parser.getTok().getLoc(), "aeabi_feature_and_bits must be marked as optional");
+        return true;
+    }
+  }
+  if (ARMBuildAttrs::AEABI_PAUTHABI == SubsectionNameID) {
+    if (ARMBuildAttrs::OPTIONAL == IsOptional) {
+        Error(Parser.getTok().getLoc(), "aeabi_pauthabi must be marked as required");
+        return true;
+    }
+  }
+  Parser.Lex();
+  // consume a comma
+  if (Parser.parseComma()) {
+    Error(Parser.getTok().getLoc(), "expected ','");
+    return true;
+  }
+
+  // Consume the second parameter (type parameter)
+  ARMBuildAttrs::SubsectionType Type;
+  if (Parser.getTok().is(AsmToken::Identifier)) {
+    StringRef Name = Parser.getTok().getIdentifier();
+    Type = ARMBuildAttrs::getTypeID(Name);
+    if (ARMBuildAttrs::TYPE_NOT_FOUND == Type) {
+      Error(Parser.getTok().getLoc(), ARMBuildAttrs::getSubsectionTypeUnknownError() + ": " + Name);
+      return true;
+    }
+  } else {
+      Error(Parser.getTok().getLoc(), "Expecitng type parameter");
+      return true;
+  }
+  // Check for possible Type unaccepted values for known subsections
+  if (ARMBuildAttrs::AEABI_FEATURE_AND_BITS == SubsectionNameID || ARMBuildAttrs::AEABI_PAUTHABI == SubsectionNameID) {
+    if (ARMBuildAttrs::NTBS == Type) {
+        Error(Parser.getTok().getLoc(), SubsectionName + "must be marked as ULEB128");
+        return true;
+    }
+  }
+  Parser.Lex();
+  // Parsing finished, check for trailing tokens.
+  if (Parser.getTok().isNot(llvm::AsmToken::EndOfStatement)) {
+    Error(Parser.getTok().getLoc(), "unexpected token for AArch64 build attributes subsection header directive");
+    return true;
+  }
+
+  getTargetStreamer().emitSubsection(SubsectionNameID, IsOptional, Type);
+
+  return false;
+}
+
+bool AArch64AsmParser::parseDirectiveAeabiAArch64Attr(SMLoc L) {
+  // Expecting 2 Tokens: after '.aeabi_attribute', e.g.:
+  // .aeabi_attribute	(1)Tag_Feature_BTI, (2)1
+  // separated by a comma.
+  MCAsmParser &Parser = getParser();
+
+  StringRef ActiveSubsection = "";
+  unsigned ActiveSubsectionID;
+  StringRef TagStr = "";
+  unsigned Tag;
+  if (Parser.getTok().is(AsmToken::Identifier)) {
+    TagStr = Parser.getTok().getIdentifier();
+    ActiveSubsection = getTargetStreamer().getActiveSubsection();
+    if ("" == ActiveSubsection) {
+      Error(Parser.getTok().getLoc(), "no active subsection, build attribute can not be added");
+      return true;
+    }
+    if(ARMBuildAttrs::VendorName[ARMBuildAttrs::AEABI_PAUTHABI] == ActiveSubsection) {
+      ActiveSubsectionID = ARMBuildAttrs::AEABI_PAUTHABI;
+      Tag = ARMBuildAttrs::getPauthABITagsID(TagStr);
+      if (ARMBuildAttrs::PAUTHABI_TAG_NOT_FOUND == Tag) {
+        Error(Parser.getTok().getLoc(), "Unknown AArch64 build attribute '" + TagStr + "' for subsection '" + ActiveSubsection + "'");
+        return true;
+      }
+    } else if(ARMBuildAttrs::VendorName[ARMBuildAttrs::AEABI_FEATURE_AND_BITS] == ActiveSubsection) {
+      ActiveSubsectionID = ARMBuildAttrs::AEABI_FEATURE_AND_BITS;
+      Tag = ARMBuildAttrs::getFeatureAndBitsTagsID(TagStr);
+      if (ARMBuildAttrs::FEATURE_AND_BITS_TAG_NOT_FOUND == Tag) {
+        Error(Parser.getTok().getLoc(), "Unknown AArch64 build attribute '" + TagStr + "' for subsection '" + ActiveSubsection + "' \n Hint: options are: Tag_Feature_BTI, Tag_Feature_PAC, Tag_Feature_GCS");
+        return true;
+      }
+    }
+  // for compatability
+  } else if(Parser.getTok().is(AsmToken::Integer)) {
+    Tag = getTok().getIntVal();
+  } else {
+      Error(Parser.getTok().getLoc(), "AArch64 build attributes Tag not found");
+      return true;
+  }
+  Parser.Lex();
+  // consume a comma
+  // parseComma() return *false* on success, and call Lex(), no need to call Lex() again.
+  if (Parser.parseComma()) {
+    Error(Parser.getTok().getLoc(), "expected ','");
+    return true;
+  }
+
+  // Consume the second parameter (attribute value)
+  unsigned Value;
+  if (Parser.getTok().is(AsmToken::Integer)) {
+    Value = getTok().getIntVal();
+  } else {
+      Error(Parser.getTok().getLoc(), "AArch64 build attributes Value not found");
+      return true;
+  }
+  // Check for possible unaccepted values for known tags
+  if (TagStr != "") { // Tag was a recognized string
+    if (0 != Value && 1 != Value) {
+      Error(Parser.getTok().getLoc(), "Unknown AArch64 build attributes Value for Tag '" + TagStr + "' \n Hint: options are '0'|'1'");
+      return true;
+    }
+  // Tag was an integer
+  } else if (0 == Tag || 1 == Tag || 2 == Tag) { // might be at attempt to represent known tags
+    if (0 != Value && 1 != Value) {
+      Warning(Parser.getTok().getLoc(), "Unknown AArch64 build attributes Value for any known AArch64 build attributes tags");
+    }
+  }
+  Parser.Lex();
+  // Parsing finished, check for trailing tokens.
+  if (Parser.getTok().isNot(llvm::AsmToken::EndOfStatement)) {
+    Error(Parser.getTok().getLoc(), "unexpected token for AArch64 build attributes tag and value attribute directive");
+    return true;
+  }
+
+  getTargetStreamer().emitAttribute(ActiveSubsectionID, Tag, Value, false);
+
+  return false;
+}
+
 bool AArch64AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
   // Try @AUTH expressions: they're more complex than the usual symbol variants.
   if (!parseAuthExpr(Res, EndLoc))
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp
index b9c70177436df4..00d72d15f1cc6f 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp
@@ -151,27 +151,28 @@ class AArch64TargetAsmStreamer : public AArch64TargetStreamer {
     OS << "\t.seh_save_any_reg_px\tq" << Reg << ", " << Offset << "\n";
   }
 
-  void emitAttribute(unsigned Vendor, unsigned Tag, unsigned Value,
+  void emitAttribute(unsigned VendorID, unsigned Tag, unsigned Value,
                      bool Override) override {
     // AArch64 build attributes for assembly attribute form:
     // .aeabi_attribute tag, value
-
-    switch (Vendor) {
-    default:
-      llvm_unreachable("unknown AArch64 build attributes subsection name");
-
+    switch (VendorID) {
+    default: {
+      assert(0 && ARMBuildAttrs::getSubsectionUnknownError().data());
+      break;
+    }
     case ARMBuildAttrs::AEABI_FEATURE_AND_BITS:
       switch (Tag) {
       default:
-        llvm_unreachable("unknown tag for the feature-and-bits subsection");
-      case ARMBuildAttrs::Tag_Feature_BTI:
-        OS << "\t.aeabi_attribute\t" << "Tag_Feature_BTI" << ", " << Value;
+        assert(0 && ARMBuildAttrs::getFeatureAndBitsTagError().data());
         break;
-      case ARMBuildAttrs::Tag_Feature_GCS:
-        OS << "\t.aeabi_attribute\t" << "Tag_Feature_GCS" << ", " << Value;
+      case ARMBuildAttrs::TAG_FEATURE_BTI:
+        OS << "\t." << ARMBuildAttrs::getAttrTag() << "\t" << ARMBuildAttrs::getFeatureAndBitsTagsStr(ARMBuildAttrs::TAG_FEATURE_BTI) << ", " << Value;
         break;
-      case ARMBuildAttrs::Tag_Feature_PAC:
-        OS << "\t.aeabi_attribute\t" << "Tag_Feature_PAC" << ", " << Value;
+      case ARMBuildAttrs::TAG_FEATURE_GCS:
+        OS << "\t." << ARMBuildAttrs::getAttrTag() << "\t" << ARMBuildAttrs::getFeatureAndBitsTagsStr(ARMBuildAttrs::TAG_FEATURE_GCS) << ", " << Value;
+        break;
+      case ARMBuildAttrs::TAG_FEATURE_PAC:
+        OS << "\t." << ARMBuildAttrs::getAttrTag() << "\t" << ARMBuildAttrs::getFeatureAndBitsTagsStr(ARMBuildAttrs::TAG_FEATURE_PAC) << ", " << Value;
         break;
       }
       break;
@@ -179,12 +180,13 @@ class AArch64TargetAsmStreamer : public AArch64TargetStreamer {
     case ARMBuildAttrs::AEABI_PAUTHABI:
       switch (Tag) {
       default:
-        llvm_unreachable("unknown tag for the feature-and-bits subsection");
-      case ARMBuildAttrs::Tag_PAuth_Platform:
-        OS << "\t.aeabi_attribute\t" << "Tag_PAuth_Platform" << ", " << Value;
+        assert(0 && ARMBuildAttrs::getFeatureAndBitsTagError().data());
+        break;
+      case ARMBuildAttrs::TAG_PAUTH_PLATFORM:
+        OS << "\t." << ARMBuildAttrs::getAttrTag() << "\t" << ARMBuildAttrs::getPauthABITagsStr(ARMBuildAttrs::TAG_PAUTH_PLATFORM) << ", " << Value;
         break;
-      case ARMBuildAttrs::Tag_PAuth_Schema:
-        OS << "\t.aeabi_attribute\t" << "Tag_PAuth_Schema" << ", " << Value;
+      case ARMBuildAttrs::TAG_PAUTH_SCHEMA:
+        OS << "\t." << ARMBuildAttrs::getAttrTag() << "\t" << ARMBuildAttrs::getPauthABITagsStr(ARMBuildAttrs::TAG_PAUTH_SCHEMA) << ", " << Value;
         break;
         break;
       }
@@ -193,43 +195,48 @@ class AArch64TargetAsmStreamer : public AArch64TargetStreamer {
   }
 
   void emitSubsection(unsigned SubsectionName,
-                      ARMBuildAttrs::SubsectionMandatory Optional,
+                      ARMBuildAttrs::SubsectionOptional Optional,
                       ARMBuildAttrs::SubsectionType ParameterType) override {
     // The AArch64 build attributes assembly subsection header format:
     // ".aeabi_subsection name, optional, parameter type"
     // optional: required (0) optional (1)
     // parameter type: uleb128 or ULEB128 (0) ntbs or NTBS (1)
 
-    assert((Optional == 0 || Optional == 1) &&
-           "unsupported parameter for Optional");
-    assert((ParameterType == 0 || ParameterType == 1) &&
-           "unsupported parameter for ParameterType");
+    assert(( 0 == Optional || 1 == Optional) &&
+           ARMBuildAttrs::getSubsectionOptionalUnknownError().data());
+    assert(( 0 == ParameterType || 1 == ParameterType) &&
+           ARMBuildAttrs::getSubsectionTypeUnknownError().data());
 
-    StringRef OptionalStr = Optional ? "optional" : "required";
-    StringRef ParameterStr = ParameterType ? "NTBS" : "ULEB128";
+    std::string SubsectionTag = ("." + ARMBuildAttrs::getSubsectionTag()).str();
+    StringRef OptionalStr = getOptionalStr(Optional);
+    StringRef ParameterStr = getTypeStr(ParameterType);
 
     switch (SubsectionName) {
-    default:
-      llvm_unreachable("unknown AArch64 build attributes subsection name");
-
-    case ARMBuildAttrs::AEABI_FEATURE_AND_BITS:
-      assert(Optional == 1 && "subsection .aeabi-feature-and-bits should be "
-                              "marked as optional and not as mandatory");
-      assert(ParameterType == 0 && "subsection .aeabi-feature-and-bits should "
-                                   "be marked as uleb128 and not as ntbs");
-      OS << "\t.aeabi_subsection\t" << ".aeabi-feature-and-bits" << ", "
-         << OptionalStr << ", " << ParameterStr;
+    default: {
+      assert(0 && ARMBuildAttrs::getSubsectionUnknownError().data());
       break;
-
-    case ARMBuildAttrs::AEABI_PAUTHABI:
-      assert(Optional == 0 && "subsection .aeabi-pauthabi should be marked as "
+    }
+    case ARMBuildAttrs::AEABI_PAUTHABI: {
+      assert(ARMBuildAttrs::REQUIRED == Optional && "subsection .aeabi-pauthabi should be marked as "
                               "mandatory and not as optional");
-      assert(ParameterType == 0 && "subsection .aeabi-pauthabi should be "
+      assert(ARMBuildAttrs::ULEB128 == ParameterType && "subsection .aeabi-pauthabi should be "
                                    "marked as uleb128 and not as ntbs");
-      OS << "\t.aeabi_subsection\t" << ".aeabi-pauthabi" << ", " << OptionalStr
+      StringRef SubsectionName = getVendorName(ARMBuildAttrs::AEABI_PAUTHABI);
+      OS << "\t" << SubsectionTag << "\t" << SubsectionName << ", " << OptionalStr
          << ", " << ParameterStr;
       break;
     }
+    case ARMBuildAttrs::AEABI_FEATURE_AND_BITS: {
+      assert( ARMBuildAttrs::OPTIONAL == Optional && "subsection .aeabi_feature_and_bits should be "
+                              "marked as optional and not as mandatory");
+      assert( ARMBuildAttrs::ULEB128 == ParameterType && "subsection .aeabi_feature_and_bits should "
+                                   "be marked as uleb128 and not as ntbs");
+      StringRef SubsectionName = getVendorName(ARMBuildAttrs::AEABI_FEATURE_AND_BITS);
+      OS << "\t" << SubsectionTag << "\t" << SubsectionName << ", "
+         << OptionalStr << ", " << ParameterStr;
+      break;
+    }
+    }
     OS << "\n";
   }
 
@@ -380,56 +387,77 @@ AArch64ELFStreamer &AArch64TargetELFStreamer::getStreamer() {
   return static_cast<AArch64ELFStreamer &>(Streamer);
 }
 
+void AArch64TargetELFStreamer::activateSubsection(StringRef VendorName) {
+  for (MCELFStreamer::AttributeSubSection &SubSection : AttributeSubSections) {
+    if (VendorName == SubSection.VendorName) {
+      SubSection.IsActive = true;
+    } else {
+      SubSection.IsActive = false;
+    }
+  }
+}
+
 void AArch64TargetELFStreamer::emitSubsection(
-    unsigned Vendor, ARMBuildAttrs::SubsectionMandatory IsMandatory,
+    unsigned VendorID, ARMBuildAttrs::SubsectionOptional IsOptional,
     ARMBuildAttrs::SubsectionType ParameterType) {
-  StringRef VendorAsStr = ARMBuildAttrs::vendorToStr(Vendor);
+  StringRef VendorName = ARMBuildAttrs::getVendorName(VendorID);
 
   // If exists, return.
   for (MCELFStreamer::AttributeSubSection &SubSection : AttributeSubSections) {
-    if (SubSection.Vendor == VendorAsStr) {
-      llvm_unreachable("AArch64 build attributes subsection already exists");
+    if (VendorName == SubSection.VendorName) {
+      // This path might be reached when an assembly directive switches attribute subsection.
+      activateSubsection(VendorName);
       return;
     }
   }
   // else, add the subsection
   MCELFStreamer::AttributeSubSection AttSubSection;
-  AttSubSection.Vendor = VendorAsStr;
-  AttSubSection.IsMandatory = IsMandatory;
+  AttSubSection.VendorName = VendorName;
+  AttSubSection.IsOptional = IsOptional;
   AttSubSection.ParameterType = ParameterType;
   AttributeSubSections.push_back(AttSubSection);
+  activateSubsection(VendorName);
 }
 
-void AArch64TargetELFStreamer::emitAttribute(unsigned Vendor, unsigned Tag,
+void AArch64TargetELFStreamer::emitAttribute(unsigned VendorID, unsigned Tag,
                                              unsigned Value, bool Override) {
-  StringRef VendorAsStr = ARMBuildAttrs::vendorToStr(Vendor);
+  StringRef VendorName = ARMBuildAttrs::getVendorName(VendorID);
 
   if (AttributeSubSections.size() == 0) {
-    llvm_unreachable("Attribute can not be added unless the required AArch64 "
-                     "build attributes subsection exists");
+    assert(0 && "Can not add AArch64 build attribute: no AArch64 subsection exists");
     return;
   }
 
   for (MCELFStreamer::AttributeSubSection &SubSection : AttributeSubSections) {
-    if (SubSection.Vendor == VendorAsStr) {
+    if (VendorName == SubSection.VendorName) {
+      if (!SubSection.IsActive) {
+        assert(0 && "Can not add AArch64 build attribute: subsection is not active");
+        return;
+      }
       for (MCELFStreamer::AttributeItem &Item : SubSection.Content) {
         if (Item.Tag == Tag) {
           if (!Override) {
-            llvm_unreachable("Attribute exists but override is set to false");
-            return;
+            if (Item.IntValue != Value) {
+                assert(0 && "Can not add AArch64 build attribute: An attribute with the same tag and a different value allready exists");
+                return;
+            }
           }
         }
       }
-      MCELFStreamer::AttributeItem AttItem;
-      AttItem.Type = AttItem.NumericAttribute;
-      AttItem.Tag = Tag;
-      AttItem.IntValue = Value;
-      SubSection.Content.push_back(AttItem);
+      SubSection.Content.push_back(MCELFStreamer::AttributeItem(MCELFStreamer::AttributeItem::NumericAttribute, Tag, Value, ""));
       return;
     }
   }
-  llvm_unreachable("Attribute can not be added unless the required AArch64 "
-                   "build attributes subsection exists");
+  assert(0 && "Can not add AArch64 build attribute: required subsection does not exists");
+}
+
+StringRef AArch64TargetELFStreamer::getActiveSubsection() {
+  for (MCELFStreamer::AttributeSubSection &SubSection : AttributeSubSections) {
+    if (SubSection.IsActive) {
+      return SubSection.VendorName;
+      }
+  }
+  return "";
 }
 
 void AArch64TargetELFStreamer::emitInst(uint32_t Inst) {
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h
index 1aa207b40a9326..ddc0ab77abe0cd 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h
@@ -14,10 +14,7 @@
 #include "llvm/MC/MCELFStreamer.h"
 #include "llvm/MC/MCStreamer.h"
 #include "llvm/Support/ARMBuildAttributes.h"
-#include "llvm/TableGen/Record.h"
-#include <cstddef>
 #include <cstdint>
-#include <utility>
 
 namespace {
 class AArch64ELFStreamer;
@@ -92,11 +89,13 @@ class AArch64TargetStreamer : public MCTargetStreamer {
   virtual void emitARM64WinCFISaveAnyRegQPX(unsigned Reg, int Offset) {}
 
   /// Build attributes implementation
-  virtual void emitSubsection(unsigned Vendor,
-                              ARMBuildAttrs::SubsectionMandatory IsMandatory,
+  virtual void emitSubsection(unsigned VendorID,
+                              ARMBuildAttrs::SubsectionOptional IsOptional,
                               ARMBuildAttrs::SubsectionType ParameterType) {}
-  virtual void emitAttribute(unsigned Vendor, unsigned Tag, unsigned Value,
+  virtual void emitAttribute(unsigned VendorID, unsigned Tag, unsigned Value,
                              bool Override) {}
+  virtual void activateSubsection(StringRef VendorName) {}
+  virtual StringRef getActiveSubsection() { return ""; }
 
 private:
   std::unique_ptr<AssemblerConstantPools> ConstantPools;
@@ -104,26 +103,26 @@ class AArch64TargetStreamer : public MCTargetStreamer {
 
 class AArch64TargetELFStreamer : public AArch64TargetStreamer {
 private:
-  StringRef CurrentVendor;
   AArch64ELFStreamer &getStreamer();
 
   MCSection *AttributeSection = nullptr;
   SmallVector<MCELFStreamer::AttributeSubSection, 64> AttributeSubSections;
 
   /// Build attributes implementation
-  void emitSubsection(unsigned Vendor,
-                      ARMBuildAttrs::SubsectionMandatory IsMandatory,
+  void emitSubsection(unsigned VendorID,
+                      ARMBuildAttrs::SubsectionOptional IsOptional,
                       ARMBuildAttrs::SubsectionType ParameterType) override;
-  void emitAttribute(unsigned Vendor, unsigned Tag, unsigned Value,
-                     bool Override) override;
+  void emitAttribute(unsigned VendorID, unsigned Tag, unsigned Value,
+                     bool Override = false) override;
+  void activateSubsection(StringRef VendorName) override;
+  StringRef getActiveSubsection() override;
 
   void emitInst(uint32_t Inst) override;
   void emitDirectiveVariantPCS(MCSymbol *Symbol) override;
   void finish() override;
 
 public:
-  AArch64TargetELFStreamer(MCStreamer &S)
-      : AArch64TargetStreamer(S), CurrentVendor("aeabi") {}
+  AArch64TargetELFStreamer(MCStreamer &S) : AArch64TargetStreamer(S) {}
 };
 
 class AArch64TargetWinCOFFStreamer : public llvm::AArch64TargetStreamer {

>From b323e838f04a175a441c3f09a328e4ee065609e7 Mon Sep 17 00:00:00 2001
From: Sivan Shani <sivan.shani at arm.com>
Date: Tue, 17 Dec 2024 13:34:17 +0000
Subject: [PATCH 06/12] Formatting

---
 llvm/include/llvm/MC/MCELFStreamer.h          |   6 +-
 .../include/llvm/Support/ARMBuildAttributes.h |  25 +-
 llvm/lib/Support/ARMBuildAttrs.cpp            | 261 +++++++++---------
 .../AArch64/AsmParser/AArch64AsmParser.cpp    | 116 +++++---
 .../MCTargetDesc/AArch64ELFStreamer.cpp       |  78 ++++--
 5 files changed, 283 insertions(+), 203 deletions(-)

diff --git a/llvm/include/llvm/MC/MCELFStreamer.h b/llvm/include/llvm/MC/MCELFStreamer.h
index 80742e8c52fc3f..06ce9884f15cf5 100644
--- a/llvm/include/llvm/MC/MCELFStreamer.h
+++ b/llvm/include/llvm/MC/MCELFStreamer.h
@@ -107,12 +107,14 @@ class MCELFStreamer : public MCObjectStreamer {
     unsigned Tag;
     unsigned IntValue;
     std::string StringValue;
-    AttributeItem(Types Ty, unsigned Tg, unsigned IV, std::string SV) : Type(Ty), Tag(Tg), IntValue(IV), StringValue(SV) {}
+    AttributeItem(Types Ty, unsigned Tg, unsigned IV, std::string SV)
+        : Type(Ty), Tag(Tg), IntValue(IV), StringValue(SV) {}
   };
 
   /// ELF object attributes subsection support
   struct AttributeSubSection {
-    bool IsActive; // Indicates whether the section is the active section, required for assembly parsing
+    bool IsActive; // Indicates whether the section is the active section,
+                   // required for assembly parsing
     // [<uint32: subsection-length> NTBS: vendor-name <bytes: vendor-data>]*
     StringRef VendorName;
     // <uint8: optional> <uint8: parameter type> <attribute>*
diff --git a/llvm/include/llvm/Support/ARMBuildAttributes.h b/llvm/include/llvm/Support/ARMBuildAttributes.h
index 2cb5f72d927332..6d396842985dcd 100644
--- a/llvm/include/llvm/Support/ARMBuildAttributes.h
+++ b/llvm/include/llvm/Support/ARMBuildAttributes.h
@@ -31,20 +31,29 @@ StringRef getSubsectionTag();
 StringRef getAttrTag();
 
 /// AArch64 build attributes vendors IDs (a.k.a subsection name)
-enum VendorID : unsigned { AEABI_FEATURE_AND_BITS = 0, AEABI_PAUTHABI = 1, VENDOR_NOT_FOUND = 404 };
-static const StringRef VendorName[] = { "aeabi_feature_and_bits", "aeabi_pauthabi" };
+enum VendorID : unsigned {
+  AEABI_FEATURE_AND_BITS = 0,
+  AEABI_PAUTHABI = 1,
+  VENDOR_NOT_FOUND = 404
+};
+static const StringRef VendorName[] = {"aeabi_feature_and_bits",
+                                       "aeabi_pauthabi"};
 StringRef getVendorName(unsigned const Vendor);
 VendorID getVendorID(StringRef const Vendor);
 StringRef getSubsectionUnknownError();
 
-enum SubsectionOptional : unsigned { REQUIRED = 0, OPTIONAL = 1, OPTIONAL_NOT_FOUND = 404 };
-static const StringRef OptionalStr[] = { "required", "optional"};
+enum SubsectionOptional : unsigned {
+  REQUIRED = 0,
+  OPTIONAL = 1,
+  OPTIONAL_NOT_FOUND = 404
+};
+static const StringRef OptionalStr[] = {"required", "optional"};
 StringRef getOptionalStr(unsigned Optional);
 SubsectionOptional getOptionalID(StringRef Optional);
 StringRef getSubsectionOptionalUnknownError();
 
 enum SubsectionType : unsigned { ULEB128 = 0, NTBS = 1, TYPE_NOT_FOUND = 404 };
-static const StringRef TypeStr[] = { "uleb128", "ntbs" };
+static const StringRef TypeStr[] = {"uleb128", "ntbs"};
 StringRef getTypeStr(unsigned Type);
 SubsectionType getTypeID(StringRef Type);
 StringRef getSubsectionTypeUnknownError();
@@ -54,7 +63,8 @@ enum PauthABITags : unsigned {
   TAG_PAUTH_SCHEMA = 2,
   PAUTHABI_TAG_NOT_FOUND = 404
 };
-static const StringRef PauthABITagsStr[] = { "Tag_PAuth_Platform", "Tag_PAuth_Schema"};
+static const StringRef PauthABITagsStr[] = {"Tag_PAuth_Platform",
+                                            "Tag_PAuth_Schema"};
 StringRef getPauthABITagsStr(unsigned PauthABITag);
 PauthABITags getPauthABITagsID(StringRef PauthABITag);
 StringRef getPauthabiTagError();
@@ -65,7 +75,8 @@ enum FeatureAndBitsTags : unsigned {
   TAG_FEATURE_GCS = 2,
   FEATURE_AND_BITS_TAG_NOT_FOUND = 404
 };
-static const StringRef FeatureAndBitsTagsStr[] = { "Tag_Feature_BTI", "Tag_Feature_PAC", "Tag_Feature_GCS"};
+static const StringRef FeatureAndBitsTagsStr[] = {
+    "Tag_Feature_BTI", "Tag_Feature_PAC", "Tag_Feature_GCS"};
 StringRef getFeatureAndBitsTagsStr(unsigned FeatureAndBitsTag);
 FeatureAndBitsTags getFeatureAndBitsTagsID(StringRef FeatureAndBitsTag);
 StringRef getFeatureAndBitsTagError();
diff --git a/llvm/lib/Support/ARMBuildAttrs.cpp b/llvm/lib/Support/ARMBuildAttrs.cpp
index eb4ee5f6d15e09..0717a30cfd433e 100644
--- a/llvm/lib/Support/ARMBuildAttrs.cpp
+++ b/llvm/lib/Support/ARMBuildAttrs.cpp
@@ -8,139 +8,150 @@
 
 #include "llvm/Support/ARMBuildAttributes.h"
 
-
 namespace llvm {
-  class StringRef;
-  namespace ARMBuildAttrs {
-    // AArch64 build attributes
-    StringRef getSubsectionTag() { return "aeabi_subsection"; }
-    StringRef getAttrTag() { return "aeabi_attribute"; }
+class StringRef;
+namespace ARMBuildAttrs {
+// AArch64 build attributes
+StringRef getSubsectionTag() { return "aeabi_subsection"; }
+StringRef getAttrTag() { return "aeabi_attribute"; }
 
-    StringRef getVendorName(unsigned Vendor) {
-      switch (Vendor) {
-      case AEABI_FEATURE_AND_BITS:
-        return VendorName[AEABI_FEATURE_AND_BITS];
-      case AEABI_PAUTHABI:
-        return VendorName[AEABI_PAUTHABI];
-      case VENDOR_NOT_FOUND:
-      [[fallthrough]];
-      default:
-        assert(0 && "unknown AArch64 vendor");
-        return "";
-      }
-    }
-    VendorID getVendorID(StringRef Vendor) {
-      if(Vendor == VendorName[AEABI_FEATURE_AND_BITS]) {
-        return AEABI_FEATURE_AND_BITS;
-      }
-      if(Vendor == VendorName[AEABI_PAUTHABI]) {
-        return AEABI_PAUTHABI;
-      }
-      assert(0 && "unknown AArch64 vendor");
-      return VENDOR_NOT_FOUND;
-    }
-    StringRef getSubsectionUnknownError() { return "unknown AArch64 build attributes subsection"; }
+StringRef getVendorName(unsigned Vendor) {
+  switch (Vendor) {
+  case AEABI_FEATURE_AND_BITS:
+    return VendorName[AEABI_FEATURE_AND_BITS];
+  case AEABI_PAUTHABI:
+    return VendorName[AEABI_PAUTHABI];
+  case VENDOR_NOT_FOUND:
+    [[fallthrough]];
+  default:
+    assert(0 && "unknown AArch64 vendor");
+    return "";
+  }
+}
+VendorID getVendorID(StringRef Vendor) {
+  if (Vendor == VendorName[AEABI_FEATURE_AND_BITS]) {
+    return AEABI_FEATURE_AND_BITS;
+  }
+  if (Vendor == VendorName[AEABI_PAUTHABI]) {
+    return AEABI_PAUTHABI;
+  }
+  assert(0 && "unknown AArch64 vendor");
+  return VENDOR_NOT_FOUND;
+}
+StringRef getSubsectionUnknownError() {
+  return "unknown AArch64 build attributes subsection";
+}
 
-    StringRef getOptionalStr(unsigned Optional) {
-      switch (Optional) {
-      case REQUIRED:
-        return OptionalStr[REQUIRED];
-      case OPTIONAL:
-        return OptionalStr[OPTIONAL];
-      case OPTIONAL_NOT_FOUND:
-      [[fallthrough]];
-      default:
-        assert(0 && "unknown AArch64 Optional option");
-        return "";
-      }
-    }
-    SubsectionOptional getOptionalID(StringRef Optional) {
-      if(Optional == OptionalStr[REQUIRED])
-        return REQUIRED;
-      if(Optional == OptionalStr[OPTIONAL])
-        return OPTIONAL;
-      assert(0 && "unknown AArch64 Optional option");
-      return OPTIONAL_NOT_FOUND;
-    }
-    StringRef getSubsectionOptionalUnknownError() { return "unknown AArch64 build attributes optionality, expecting required|optional"; }
+StringRef getOptionalStr(unsigned Optional) {
+  switch (Optional) {
+  case REQUIRED:
+    return OptionalStr[REQUIRED];
+  case OPTIONAL:
+    return OptionalStr[OPTIONAL];
+  case OPTIONAL_NOT_FOUND:
+    [[fallthrough]];
+  default:
+    assert(0 && "unknown AArch64 Optional option");
+    return "";
+  }
+}
+SubsectionOptional getOptionalID(StringRef Optional) {
+  if (Optional == OptionalStr[REQUIRED])
+    return REQUIRED;
+  if (Optional == OptionalStr[OPTIONAL])
+    return OPTIONAL;
+  assert(0 && "unknown AArch64 Optional option");
+  return OPTIONAL_NOT_FOUND;
+}
+StringRef getSubsectionOptionalUnknownError() {
+  return "unknown AArch64 build attributes optionality, expecting "
+         "required|optional";
+}
 
-    StringRef getTypeStr(unsigned Type) {
-      switch (Type) {
-      case ULEB128:
-        return TypeStr[ULEB128];
-      case NTBS:
-        return TypeStr[NTBS];
-      case TYPE_NOT_FOUND:
-      [[fallthrough]];
-      default:
-        assert(0 && "unknown AArch64 subsection type");
-        return "";
-      }
-    }
-    SubsectionType getTypeID(StringRef Type) {
-      if(Type == TypeStr[ULEB128] || Type == (TypeStr[ULEB128].upper()))
-        return ULEB128;
-      if(Type == TypeStr[NTBS]|| Type == (TypeStr[NTBS].upper()))
-        return NTBS;
-      assert(0 && "unknown AArch64 subsection type");
-      return TYPE_NOT_FOUND;
-    }
-    StringRef getSubsectionTypeUnknownError() { return "unknown AArch64 build attributes type, expecting uleb128 or ntbs"; }
+StringRef getTypeStr(unsigned Type) {
+  switch (Type) {
+  case ULEB128:
+    return TypeStr[ULEB128];
+  case NTBS:
+    return TypeStr[NTBS];
+  case TYPE_NOT_FOUND:
+    [[fallthrough]];
+  default:
+    assert(0 && "unknown AArch64 subsection type");
+    return "";
+  }
+}
+SubsectionType getTypeID(StringRef Type) {
+  if (Type == TypeStr[ULEB128] || Type == (TypeStr[ULEB128].upper()))
+    return ULEB128;
+  if (Type == TypeStr[NTBS] || Type == (TypeStr[NTBS].upper()))
+    return NTBS;
+  assert(0 && "unknown AArch64 subsection type");
+  return TYPE_NOT_FOUND;
+}
+StringRef getSubsectionTypeUnknownError() {
+  return "unknown AArch64 build attributes type, expecting uleb128 or ntbs";
+}
 
-    StringRef getPauthABITagsStr(unsigned PauthABITag) {
-      switch(PauthABITag) {
-        case TAG_PAUTH_PLATFORM:
-          return PauthABITagsStr[TAG_PAUTH_PLATFORM - 1]; // Tag_PAuth_Platform = 1 in accordance with the spec
-        case TAG_PAUTH_SCHEMA:
-          return PauthABITagsStr[TAG_PAUTH_SCHEMA - 1]; // Tag_PAuth_Schema = 2 in accordance with the spec
-        case PAUTHABI_TAG_NOT_FOUND:
-          [[fallthrough]];
-        default:
-          assert(0 && "unknown pauthabi tag");
-          return "";
-      }
-    }
-    PauthABITags getPauthABITagsID(StringRef PauthABITag) {
-      if(PauthABITag == PauthABITagsStr[TAG_PAUTH_PLATFORM - 1])
-        return TAG_PAUTH_PLATFORM;
-      if(PauthABITag == PauthABITagsStr[TAG_PAUTH_SCHEMA - 1])
-        return TAG_PAUTH_SCHEMA;
-      assert(0 && "unknown FPauthABI tag");
-      return PAUTHABI_TAG_NOT_FOUND;
-    }
-    StringRef getPauthabiTagError() { return "unknown tag for the AArch64 Pauthabi subsection"; }
+StringRef getPauthABITagsStr(unsigned PauthABITag) {
+  switch (PauthABITag) {
+  case TAG_PAUTH_PLATFORM:
+    return PauthABITagsStr[TAG_PAUTH_PLATFORM - 1]; // Tag_PAuth_Platform = 1 in
+                                                    // accordance with the spec
+  case TAG_PAUTH_SCHEMA:
+    return PauthABITagsStr[TAG_PAUTH_SCHEMA - 1]; // Tag_PAuth_Schema = 2 in
+                                                  // accordance with the spec
+  case PAUTHABI_TAG_NOT_FOUND:
+    [[fallthrough]];
+  default:
+    assert(0 && "unknown pauthabi tag");
+    return "";
+  }
+}
+PauthABITags getPauthABITagsID(StringRef PauthABITag) {
+  if (PauthABITag == PauthABITagsStr[TAG_PAUTH_PLATFORM - 1])
+    return TAG_PAUTH_PLATFORM;
+  if (PauthABITag == PauthABITagsStr[TAG_PAUTH_SCHEMA - 1])
+    return TAG_PAUTH_SCHEMA;
+  assert(0 && "unknown FPauthABI tag");
+  return PAUTHABI_TAG_NOT_FOUND;
+}
+StringRef getPauthabiTagError() {
+  return "unknown tag for the AArch64 Pauthabi subsection";
+}
 
-    StringRef getFeatureAndBitsTagsStr(unsigned FeatureAndBitsTag) {
-      switch(FeatureAndBitsTag) {
-        case TAG_FEATURE_BTI:
-          return FeatureAndBitsTagsStr[TAG_FEATURE_BTI];
-        case TAG_FEATURE_PAC:
-          return FeatureAndBitsTagsStr[TAG_FEATURE_PAC];
-        case TAG_FEATURE_GCS:
-          return FeatureAndBitsTagsStr[TAG_FEATURE_GCS];
-        case FEATURE_AND_BITS_TAG_NOT_FOUND:
-          [[fallthrough]];
-        default:
-          assert(0 && "unknown feature and bits tag");
-          return "";
-      }
-    }
-    FeatureAndBitsTags getFeatureAndBitsTagsID(StringRef FeatureAndBitsTag) {
-      if(FeatureAndBitsTag == FeatureAndBitsTagsStr[TAG_FEATURE_BTI])
-        return TAG_FEATURE_BTI;
-      if(FeatureAndBitsTag == FeatureAndBitsTagsStr[TAG_FEATURE_PAC])
-        return TAG_FEATURE_PAC;
-      if(FeatureAndBitsTag == FeatureAndBitsTagsStr[TAG_FEATURE_GCS])
-        return TAG_FEATURE_GCS;
-      assert(0 && "unknown Feature and Bits tag");
-      return FEATURE_AND_BITS_TAG_NOT_FOUND;
-    }
-    StringRef getFeatureAndBitsTagError() { return "unknown tag for the AArch64 Feature And Bits subsection"; }
-    ///--- AArch64 build attributes
-  } // namespace ARMBuildAttrs
+StringRef getFeatureAndBitsTagsStr(unsigned FeatureAndBitsTag) {
+  switch (FeatureAndBitsTag) {
+  case TAG_FEATURE_BTI:
+    return FeatureAndBitsTagsStr[TAG_FEATURE_BTI];
+  case TAG_FEATURE_PAC:
+    return FeatureAndBitsTagsStr[TAG_FEATURE_PAC];
+  case TAG_FEATURE_GCS:
+    return FeatureAndBitsTagsStr[TAG_FEATURE_GCS];
+  case FEATURE_AND_BITS_TAG_NOT_FOUND:
+    [[fallthrough]];
+  default:
+    assert(0 && "unknown feature and bits tag");
+    return "";
+  }
+}
+FeatureAndBitsTags getFeatureAndBitsTagsID(StringRef FeatureAndBitsTag) {
+  if (FeatureAndBitsTag == FeatureAndBitsTagsStr[TAG_FEATURE_BTI])
+    return TAG_FEATURE_BTI;
+  if (FeatureAndBitsTag == FeatureAndBitsTagsStr[TAG_FEATURE_PAC])
+    return TAG_FEATURE_PAC;
+  if (FeatureAndBitsTag == FeatureAndBitsTagsStr[TAG_FEATURE_GCS])
+    return TAG_FEATURE_GCS;
+  assert(0 && "unknown Feature and Bits tag");
+  return FEATURE_AND_BITS_TAG_NOT_FOUND;
+}
+StringRef getFeatureAndBitsTagError() {
+  return "unknown tag for the AArch64 Feature And Bits subsection";
+}
+///--- AArch64 build attributes
+} // namespace ARMBuildAttrs
 } // namespace llvm
 
-
 using namespace llvm;
 
 static const TagNameItem tagData[] = {
diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index c17e24e44f3ae3..cd0f34ddc32907 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -7068,11 +7068,12 @@ bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
     else
       return true;
   } else if (!IsMachO && !IsCOFF) {
-      if (IDVal == ".aeabi_subsection")
-        parseDirectiveAeabiSubSectionHeader(Loc);
-      else if (IDVal == ".aeabi_attribute")
-        parseDirectiveAeabiAArch64Attr(Loc);
-  } else return true;
+    if (IDVal == ".aeabi_subsection")
+      parseDirectiveAeabiSubSectionHeader(Loc);
+    else if (IDVal == ".aeabi_attribute")
+      parseDirectiveAeabiAArch64Attr(Loc);
+  } else
+    return true;
   return false;
 }
 
@@ -7808,9 +7809,9 @@ bool AArch64AsmParser::parseDirectiveSEHSaveAnyReg(SMLoc L, bool Paired,
 }
 
 bool AArch64AsmParser::parseDirectiveAeabiSubSectionHeader(SMLoc L) {
-  // Expecting 3 AsmToken::Identifier after '.aeabi_subsection', a name and 2 parameters, e.g.:
-  // .aeabi_subsection (1)aeabi_feature_and_bits, (2)optional, (3)uleb128
-  // separated by 2 commas.
+  // Expecting 3 AsmToken::Identifier after '.aeabi_subsection', a name and 2
+  // parameters, e.g.: .aeabi_subsection (1)aeabi_feature_and_bits, (2)optional,
+  // (3)uleb128 separated by 2 commas.
   MCAsmParser &Parser = getParser();
 
   // Consume the name (subsection name)
@@ -7820,15 +7821,17 @@ bool AArch64AsmParser::parseDirectiveAeabiSubSectionHeader(SMLoc L) {
     StringRef SubsectionName = Parser.getTok().getIdentifier();
     SubsectionNameID = ARMBuildAttrs::getVendorID(SubsectionName);
     if (ARMBuildAttrs::VENDOR_NOT_FOUND == SubsectionNameID) {
-      Error(Parser.getTok().getLoc(), ARMBuildAttrs::getSubsectionUnknownError() + ": " + SubsectionName);
+      Error(Parser.getTok().getLoc(),
+            ARMBuildAttrs::getSubsectionUnknownError() + ": " + SubsectionName);
     }
   } else {
-      Error(Parser.getTok().getLoc(), "Expecting subsection name");
-      return true;
+    Error(Parser.getTok().getLoc(), "Expecting subsection name");
+    return true;
   }
   Parser.Lex();
   // consume a comma
-  // parseComma() return *false* on success, and call Lex(), no need to call Lex() again.
+  // parseComma() return *false* on success, and call Lex(), no need to call
+  // Lex() again.
   if (Parser.parseComma()) {
     Error(Parser.getTok().getLoc(), "expected ','");
     return true;
@@ -7841,24 +7844,29 @@ bool AArch64AsmParser::parseDirectiveAeabiSubSectionHeader(SMLoc L) {
     StringRef Name = Parser.getTok().getIdentifier();
     IsOptional = ARMBuildAttrs::getOptionalID(Name);
     if (ARMBuildAttrs::OPTIONAL_NOT_FOUND == IsOptional) {
-      Error(Parser.getTok().getLoc(), ARMBuildAttrs::getSubsectionOptionalUnknownError() + ": " + Name);
+      Error(Parser.getTok().getLoc(),
+            ARMBuildAttrs::getSubsectionOptionalUnknownError() + ": " + Name);
       return true;
     }
   } else {
-      Error(Parser.getTok().getLoc(), "Expecitng optionality parameter \n Hint: use 'optional' | 'required'");
-      return true;
+    Error(
+        Parser.getTok().getLoc(),
+        "Expecitng optionality parameter \n Hint: use 'optional' | 'required'");
+    return true;
   }
   // Check for possible IsOptional unaccepted values for known subsections
   if (ARMBuildAttrs::AEABI_FEATURE_AND_BITS == SubsectionNameID) {
     if (ARMBuildAttrs::REQUIRED == IsOptional) {
-        Error(Parser.getTok().getLoc(), "aeabi_feature_and_bits must be marked as optional");
-        return true;
+      Error(Parser.getTok().getLoc(),
+            "aeabi_feature_and_bits must be marked as optional");
+      return true;
     }
   }
   if (ARMBuildAttrs::AEABI_PAUTHABI == SubsectionNameID) {
     if (ARMBuildAttrs::OPTIONAL == IsOptional) {
-        Error(Parser.getTok().getLoc(), "aeabi_pauthabi must be marked as required");
-        return true;
+      Error(Parser.getTok().getLoc(),
+            "aeabi_pauthabi must be marked as required");
+      return true;
     }
   }
   Parser.Lex();
@@ -7874,24 +7882,28 @@ bool AArch64AsmParser::parseDirectiveAeabiSubSectionHeader(SMLoc L) {
     StringRef Name = Parser.getTok().getIdentifier();
     Type = ARMBuildAttrs::getTypeID(Name);
     if (ARMBuildAttrs::TYPE_NOT_FOUND == Type) {
-      Error(Parser.getTok().getLoc(), ARMBuildAttrs::getSubsectionTypeUnknownError() + ": " + Name);
+      Error(Parser.getTok().getLoc(),
+            ARMBuildAttrs::getSubsectionTypeUnknownError() + ": " + Name);
       return true;
     }
   } else {
-      Error(Parser.getTok().getLoc(), "Expecitng type parameter");
-      return true;
+    Error(Parser.getTok().getLoc(), "Expecitng type parameter");
+    return true;
   }
   // Check for possible Type unaccepted values for known subsections
-  if (ARMBuildAttrs::AEABI_FEATURE_AND_BITS == SubsectionNameID || ARMBuildAttrs::AEABI_PAUTHABI == SubsectionNameID) {
+  if (ARMBuildAttrs::AEABI_FEATURE_AND_BITS == SubsectionNameID ||
+      ARMBuildAttrs::AEABI_PAUTHABI == SubsectionNameID) {
     if (ARMBuildAttrs::NTBS == Type) {
-        Error(Parser.getTok().getLoc(), SubsectionName + "must be marked as ULEB128");
-        return true;
+      Error(Parser.getTok().getLoc(),
+            SubsectionName + "must be marked as ULEB128");
+      return true;
     }
   }
   Parser.Lex();
   // Parsing finished, check for trailing tokens.
   if (Parser.getTok().isNot(llvm::AsmToken::EndOfStatement)) {
-    Error(Parser.getTok().getLoc(), "unexpected token for AArch64 build attributes subsection header directive");
+    Error(Parser.getTok().getLoc(), "unexpected token for AArch64 build "
+                                    "attributes subsection header directive");
     return true;
   }
 
@@ -7914,34 +7926,45 @@ bool AArch64AsmParser::parseDirectiveAeabiAArch64Attr(SMLoc L) {
     TagStr = Parser.getTok().getIdentifier();
     ActiveSubsection = getTargetStreamer().getActiveSubsection();
     if ("" == ActiveSubsection) {
-      Error(Parser.getTok().getLoc(), "no active subsection, build attribute can not be added");
+      Error(Parser.getTok().getLoc(),
+            "no active subsection, build attribute can not be added");
       return true;
     }
-    if(ARMBuildAttrs::VendorName[ARMBuildAttrs::AEABI_PAUTHABI] == ActiveSubsection) {
+    if (ARMBuildAttrs::VendorName[ARMBuildAttrs::AEABI_PAUTHABI] ==
+        ActiveSubsection) {
       ActiveSubsectionID = ARMBuildAttrs::AEABI_PAUTHABI;
       Tag = ARMBuildAttrs::getPauthABITagsID(TagStr);
       if (ARMBuildAttrs::PAUTHABI_TAG_NOT_FOUND == Tag) {
-        Error(Parser.getTok().getLoc(), "Unknown AArch64 build attribute '" + TagStr + "' for subsection '" + ActiveSubsection + "'");
+        Error(Parser.getTok().getLoc(), "Unknown AArch64 build attribute '" +
+                                            TagStr + "' for subsection '" +
+                                            ActiveSubsection + "'");
         return true;
       }
-    } else if(ARMBuildAttrs::VendorName[ARMBuildAttrs::AEABI_FEATURE_AND_BITS] == ActiveSubsection) {
+    } else if (ARMBuildAttrs::VendorName
+                   [ARMBuildAttrs::AEABI_FEATURE_AND_BITS] ==
+               ActiveSubsection) {
       ActiveSubsectionID = ARMBuildAttrs::AEABI_FEATURE_AND_BITS;
       Tag = ARMBuildAttrs::getFeatureAndBitsTagsID(TagStr);
       if (ARMBuildAttrs::FEATURE_AND_BITS_TAG_NOT_FOUND == Tag) {
-        Error(Parser.getTok().getLoc(), "Unknown AArch64 build attribute '" + TagStr + "' for subsection '" + ActiveSubsection + "' \n Hint: options are: Tag_Feature_BTI, Tag_Feature_PAC, Tag_Feature_GCS");
+        Error(Parser.getTok().getLoc(),
+              "Unknown AArch64 build attribute '" + TagStr +
+                  "' for subsection '" + ActiveSubsection +
+                  "' \n Hint: options are: Tag_Feature_BTI, Tag_Feature_PAC, "
+                  "Tag_Feature_GCS");
         return true;
       }
     }
-  // for compatability
-  } else if(Parser.getTok().is(AsmToken::Integer)) {
+    // for compatability
+  } else if (Parser.getTok().is(AsmToken::Integer)) {
     Tag = getTok().getIntVal();
   } else {
-      Error(Parser.getTok().getLoc(), "AArch64 build attributes Tag not found");
-      return true;
+    Error(Parser.getTok().getLoc(), "AArch64 build attributes Tag not found");
+    return true;
   }
   Parser.Lex();
   // consume a comma
-  // parseComma() return *false* on success, and call Lex(), no need to call Lex() again.
+  // parseComma() return *false* on success, and call Lex(), no need to call
+  // Lex() again.
   if (Parser.parseComma()) {
     Error(Parser.getTok().getLoc(), "expected ','");
     return true;
@@ -7952,25 +7975,32 @@ bool AArch64AsmParser::parseDirectiveAeabiAArch64Attr(SMLoc L) {
   if (Parser.getTok().is(AsmToken::Integer)) {
     Value = getTok().getIntVal();
   } else {
-      Error(Parser.getTok().getLoc(), "AArch64 build attributes Value not found");
-      return true;
+    Error(Parser.getTok().getLoc(), "AArch64 build attributes Value not found");
+    return true;
   }
   // Check for possible unaccepted values for known tags
   if (TagStr != "") { // Tag was a recognized string
     if (0 != Value && 1 != Value) {
-      Error(Parser.getTok().getLoc(), "Unknown AArch64 build attributes Value for Tag '" + TagStr + "' \n Hint: options are '0'|'1'");
+      Error(Parser.getTok().getLoc(),
+            "Unknown AArch64 build attributes Value for Tag '" + TagStr +
+                "' \n Hint: options are '0'|'1'");
       return true;
     }
-  // Tag was an integer
-  } else if (0 == Tag || 1 == Tag || 2 == Tag) { // might be at attempt to represent known tags
+    // Tag was an integer
+  } else if (0 == Tag || 1 == Tag ||
+             2 == Tag) { // might be at attempt to represent known tags
     if (0 != Value && 1 != Value) {
-      Warning(Parser.getTok().getLoc(), "Unknown AArch64 build attributes Value for any known AArch64 build attributes tags");
+      Warning(Parser.getTok().getLoc(),
+              "Unknown AArch64 build attributes Value for any known AArch64 "
+              "build attributes tags");
     }
   }
   Parser.Lex();
   // Parsing finished, check for trailing tokens.
   if (Parser.getTok().isNot(llvm::AsmToken::EndOfStatement)) {
-    Error(Parser.getTok().getLoc(), "unexpected token for AArch64 build attributes tag and value attribute directive");
+    Error(Parser.getTok().getLoc(),
+          "unexpected token for AArch64 build attributes tag and value "
+          "attribute directive");
     return true;
   }
 
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp
index 00d72d15f1cc6f..902cb3c416d6c2 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp
@@ -166,13 +166,22 @@ class AArch64TargetAsmStreamer : public AArch64TargetStreamer {
         assert(0 && ARMBuildAttrs::getFeatureAndBitsTagError().data());
         break;
       case ARMBuildAttrs::TAG_FEATURE_BTI:
-        OS << "\t." << ARMBuildAttrs::getAttrTag() << "\t" << ARMBuildAttrs::getFeatureAndBitsTagsStr(ARMBuildAttrs::TAG_FEATURE_BTI) << ", " << Value;
+        OS << "\t." << ARMBuildAttrs::getAttrTag() << "\t"
+           << ARMBuildAttrs::getFeatureAndBitsTagsStr(
+                  ARMBuildAttrs::TAG_FEATURE_BTI)
+           << ", " << Value;
         break;
       case ARMBuildAttrs::TAG_FEATURE_GCS:
-        OS << "\t." << ARMBuildAttrs::getAttrTag() << "\t" << ARMBuildAttrs::getFeatureAndBitsTagsStr(ARMBuildAttrs::TAG_FEATURE_GCS) << ", " << Value;
+        OS << "\t." << ARMBuildAttrs::getAttrTag() << "\t"
+           << ARMBuildAttrs::getFeatureAndBitsTagsStr(
+                  ARMBuildAttrs::TAG_FEATURE_GCS)
+           << ", " << Value;
         break;
       case ARMBuildAttrs::TAG_FEATURE_PAC:
-        OS << "\t." << ARMBuildAttrs::getAttrTag() << "\t" << ARMBuildAttrs::getFeatureAndBitsTagsStr(ARMBuildAttrs::TAG_FEATURE_PAC) << ", " << Value;
+        OS << "\t." << ARMBuildAttrs::getAttrTag() << "\t"
+           << ARMBuildAttrs::getFeatureAndBitsTagsStr(
+                  ARMBuildAttrs::TAG_FEATURE_PAC)
+           << ", " << Value;
         break;
       }
       break;
@@ -183,10 +192,15 @@ class AArch64TargetAsmStreamer : public AArch64TargetStreamer {
         assert(0 && ARMBuildAttrs::getFeatureAndBitsTagError().data());
         break;
       case ARMBuildAttrs::TAG_PAUTH_PLATFORM:
-        OS << "\t." << ARMBuildAttrs::getAttrTag() << "\t" << ARMBuildAttrs::getPauthABITagsStr(ARMBuildAttrs::TAG_PAUTH_PLATFORM) << ", " << Value;
+        OS << "\t." << ARMBuildAttrs::getAttrTag() << "\t"
+           << ARMBuildAttrs::getPauthABITagsStr(
+                  ARMBuildAttrs::TAG_PAUTH_PLATFORM)
+           << ", " << Value;
         break;
       case ARMBuildAttrs::TAG_PAUTH_SCHEMA:
-        OS << "\t." << ARMBuildAttrs::getAttrTag() << "\t" << ARMBuildAttrs::getPauthABITagsStr(ARMBuildAttrs::TAG_PAUTH_SCHEMA) << ", " << Value;
+        OS << "\t." << ARMBuildAttrs::getAttrTag() << "\t"
+           << ARMBuildAttrs::getPauthABITagsStr(ARMBuildAttrs::TAG_PAUTH_SCHEMA)
+           << ", " << Value;
         break;
         break;
       }
@@ -202,9 +216,9 @@ class AArch64TargetAsmStreamer : public AArch64TargetStreamer {
     // optional: required (0) optional (1)
     // parameter type: uleb128 or ULEB128 (0) ntbs or NTBS (1)
 
-    assert(( 0 == Optional || 1 == Optional) &&
+    assert((0 == Optional || 1 == Optional) &&
            ARMBuildAttrs::getSubsectionOptionalUnknownError().data());
-    assert(( 0 == ParameterType || 1 == ParameterType) &&
+    assert((0 == ParameterType || 1 == ParameterType) &&
            ARMBuildAttrs::getSubsectionTypeUnknownError().data());
 
     std::string SubsectionTag = ("." + ARMBuildAttrs::getSubsectionTag()).str();
@@ -217,21 +231,26 @@ class AArch64TargetAsmStreamer : public AArch64TargetStreamer {
       break;
     }
     case ARMBuildAttrs::AEABI_PAUTHABI: {
-      assert(ARMBuildAttrs::REQUIRED == Optional && "subsection .aeabi-pauthabi should be marked as "
-                              "mandatory and not as optional");
-      assert(ARMBuildAttrs::ULEB128 == ParameterType && "subsection .aeabi-pauthabi should be "
-                                   "marked as uleb128 and not as ntbs");
+      assert(ARMBuildAttrs::REQUIRED == Optional &&
+             "subsection .aeabi-pauthabi should be marked as "
+             "mandatory and not as optional");
+      assert(ARMBuildAttrs::ULEB128 == ParameterType &&
+             "subsection .aeabi-pauthabi should be "
+             "marked as uleb128 and not as ntbs");
       StringRef SubsectionName = getVendorName(ARMBuildAttrs::AEABI_PAUTHABI);
-      OS << "\t" << SubsectionTag << "\t" << SubsectionName << ", " << OptionalStr
-         << ", " << ParameterStr;
+      OS << "\t" << SubsectionTag << "\t" << SubsectionName << ", "
+         << OptionalStr << ", " << ParameterStr;
       break;
     }
     case ARMBuildAttrs::AEABI_FEATURE_AND_BITS: {
-      assert( ARMBuildAttrs::OPTIONAL == Optional && "subsection .aeabi_feature_and_bits should be "
-                              "marked as optional and not as mandatory");
-      assert( ARMBuildAttrs::ULEB128 == ParameterType && "subsection .aeabi_feature_and_bits should "
-                                   "be marked as uleb128 and not as ntbs");
-      StringRef SubsectionName = getVendorName(ARMBuildAttrs::AEABI_FEATURE_AND_BITS);
+      assert(ARMBuildAttrs::OPTIONAL == Optional &&
+             "subsection .aeabi_feature_and_bits should be "
+             "marked as optional and not as mandatory");
+      assert(ARMBuildAttrs::ULEB128 == ParameterType &&
+             "subsection .aeabi_feature_and_bits should "
+             "be marked as uleb128 and not as ntbs");
+      StringRef SubsectionName =
+          getVendorName(ARMBuildAttrs::AEABI_FEATURE_AND_BITS);
       OS << "\t" << SubsectionTag << "\t" << SubsectionName << ", "
          << OptionalStr << ", " << ParameterStr;
       break;
@@ -405,7 +424,8 @@ void AArch64TargetELFStreamer::emitSubsection(
   // If exists, return.
   for (MCELFStreamer::AttributeSubSection &SubSection : AttributeSubSections) {
     if (VendorName == SubSection.VendorName) {
-      // This path might be reached when an assembly directive switches attribute subsection.
+      // This path might be reached when an assembly directive switches
+      // attribute subsection.
       activateSubsection(VendorName);
       return;
     }
@@ -424,38 +444,44 @@ void AArch64TargetELFStreamer::emitAttribute(unsigned VendorID, unsigned Tag,
   StringRef VendorName = ARMBuildAttrs::getVendorName(VendorID);
 
   if (AttributeSubSections.size() == 0) {
-    assert(0 && "Can not add AArch64 build attribute: no AArch64 subsection exists");
+    assert(0 &&
+           "Can not add AArch64 build attribute: no AArch64 subsection exists");
     return;
   }
 
   for (MCELFStreamer::AttributeSubSection &SubSection : AttributeSubSections) {
     if (VendorName == SubSection.VendorName) {
       if (!SubSection.IsActive) {
-        assert(0 && "Can not add AArch64 build attribute: subsection is not active");
+        assert(0 &&
+               "Can not add AArch64 build attribute: subsection is not active");
         return;
       }
       for (MCELFStreamer::AttributeItem &Item : SubSection.Content) {
         if (Item.Tag == Tag) {
           if (!Override) {
             if (Item.IntValue != Value) {
-                assert(0 && "Can not add AArch64 build attribute: An attribute with the same tag and a different value allready exists");
-                return;
+              assert(0 &&
+                     "Can not add AArch64 build attribute: An attribute with "
+                     "the same tag and a different value allready exists");
+              return;
             }
           }
         }
       }
-      SubSection.Content.push_back(MCELFStreamer::AttributeItem(MCELFStreamer::AttributeItem::NumericAttribute, Tag, Value, ""));
+      SubSection.Content.push_back(MCELFStreamer::AttributeItem(
+          MCELFStreamer::AttributeItem::NumericAttribute, Tag, Value, ""));
       return;
     }
   }
-  assert(0 && "Can not add AArch64 build attribute: required subsection does not exists");
+  assert(0 && "Can not add AArch64 build attribute: required subsection does "
+              "not exists");
 }
 
 StringRef AArch64TargetELFStreamer::getActiveSubsection() {
   for (MCELFStreamer::AttributeSubSection &SubSection : AttributeSubSections) {
     if (SubSection.IsActive) {
       return SubSection.VendorName;
-      }
+    }
   }
   return "";
 }

>From 4505446f019489edc23328dfcb5018a4ab092580 Mon Sep 17 00:00:00 2001
From: Sivan Shani <sivan.shani at arm.com>
Date: Tue, 17 Dec 2024 14:19:55 +0000
Subject: [PATCH 07/12] add llvm test files

---
 .../aarch64-build-attributes-asm-all.ll       | 22 +++++++++++++++++++
 .../aarch64-build-attributes-asm-bti.ll       | 20 +++++++++++++++++
 .../aarch64-build-attributes-asm-gcs.ll       | 20 +++++++++++++++++
 .../aarch64-build-attributes-asm-pac.ll       | 20 +++++++++++++++++
 4 files changed, 82 insertions(+)
 create mode 100644 llvm/test/CodeGen/AArch64/aarch64-build-attributes-asm-all.ll
 create mode 100644 llvm/test/CodeGen/AArch64/aarch64-build-attributes-asm-bti.ll
 create mode 100644 llvm/test/CodeGen/AArch64/aarch64-build-attributes-asm-gcs.ll
 create mode 100644 llvm/test/CodeGen/AArch64/aarch64-build-attributes-asm-pac.ll

diff --git a/llvm/test/CodeGen/AArch64/aarch64-build-attributes-asm-all.ll b/llvm/test/CodeGen/AArch64/aarch64-build-attributes-asm-all.ll
new file mode 100644
index 00000000000000..81ece7aec8793b
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/aarch64-build-attributes-asm-all.ll
@@ -0,0 +1,22 @@
+; RUN: llc %s -o - | FileCheck %s --check-prefix=ASM
+; RUN: llc %s -filetype=obj -o - | llvm-readelf --hex-dump=.ARM.attributes - | FileCheck %s --check-prefix=ELF
+
+; ASM: .text
+; ASM-NEXT:      .aeabi_subsection	aeabi_feature_and_bits, optional, uleb128
+; ASM-NEXT: .aeabi_attribute	Tag_Feature_BTI, 1
+; ASM-NEXT: .aeabi_attribute	Tag_Feature_PAC, 1
+; ASM-NEXT: .aeabi_attribute	Tag_Feature_GCS, 1
+
+; ELF: Hex dump of section '.ARM.attributes':
+; ELF-NEXT: 0x00000000 41230000 00616561 62695f66 65617475 A#...aeabi_featu
+; ELF-NEXT: 0x00000010 72655f61 6e645f62 69747300 01000001 re_and_bits.....
+; ELF-NEXT: 0x00000020 01010201
+
+
+target triple = "aarch64-unknown-none-elf"
+
+!llvm.module.flags = !{!1, !2, !3}
+
+!1 = !{i32 8, !"branch-target-enforcement", i32 1}
+!2 = !{i32 8, !"guarded-control-stack", i32 1}
+!3 = !{i32 8, !"sign-return-address", i32 1}
diff --git a/llvm/test/CodeGen/AArch64/aarch64-build-attributes-asm-bti.ll b/llvm/test/CodeGen/AArch64/aarch64-build-attributes-asm-bti.ll
new file mode 100644
index 00000000000000..e719e06553cc0f
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/aarch64-build-attributes-asm-bti.ll
@@ -0,0 +1,20 @@
+; RUN: llc < %s | FileCheck %s --check-prefix=ASM
+; RUN: llc %s -filetype=obj -o - | llvm-readelf --hex-dump=.ARM.attributes - | FileCheck %s --check-prefix=ELF
+
+; ASM: .text
+; ASM-NEXT:      .aeabi_subsection	aeabi_feature_and_bits, optional, uleb128
+; ASM-NEXT: .aeabi_attribute	Tag_Feature_BTI, 1
+; ASM-NEXT: .aeabi_attribute	Tag_Feature_PAC, 0
+; ASM-NEXT: .aeabi_attribute	Tag_Feature_GCS, 0
+
+; ELF: Hex dump of section '.ARM.attributes':
+; ELF-NEXT: 0x00000000 41230000 00616561 62695f66 65617475 A#...aeabi_featu
+; ELF-NEXT: 0x00000010 72655f61 6e645f62 69747300 01000001 re_and_bits.....
+; ELF-NEXT: 0x00000020 01000200 
+
+
+target triple = "aarch64-unknown-none-elf"
+
+!llvm.module.flags = !{!1}
+
+!1 = !{i32 8, !"branch-target-enforcement", i32 1}
diff --git a/llvm/test/CodeGen/AArch64/aarch64-build-attributes-asm-gcs.ll b/llvm/test/CodeGen/AArch64/aarch64-build-attributes-asm-gcs.ll
new file mode 100644
index 00000000000000..6f231025a11e33
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/aarch64-build-attributes-asm-gcs.ll
@@ -0,0 +1,20 @@
+; RUN: llc < %s | FileCheck %s --check-prefix=ASM
+; RUN: llc %s -filetype=obj -o - | llvm-readelf --hex-dump=.ARM.attributes - | FileCheck %s --check-prefix=ELF
+
+; ASM: .text
+; ASM-NEXT:      .aeabi_subsection	aeabi_feature_and_bits, optional, uleb128
+; ASM-NEXT: .aeabi_attribute	Tag_Feature_BTI, 0
+; ASM-NEXT: .aeabi_attribute	Tag_Feature_PAC, 0
+; ASM-NEXT: .aeabi_attribute	Tag_Feature_GCS, 1
+
+; ELF: Hex dump of section '.ARM.attributes':
+; ELF-NEXT: 0x00000000 41230000 00616561 62695f66 65617475 A#...aeabi_featu
+; ELF-NEXT: 0x00000010 72655f61 6e645f62 69747300 01000000 re_and_bits.....
+; ELF-NEXT: 0x00000020 01000201
+
+
+target triple = "aarch64-unknown-none-elf"
+
+!llvm.module.flags = !{!1}
+
+!1 = !{i32 8, !"guarded-control-stack", i32 1}
diff --git a/llvm/test/CodeGen/AArch64/aarch64-build-attributes-asm-pac.ll b/llvm/test/CodeGen/AArch64/aarch64-build-attributes-asm-pac.ll
new file mode 100644
index 00000000000000..54ff12655eb23f
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/aarch64-build-attributes-asm-pac.ll
@@ -0,0 +1,20 @@
+; RUN: llc < %s | FileCheck %s --check-prefix=ASM
+; RUN: llc %s -filetype=obj -o - | llvm-readelf --hex-dump=.ARM.attributes - | FileCheck %s --check-prefix=ELF
+
+; ASM: .text
+; ASM-NEXT:      .aeabi_subsection	aeabi_feature_and_bits, optional, uleb128
+; ASM-NEXT: .aeabi_attribute	Tag_Feature_BTI, 0
+; ASM-NEXT: .aeabi_attribute	Tag_Feature_PAC, 1
+; ASM-NEXT: .aeabi_attribute	Tag_Feature_GCS, 0
+
+; ELF: Hex dump of section '.ARM.attributes':
+; ELF-NEXT: 0x00000000 41230000 00616561 62695f66 65617475 A#...aeabi_featu
+; ELF-NEXT: 0x00000010 72655f61 6e645f62 69747300 01000000 re_and_bits.....
+; ELF-NEXT: 0x00000020 01010200
+
+
+target triple = "aarch64-unknown-none-elf"
+
+!llvm.module.flags = !{!1}
+
+!1 = !{i32 8, !"sign-return-address", i32 1}

>From f4f1b1b5cd5ae0ce28226f54cc88b0b8b21068f8 Mon Sep 17 00:00:00 2001
From: Sivan Shani <sivan.shani at arm.com>
Date: Tue, 17 Dec 2024 15:19:03 +0000
Subject: [PATCH 08/12] format

---
 llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h
index 922dec799491be..6344a26e1d1efe 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h
@@ -9,10 +9,10 @@
 #ifndef LLVM_LIB_TARGET_AARCH64_MCTARGETDESC_AARCH64TARGETSTREAMER_H
 #define LLVM_LIB_TARGET_AARCH64_MCTARGETDESC_AARCH64TARGETSTREAMER_H
 
+#include "AArch64MCExpr.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/MC/MCELFStreamer.h"
-#include "AArch64MCExpr.h"
 #include "llvm/MC/MCStreamer.h"
 #include "llvm/Support/ARMBuildAttributes.h"
 #include <cstdint>

>From b651b3c81d38410aff4df7127502dcafb4ffe25e Mon Sep 17 00:00:00 2001
From: Sivan Shani <sivan.shani at arm.com>
Date: Tue, 17 Dec 2024 16:25:34 +0000
Subject: [PATCH 09/12] fix small bug

---
 llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index 1f0b761c6249a6..e31405b950d675 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -7824,7 +7824,7 @@ bool AArch64AsmParser::parseDirectiveAeabiSubSectionHeader(SMLoc L) {
   StringRef SubsectionName;
   ARMBuildAttrs::VendorID SubsectionNameID;
   if (Parser.getTok().is(AsmToken::Identifier)) {
-    StringRef SubsectionName = Parser.getTok().getIdentifier();
+    SubsectionName = Parser.getTok().getIdentifier();
     SubsectionNameID = ARMBuildAttrs::getVendorID(SubsectionName);
     if (ARMBuildAttrs::VENDOR_NOT_FOUND == SubsectionNameID) {
       Error(Parser.getTok().getLoc(),
@@ -7901,7 +7901,7 @@ bool AArch64AsmParser::parseDirectiveAeabiSubSectionHeader(SMLoc L) {
       ARMBuildAttrs::AEABI_PAUTHABI == SubsectionNameID) {
     if (ARMBuildAttrs::NTBS == Type) {
       Error(Parser.getTok().getLoc(),
-            SubsectionName + "must be marked as ULEB128");
+            SubsectionName + " must be marked as ULEB128");
       return true;
     }
   }

>From 7cde2152976c1b48f0a958a7b37288fbffd9c7cc Mon Sep 17 00:00:00 2001
From: Sivan Shani <sivan.shani at arm.com>
Date: Wed, 18 Dec 2024 13:13:47 +0000
Subject: [PATCH 10/12] Fix a bug

---
 llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index e31405b950d675..dca39f834cefcf 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -6978,6 +6978,7 @@ bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
   const MCContext::Environment Format = getContext().getObjectFileType();
   bool IsMachO = Format == MCContext::IsMachO;
   bool IsCOFF = Format == MCContext::IsCOFF;
+  bool IsELF = Format == MCContext::IsELF;
 
   auto IDVal = DirectiveID.getIdentifier().lower();
   SMLoc Loc = DirectiveID.getLoc();
@@ -7073,11 +7074,13 @@ bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
       parseDirectiveSEHSaveAnyReg(Loc, true, true);
     else
       return true;
-  } else if (!IsMachO && !IsCOFF) {
+  } else if (IsELF) {
     if (IDVal == ".aeabi_subsection")
       parseDirectiveAeabiSubSectionHeader(Loc);
     else if (IDVal == ".aeabi_attribute")
       parseDirectiveAeabiAArch64Attr(Loc);
+    else
+     return true;
   } else
     return true;
   return false;

>From 07b1f745d7d43e0af198fe8d99734ae0b2aefa74 Mon Sep 17 00:00:00 2001
From: Sivan Shani <sivan.shani at arm.com>
Date: Wed, 18 Dec 2024 13:28:14 +0000
Subject: [PATCH 11/12] format

---
 llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index dca39f834cefcf..00833892a1a49f 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -7080,7 +7080,7 @@ bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
     else if (IDVal == ".aeabi_attribute")
       parseDirectiveAeabiAArch64Attr(Loc);
     else
-     return true;
+      return true;
   } else
     return true;
   return false;

>From 06215d91de16eb01afd88bd2df234248027286a8 Mon Sep 17 00:00:00 2001
From: Sivan Shani <sivan.shani at arm.com>
Date: Wed, 18 Dec 2024 17:21:15 +0000
Subject: [PATCH 12/12] - add llvm-mc test files - fix bug

---
 .../MCTargetDesc/AArch64ELFStreamer.cpp       | 92 ++++---------------
 .../MCTargetDesc/AArch64TargetStreamer.cpp    | 78 ++++++++++++++++
 .../MCTargetDesc/AArch64TargetStreamer.h      | 13 ++-
 .../aarch64-build-attributes-asm-all.s        | 27 ++++++
 .../aarch64-build-attributes-asm-bti.s        | 19 ++++
 .../aarch64-build-attributes-asm-gcs.s        | 19 ++++
 .../aarch64-build-attributes-asm-none.s       | 27 ++++++
 ...arch64-build-attributes-asm-out-of-order.s | 50 ++++++++++
 .../aarch64-build-attributes-asm-pac.s        | 19 ++++
 9 files changed, 262 insertions(+), 82 deletions(-)
 create mode 100644 llvm/test/MC/AArch64/aarch64-build-attributes-asm-all.s
 create mode 100644 llvm/test/MC/AArch64/aarch64-build-attributes-asm-bti.s
 create mode 100644 llvm/test/MC/AArch64/aarch64-build-attributes-asm-gcs.s
 create mode 100644 llvm/test/MC/AArch64/aarch64-build-attributes-asm-none.s
 create mode 100644 llvm/test/MC/AArch64/aarch64-build-attributes-asm-out-of-order.s
 create mode 100644 llvm/test/MC/AArch64/aarch64-build-attributes-asm-pac.s

diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp
index 902cb3c416d6c2..26d1441f3120d6 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp
@@ -170,18 +170,23 @@ class AArch64TargetAsmStreamer : public AArch64TargetStreamer {
            << ARMBuildAttrs::getFeatureAndBitsTagsStr(
                   ARMBuildAttrs::TAG_FEATURE_BTI)
            << ", " << Value;
+        // Keep the data structure consistent with the case of ELF emission
+        // (important for llvm-mc asm parsing)
+        AArch64TargetStreamer::emitAttribute(VendorID, Tag, Value, Override);
         break;
       case ARMBuildAttrs::TAG_FEATURE_GCS:
         OS << "\t." << ARMBuildAttrs::getAttrTag() << "\t"
            << ARMBuildAttrs::getFeatureAndBitsTagsStr(
                   ARMBuildAttrs::TAG_FEATURE_GCS)
            << ", " << Value;
+        AArch64TargetStreamer::emitAttribute(VendorID, Tag, Value, Override);
         break;
       case ARMBuildAttrs::TAG_FEATURE_PAC:
         OS << "\t." << ARMBuildAttrs::getAttrTag() << "\t"
            << ARMBuildAttrs::getFeatureAndBitsTagsStr(
                   ARMBuildAttrs::TAG_FEATURE_PAC)
            << ", " << Value;
+        AArch64TargetStreamer::emitAttribute(VendorID, Tag, Value, Override);
         break;
       }
       break;
@@ -196,26 +201,26 @@ class AArch64TargetAsmStreamer : public AArch64TargetStreamer {
            << ARMBuildAttrs::getPauthABITagsStr(
                   ARMBuildAttrs::TAG_PAUTH_PLATFORM)
            << ", " << Value;
+        AArch64TargetStreamer::emitAttribute(VendorID, Tag, Value, Override);
         break;
       case ARMBuildAttrs::TAG_PAUTH_SCHEMA:
         OS << "\t." << ARMBuildAttrs::getAttrTag() << "\t"
            << ARMBuildAttrs::getPauthABITagsStr(ARMBuildAttrs::TAG_PAUTH_SCHEMA)
            << ", " << Value;
-        break;
+        AArch64TargetStreamer::emitAttribute(VendorID, Tag, Value, Override);
         break;
       }
     }
     OS << "\n";
   }
 
-  void emitSubsection(unsigned SubsectionName,
+  void emitSubsection(unsigned Subsection,
                       ARMBuildAttrs::SubsectionOptional Optional,
                       ARMBuildAttrs::SubsectionType ParameterType) override {
     // The AArch64 build attributes assembly subsection header format:
     // ".aeabi_subsection name, optional, parameter type"
     // optional: required (0) optional (1)
     // parameter type: uleb128 or ULEB128 (0) ntbs or NTBS (1)
-
     assert((0 == Optional || 1 == Optional) &&
            ARMBuildAttrs::getSubsectionOptionalUnknownError().data());
     assert((0 == ParameterType || 1 == ParameterType) &&
@@ -225,7 +230,7 @@ class AArch64TargetAsmStreamer : public AArch64TargetStreamer {
     StringRef OptionalStr = getOptionalStr(Optional);
     StringRef ParameterStr = getTypeStr(ParameterType);
 
-    switch (SubsectionName) {
+    switch (Subsection) {
     default: {
       assert(0 && ARMBuildAttrs::getSubsectionUnknownError().data());
       break;
@@ -240,6 +245,10 @@ class AArch64TargetAsmStreamer : public AArch64TargetStreamer {
       StringRef SubsectionName = getVendorName(ARMBuildAttrs::AEABI_PAUTHABI);
       OS << "\t" << SubsectionTag << "\t" << SubsectionName << ", "
          << OptionalStr << ", " << ParameterStr;
+      // Keep the data structure consistent with the case of ELF emission
+      // (important for llvm-mc asm parsing)
+      AArch64TargetStreamer::emitSubsection(Subsection, Optional,
+                                            ParameterType);
       break;
     }
     case ARMBuildAttrs::AEABI_FEATURE_AND_BITS: {
@@ -253,6 +262,8 @@ class AArch64TargetAsmStreamer : public AArch64TargetStreamer {
           getVendorName(ARMBuildAttrs::AEABI_FEATURE_AND_BITS);
       OS << "\t" << SubsectionTag << "\t" << SubsectionName << ", "
          << OptionalStr << ", " << ParameterStr;
+      AArch64TargetStreamer::emitSubsection(Subsection, Optional,
+                                            ParameterType);
       break;
     }
     }
@@ -406,84 +417,15 @@ AArch64ELFStreamer &AArch64TargetELFStreamer::getStreamer() {
   return static_cast<AArch64ELFStreamer &>(Streamer);
 }
 
-void AArch64TargetELFStreamer::activateSubsection(StringRef VendorName) {
-  for (MCELFStreamer::AttributeSubSection &SubSection : AttributeSubSections) {
-    if (VendorName == SubSection.VendorName) {
-      SubSection.IsActive = true;
-    } else {
-      SubSection.IsActive = false;
-    }
-  }
-}
-
 void AArch64TargetELFStreamer::emitSubsection(
     unsigned VendorID, ARMBuildAttrs::SubsectionOptional IsOptional,
     ARMBuildAttrs::SubsectionType ParameterType) {
-  StringRef VendorName = ARMBuildAttrs::getVendorName(VendorID);
-
-  // If exists, return.
-  for (MCELFStreamer::AttributeSubSection &SubSection : AttributeSubSections) {
-    if (VendorName == SubSection.VendorName) {
-      // This path might be reached when an assembly directive switches
-      // attribute subsection.
-      activateSubsection(VendorName);
-      return;
-    }
-  }
-  // else, add the subsection
-  MCELFStreamer::AttributeSubSection AttSubSection;
-  AttSubSection.VendorName = VendorName;
-  AttSubSection.IsOptional = IsOptional;
-  AttSubSection.ParameterType = ParameterType;
-  AttributeSubSections.push_back(AttSubSection);
-  activateSubsection(VendorName);
+  AArch64TargetStreamer::emitSubsection(VendorID, IsOptional, ParameterType);
 }
 
 void AArch64TargetELFStreamer::emitAttribute(unsigned VendorID, unsigned Tag,
                                              unsigned Value, bool Override) {
-  StringRef VendorName = ARMBuildAttrs::getVendorName(VendorID);
-
-  if (AttributeSubSections.size() == 0) {
-    assert(0 &&
-           "Can not add AArch64 build attribute: no AArch64 subsection exists");
-    return;
-  }
-
-  for (MCELFStreamer::AttributeSubSection &SubSection : AttributeSubSections) {
-    if (VendorName == SubSection.VendorName) {
-      if (!SubSection.IsActive) {
-        assert(0 &&
-               "Can not add AArch64 build attribute: subsection is not active");
-        return;
-      }
-      for (MCELFStreamer::AttributeItem &Item : SubSection.Content) {
-        if (Item.Tag == Tag) {
-          if (!Override) {
-            if (Item.IntValue != Value) {
-              assert(0 &&
-                     "Can not add AArch64 build attribute: An attribute with "
-                     "the same tag and a different value allready exists");
-              return;
-            }
-          }
-        }
-      }
-      SubSection.Content.push_back(MCELFStreamer::AttributeItem(
-          MCELFStreamer::AttributeItem::NumericAttribute, Tag, Value, ""));
-      return;
-    }
-  }
-  assert(0 && "Can not add AArch64 build attribute: required subsection does "
-              "not exists");
-}
-
-StringRef AArch64TargetELFStreamer::getActiveSubsection() {
-  for (MCELFStreamer::AttributeSubSection &SubSection : AttributeSubSections) {
-    if (SubSection.IsActive) {
-      return SubSection.VendorName;
-    }
-  }
-  return "";
+  AArch64TargetStreamer::emitAttribute(VendorID, Tag, Value, Override);
 }
 
 void AArch64TargetELFStreamer::emitInst(uint32_t Inst) {
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.cpp
index 7bd89c9e29a728..c014ddcab452e8 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.cpp
@@ -151,3 +151,81 @@ llvm::createAArch64ObjectTargetStreamer(MCStreamer &S,
 MCTargetStreamer *llvm::createAArch64NullTargetStreamer(MCStreamer &S) {
   return new AArch64TargetStreamer(S);
 }
+
+void AArch64TargetStreamer::emitSubsection(
+    unsigned VendorID, ARMBuildAttrs::SubsectionOptional IsOptional,
+    ARMBuildAttrs::SubsectionType ParameterType) {
+  StringRef VendorName = ARMBuildAttrs::getVendorName(VendorID);
+
+  // If exists, return.
+  for (MCELFStreamer::AttributeSubSection &SubSection : AttributeSubSections) {
+    if (VendorName == SubSection.VendorName) {
+      activateSubsection(VendorName);
+      return;
+    }
+  }
+  // else, add the subsection
+  MCELFStreamer::AttributeSubSection AttSubSection;
+  AttSubSection.VendorName = VendorName;
+  AttSubSection.IsOptional = IsOptional;
+  AttSubSection.ParameterType = ParameterType;
+  AttributeSubSections.push_back(AttSubSection);
+  activateSubsection(VendorName);
+}
+
+StringRef AArch64TargetStreamer::getActiveSubsection() {
+  for (MCELFStreamer::AttributeSubSection &SubSection : AttributeSubSections) {
+    if (SubSection.IsActive) {
+      return SubSection.VendorName;
+    }
+  }
+  return "";
+}
+
+void AArch64TargetStreamer::emitAttribute(unsigned VendorID, unsigned Tag,
+                                          unsigned Value, bool Override) {
+  StringRef VendorName = ARMBuildAttrs::getVendorName(VendorID);
+
+  if (AttributeSubSections.size() == 0) {
+    assert(0 &&
+           "Can not add AArch64 build attribute: no AArch64 subsection exists");
+    return;
+  }
+
+  for (MCELFStreamer::AttributeSubSection &SubSection : AttributeSubSections) {
+    if (VendorName == SubSection.VendorName) {
+      if (!SubSection.IsActive) {
+        assert(0 &&
+               "Can not add AArch64 build attribute: subsection is not active");
+        return;
+      }
+      for (MCELFStreamer::AttributeItem &Item : SubSection.Content) {
+        if (Item.Tag == Tag) {
+          if (!Override) {
+            if (Item.IntValue != Value) {
+              assert(0 &&
+                     "Can not add AArch64 build attribute: An attribute with "
+                     "the same tag and a different value allready exists");
+              return;
+            }
+          }
+        }
+      }
+      SubSection.Content.push_back(MCELFStreamer::AttributeItem(
+          MCELFStreamer::AttributeItem::NumericAttribute, Tag, Value, ""));
+      return;
+    }
+  }
+  assert(0 && "Can not add AArch64 build attribute: required subsection does "
+              "not exists");
+}
+
+void AArch64TargetStreamer::activateSubsection(StringRef VendorName) {
+  for (MCELFStreamer::AttributeSubSection &SubSection : AttributeSubSections) {
+    if (VendorName == SubSection.VendorName) {
+      SubSection.IsActive = true;
+    } else {
+      SubSection.IsActive = false;
+    }
+  }
+}
\ No newline at end of file
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h
index 6344a26e1d1efe..48bab0bbc99050 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h
@@ -97,11 +97,13 @@ class AArch64TargetStreamer : public MCTargetStreamer {
   /// Build attributes implementation
   virtual void emitSubsection(unsigned VendorID,
                               ARMBuildAttrs::SubsectionOptional IsOptional,
-                              ARMBuildAttrs::SubsectionType ParameterType) {}
+                              ARMBuildAttrs::SubsectionType ParameterType);
   virtual void emitAttribute(unsigned VendorID, unsigned Tag, unsigned Value,
-                             bool Override) {}
-  virtual void activateSubsection(StringRef VendorName) {}
-  virtual StringRef getActiveSubsection() { return ""; }
+                             bool Override);
+  void activateSubsection(StringRef VendorName);
+  StringRef getActiveSubsection();
+
+  SmallVector<MCELFStreamer::AttributeSubSection, 64> AttributeSubSections;
 
 private:
   std::unique_ptr<AssemblerConstantPools> ConstantPools;
@@ -112,7 +114,6 @@ class AArch64TargetELFStreamer : public AArch64TargetStreamer {
   AArch64ELFStreamer &getStreamer();
 
   MCSection *AttributeSection = nullptr;
-  SmallVector<MCELFStreamer::AttributeSubSection, 64> AttributeSubSections;
 
   /// Build attributes implementation
   void emitSubsection(unsigned VendorID,
@@ -120,8 +121,6 @@ class AArch64TargetELFStreamer : public AArch64TargetStreamer {
                       ARMBuildAttrs::SubsectionType ParameterType) override;
   void emitAttribute(unsigned VendorID, unsigned Tag, unsigned Value,
                      bool Override = false) override;
-  void activateSubsection(StringRef VendorName) override;
-  StringRef getActiveSubsection() override;
 
   void emitInst(uint32_t Inst) override;
   void emitDirectiveVariantPCS(MCSymbol *Symbol) override;
diff --git a/llvm/test/MC/AArch64/aarch64-build-attributes-asm-all.s b/llvm/test/MC/AArch64/aarch64-build-attributes-asm-all.s
new file mode 100644
index 00000000000000..30b552ebba1b77
--- /dev/null
+++ b/llvm/test/MC/AArch64/aarch64-build-attributes-asm-all.s
@@ -0,0 +1,27 @@
+// RUN: llvm-mc -triple=aarch64 %s -o - | FileCheck %s --check-prefix=ASM
+// RUN: llvm-mc -triple=aarch64 -filetype=obj %s -o - | llvm-readelf --hex-dump=.ARM.attributes - | FileCheck %s --check-prefix=ELF
+
+// ASM: .text
+// ASM: .aeabi_subsection aeabi_pauthabi, required, uleb128
+// ASM: .aeabi_attribute Tag_PAuth_Platform, 1
+// ASM: .aeabi_attribute Tag_PAuth_Schema, 1
+// ASM: .aeabi_subsection aeabi_feature_and_bits, optional, uleb128
+// ASM: .aeabi_attribute Tag_Feature_BTI, 1
+// ASM: .aeabi_attribute Tag_Feature_PAC, 1
+// ASM: .aeabi_attribute Tag_Feature_GCS, 1
+
+// ELF: Hex dump of section '.ARM.attributes':
+// ELF-NEXT: 0x00000000 41190000 00616561 62695f70 61757468 A....aeabi_pauth
+// ELF-NEXT: 0x00000010 61626900 00000101 02012300 00006165 abi.......#...ae
+// ELF-NEXT: 0x00000020 6162695f 66656174 7572655f 616e645f abi_feature_and_
+// ELF-NEXT: 0x00000030 62697473 00010000 01010102 01
+
+
+.text
+.aeabi_subsection aeabi_pauthabi, required, uleb128
+.aeabi_attribute Tag_PAuth_Platform, 1
+.aeabi_attribute Tag_PAuth_Schema, 1
+.aeabi_subsection aeabi_feature_and_bits, optional, uleb128
+.aeabi_attribute Tag_Feature_BTI, 1
+.aeabi_attribute Tag_Feature_PAC, 1
+.aeabi_attribute Tag_Feature_GCS, 1
\ No newline at end of file
diff --git a/llvm/test/MC/AArch64/aarch64-build-attributes-asm-bti.s b/llvm/test/MC/AArch64/aarch64-build-attributes-asm-bti.s
new file mode 100644
index 00000000000000..4da0b21fcc191b
--- /dev/null
+++ b/llvm/test/MC/AArch64/aarch64-build-attributes-asm-bti.s
@@ -0,0 +1,19 @@
+// RUN: llvm-mc -triple=aarch64 %s -o - | FileCheck %s --check-prefix=ASM
+// RUN: llvm-mc -triple=aarch64 -filetype=obj %s -o - | llvm-readelf --hex-dump=.ARM.attributes - | FileCheck %s --check-prefix=ELF
+
+// ASM: .aeabi_subsection aeabi_feature_and_bits, optional, uleb128
+// ASM: .aeabi_attribute Tag_Feature_BTI, 1
+// ASM: .aeabi_attribute Tag_Feature_PAC, 0
+// ASM: .aeabi_attribute Tag_Feature_GCS, 0
+
+// ELF: Hex dump of section '.ARM.attributes':
+// ELF-NEXT: 0x00000000 41230000 00616561 62695f66 65617475 A#...aeabi_featu
+// ELF-NEXT: 0x00000010 72655f61 6e645f62 69747300 01000001 re_and_bits.....
+// ELF-NEXT: 0x00000020 01000200
+
+
+.text
+.aeabi_subsection aeabi_feature_and_bits, optional, uleb128
+.aeabi_attribute Tag_Feature_BTI, 1
+.aeabi_attribute Tag_Feature_PAC, 0
+.aeabi_attribute Tag_Feature_GCS, 0
\ No newline at end of file
diff --git a/llvm/test/MC/AArch64/aarch64-build-attributes-asm-gcs.s b/llvm/test/MC/AArch64/aarch64-build-attributes-asm-gcs.s
new file mode 100644
index 00000000000000..62789c514dc332
--- /dev/null
+++ b/llvm/test/MC/AArch64/aarch64-build-attributes-asm-gcs.s
@@ -0,0 +1,19 @@
+// RUN: llvm-mc -triple=aarch64 %s -o - | FileCheck %s --check-prefix=ASM
+// RUN: llvm-mc -triple=aarch64 -filetype=obj %s -o - | llvm-readelf --hex-dump=.ARM.attributes - | FileCheck %s --check-prefix=ELF
+
+// ASM: .aeabi_subsection aeabi_feature_and_bits, optional, uleb128
+// ASM: .aeabi_attribute Tag_Feature_BTI, 0
+// ASM: .aeabi_attribute Tag_Feature_PAC, 0
+// ASM: .aeabi_attribute Tag_Feature_GCS, 1
+
+// ELF: Hex dump of section '.ARM.attributes':
+// ELF-NEXT: 0x00000000 41230000 00616561 62695f66 65617475 A#...aeabi_featu
+// ELF-NEXT: 0x00000010 72655f61 6e645f62 69747300 01000000 re_and_bits.....
+// ELF-NEXT: 0x00000020 01000201
+
+
+.text
+.aeabi_subsection aeabi_feature_and_bits, optional, uleb128
+.aeabi_attribute Tag_Feature_BTI, 0
+.aeabi_attribute Tag_Feature_PAC, 0
+.aeabi_attribute Tag_Feature_GCS, 1
\ No newline at end of file
diff --git a/llvm/test/MC/AArch64/aarch64-build-attributes-asm-none.s b/llvm/test/MC/AArch64/aarch64-build-attributes-asm-none.s
new file mode 100644
index 00000000000000..07c89670373de8
--- /dev/null
+++ b/llvm/test/MC/AArch64/aarch64-build-attributes-asm-none.s
@@ -0,0 +1,27 @@
+// RUN: llvm-mc -triple=aarch64 %s -o - | FileCheck %s --check-prefix=ASM
+// RUN: llvm-mc -triple=aarch64 -filetype=obj %s -o - | llvm-readelf --hex-dump=.ARM.attributes - | FileCheck %s --check-prefix=ELF
+
+// ASM: .text
+// ASM: .aeabi_subsection aeabi_pauthabi, required, uleb128
+// ASM: .aeabi_attribute Tag_PAuth_Platform, 0
+// ASM: .aeabi_attribute Tag_PAuth_Schema, 0
+// ASM: .aeabi_subsection aeabi_feature_and_bits, optional, uleb128
+// ASM: .aeabi_attribute Tag_Feature_BTI, 0
+// ASM: .aeabi_attribute Tag_Feature_PAC, 0
+// ASM: .aeabi_attribute Tag_Feature_GCS, 0
+
+// ELF: Hex dump of section '.ARM.attributes':
+// ELF-NEXT: 0x00000000 41190000 00616561 62695f70 61757468 A....aeabi_pauth
+// ELF-NEXT: 0x00000010 61626900 00000100 02002300 00006165 abi.......#...ae
+// ELF-NEXT: 0x00000020 6162695f 66656174 7572655f 616e645f abi_feature_and_
+// ELF-NEXT: 0x00000030 62697473 00010000 00010002 00
+
+
+.text
+.aeabi_subsection aeabi_pauthabi, required, uleb128
+.aeabi_attribute Tag_PAuth_Platform, 0
+.aeabi_attribute Tag_PAuth_Schema, 0
+.aeabi_subsection aeabi_feature_and_bits, optional, uleb128
+.aeabi_attribute Tag_Feature_BTI, 0
+.aeabi_attribute Tag_Feature_PAC, 0
+.aeabi_attribute Tag_Feature_GCS, 0
\ No newline at end of file
diff --git a/llvm/test/MC/AArch64/aarch64-build-attributes-asm-out-of-order.s b/llvm/test/MC/AArch64/aarch64-build-attributes-asm-out-of-order.s
new file mode 100644
index 00000000000000..8a7f681b5f3e76
--- /dev/null
+++ b/llvm/test/MC/AArch64/aarch64-build-attributes-asm-out-of-order.s
@@ -0,0 +1,50 @@
+// RUN: llvm-mc -triple=aarch64 %s -o - | FileCheck %s --check-prefix=ASM
+// RUN: llvm-mc -triple=aarch64 -filetype=obj %s -o - | llvm-readelf --hex-dump=.ARM.attributes - | FileCheck %s --check-prefix=ELF
+
+// ASM: .text
+// ASM: .aeabi_subsection aeabi_pauthabi, required, uleb128
+// ASM: .aeabi_subsection aeabi_feature_and_bits, optional, uleb128
+// ASM: .aeabi_attribute Tag_Feature_BTI, 1
+// ASM: .aeabi_subsection aeabi_feature_and_bits, optional, uleb128
+// ASM: .aeabi_subsection aeabi_pauthabi, required, uleb128
+// ASM: .aeabi_attribute Tag_PAuth_Schema, 1
+// ASM: .aeabi_subsection aeabi_pauthabi, required, uleb128
+// ASM: .aeabi_attribute Tag_PAuth_Platform, 1
+// ASM: .aeabi_subsection aeabi_pauthabi, required, uleb128
+// ASM: .aeabi_subsection aeabi_feature_and_bits, optional, uleb128
+// ASM: .aeabi_attribute Tag_Feature_GCS, 1
+// ASM: .aeabi_subsection aeabi_pauthabi, required, uleb128
+// ASM: .aeabi_subsection aeabi_feature_and_bits, optional, uleb128
+// ASM: .aeabi_attribute Tag_Feature_BTI, 1
+// ASM: .aeabi_subsection aeabi_feature_and_bits, optional, uleb128
+// ASM: .aeabi_attribute Tag_Feature_PAC, 1
+// ASM: .aeabi_subsection aeabi_pauthabi, required, uleb128
+// ASM: .aeabi_attribute Tag_PAuth_Schema, 1
+
+// ELF: Hex dump of section '.ARM.attributes':
+// ELF-NEXT: 0x00000000 411b0000 00616561 62695f70 61757468 A....aeabi_pauth
+// ELF-NEXT: 0x00000010 61626900 00000201 01010201 25000000 abi.........%...
+// ELF-NEXT: 0x00000020 61656162 695f6665 61747572 655f616e aeabi_feature_an
+// ELF-NEXT: 0x00000030 645f6269 74730001 00000102 01000101 d_bits..........
+// ELF-NEXT: 0x00000040 01
+
+
+.text
+.aeabi_subsection aeabi_pauthabi, required, uleb128
+.aeabi_subsection aeabi_feature_and_bits, optional, uleb128
+.aeabi_attribute Tag_Feature_BTI, 1
+.aeabi_subsection aeabi_feature_and_bits, optional, uleb128
+.aeabi_subsection aeabi_pauthabi, required, uleb128
+.aeabi_attribute Tag_PAuth_Schema, 1
+.aeabi_subsection aeabi_pauthabi, required, uleb128
+.aeabi_attribute Tag_PAuth_Platform, 1
+.aeabi_subsection aeabi_pauthabi, required, uleb128
+.aeabi_subsection aeabi_feature_and_bits, optional, uleb128
+.aeabi_attribute Tag_Feature_GCS, 1
+.aeabi_subsection aeabi_pauthabi, required, uleb128
+.aeabi_subsection aeabi_feature_and_bits, optional, uleb128
+.aeabi_attribute Tag_Feature_BTI, 1
+.aeabi_subsection aeabi_feature_and_bits, optional, uleb128
+.aeabi_attribute Tag_Feature_PAC, 1
+.aeabi_subsection aeabi_pauthabi, required, uleb128
+.aeabi_attribute Tag_PAuth_Schema, 1
\ No newline at end of file
diff --git a/llvm/test/MC/AArch64/aarch64-build-attributes-asm-pac.s b/llvm/test/MC/AArch64/aarch64-build-attributes-asm-pac.s
new file mode 100644
index 00000000000000..b67904b9a08fc9
--- /dev/null
+++ b/llvm/test/MC/AArch64/aarch64-build-attributes-asm-pac.s
@@ -0,0 +1,19 @@
+// RUN: llvm-mc -triple=aarch64 %s -o - | FileCheck %s --check-prefix=ASM
+// RUN: llvm-mc -triple=aarch64 -filetype=obj %s -o - | llvm-readelf --hex-dump=.ARM.attributes - | FileCheck %s --check-prefix=ELF
+
+// ASM: .aeabi_subsection aeabi_feature_and_bits, optional, uleb128
+// ASM: .aeabi_attribute Tag_Feature_BTI, 0
+// ASM: .aeabi_attribute Tag_Feature_PAC, 1
+// ASM: .aeabi_attribute Tag_Feature_GCS, 0
+
+// ELF: Hex dump of section '.ARM.attributes':
+// ELF-NEXT: 0x00000000 41230000 00616561 62695f66 65617475 A#...aeabi_featu
+// ELF-NEXT: 0x00000010 72655f61 6e645f62 69747300 01000000 re_and_bits.....
+// ELF-NEXT: 0x00000020 01010200
+
+
+.text
+.aeabi_subsection aeabi_feature_and_bits, optional, uleb128
+.aeabi_attribute Tag_Feature_BTI, 0
+.aeabi_attribute Tag_Feature_PAC, 1
+.aeabi_attribute Tag_Feature_GCS, 0
\ No newline at end of file



More information about the llvm-commits mailing list