diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h index 5356843f8ecf1..7468886bd737a 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 94d14088d0f5d..5a1cdd9e96cad 100644 --- a/llvm/include/llvm/MC/MCELFStreamer.h +++ b/llvm/include/llvm/MC/MCELFStreamer.h @@ -96,7 +96,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, @@ -105,6 +105,17 @@ 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; + StringRef VendorName; + unsigned IsOptional; + unsigned ParameterType; + SmallVector Content; }; // Attributes that are added and managed entirely by target. @@ -119,13 +130,23 @@ class MCELFStreamer : public MCObjectStreamer { unsigned Type, MCSection *&AttributeSection) { createAttributesSection(Vendor, Section, Type, AttributeSection, Contents); } + void + emitAttributesSection(MCSection *&AttributeSection, const Twine &Section, + unsigned Type, + SmallVector &SubSectionVec) { + createAttributesWithSubsection(AttributeSection, Section, Type, + SubSectionVec); + } private: AttributeItem *getAttributeItem(unsigned Attribute); - size_t calculateContentSize(SmallVector &AttrsVec); + size_t calculateContentSize(SmallVector &AttrsVec) const; void createAttributesSection(StringRef Vendor, const Twine &Section, unsigned Type, MCSection *&AttributeSection, SmallVector &AttrsVec); + void createAttributesWithSubsection( + MCSection *&AttributeSection, const Twine &Section, unsigned Type, + SmallVector &SubSectionVec); // GNU attributes that will get emitted at the end of the asm file. SmallVector GNUAttributes; diff --git a/llvm/include/llvm/Support/AArch64BuildAttributes.h b/llvm/include/llvm/Support/AArch64BuildAttributes.h new file mode 100644 index 0000000000000..ea293b72f9bb1 --- /dev/null +++ b/llvm/include/llvm/Support/AArch64BuildAttributes.h @@ -0,0 +1,75 @@ +//===-- AArch64BuildAttributes.h - AARch64 Build Attributes -----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file contains enumerations and support routines for AArch64 build +// attributes as defined in Build Attributes for the AArch64 document. +// +// Build Attributes for the ArmĀ® 64-bit Architecture (AArch64) 2024Q1 +// +// https://github.com/ARM-software/abi-aa/pull/230 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_AARCH64BUILDATTRIBUTES_H +#define LLVM_SUPPORT_AARCH64BUILDATTRIBUTES_H + +#include "llvm/ADT/StringRef.h" + +namespace llvm { + +namespace AArch64BuildAttributes { + +/// AArch64 build attributes vendors IDs (a.k.a subsection name) +enum VendorID : unsigned { + AEABI_FEATURE_AND_BITS = 0, + AEABI_PAUTHABI = 1, + VENDOR_UNKNOWN = 404 // Treated as a private subsection name +}; +StringRef getVendorName(unsigned const Vendor); +VendorID getVendorID(StringRef const Vendor); + +enum SubsectionOptional : unsigned { + REQUIRED = 0, + OPTIONAL = 1, + OPTIONAL_NOT_FOUND = 404 +}; +StringRef getOptionalStr(unsigned Optional); +SubsectionOptional getOptionalID(StringRef Optional); +StringRef getSubsectionOptionalUnknownError(); + +enum SubsectionType : unsigned { ULEB128 = 0, NTBS = 1, TYPE_NOT_FOUND = 404 }; +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 +}; +StringRef getPauthABITagsStr(unsigned PauthABITag); +PauthABITags getPauthABITagsID(StringRef PauthABITag); + +enum FeatureAndBitsTags : unsigned { + TAG_FEATURE_BTI = 0, + TAG_FEATURE_PAC = 1, + TAG_FEATURE_GCS = 2, + FEATURE_AND_BITS_TAG_NOT_FOUND = 404 +}; +StringRef getFeatureAndBitsTagsStr(unsigned FeatureAndBitsTag); +FeatureAndBitsTags getFeatureAndBitsTagsID(StringRef FeatureAndBitsTag); + +enum FeatureAndBitsFlag : unsigned { + Feature_BTI_Flag = 1 << 0, + Feature_PAC_Flag = 1 << 1, + Feature_GCS_Flag = 1 << 2 +}; +} // namespace AArch64BuildAttributes +} // namespace llvm + +#endif // LLVM_SUPPORT_AARCH64BUILDATTRIBUTES_H \ No newline at end of file diff --git a/llvm/lib/MC/MCELFStreamer.cpp b/llvm/lib/MC/MCELFStreamer.cpp index 64ab2b2ab58f5..282c82198507d 100644 --- a/llvm/lib/MC/MCELFStreamer.cpp +++ b/llvm/lib/MC/MCELFStreamer.cpp @@ -696,8 +696,8 @@ MCELFStreamer::getAttributeItem(unsigned Attribute) { return nullptr; } -size_t -MCELFStreamer::calculateContentSize(SmallVector &AttrsVec) { +size_t MCELFStreamer::calculateContentSize( + SmallVector &AttrsVec) const { size_t Result = 0; for (const AttributeItem &Item : AttrsVec) { switch (Item.Type) { @@ -783,6 +783,67 @@ void MCELFStreamer::createAttributesSection( AttrsVec.clear(); } +void MCELFStreamer::createAttributesWithSubsection( + MCSection *&AttributeSection, const Twine &Section, unsigned Type, + SmallVector &SubSectionVec) { + // + // [ NTBS: vendor-name + // + // ]* + // vendor-data expends to: + // * + if (0 == SubSectionVec.size()) { + 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.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.VendorName); + emitInt8(0); // '\0' + emitInt8(SubSection.IsOptional); + emitInt8(SubSection.ParameterType); + + for (AttributeItem &Item : SubSection.Content) { + emitULEB128IntValue(Item.Tag); + switch (Item.Type) { + default: + assert(0 && "Invalid attribute type"); + break; + 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 &&MAB, std::unique_ptr &&OW, diff --git a/llvm/lib/Support/AArch64BuildAttributes.cpp b/llvm/lib/Support/AArch64BuildAttributes.cpp new file mode 100644 index 0000000000000..ada34eb3f927d --- /dev/null +++ b/llvm/lib/Support/AArch64BuildAttributes.cpp @@ -0,0 +1,117 @@ +//===-- AArch64BuildAttributes.cpp - AArch64 Build Attributes -------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/AArch64BuildAttributes.h" +#include "llvm/ADT/StringSwitch.h" + +namespace llvm { +namespace AArch64BuildAttributes { + +StringRef getVendorName(unsigned Vendor) { + switch (Vendor) { + case AEABI_FEATURE_AND_BITS: + return "aeabi_feature_and_bits"; + case AEABI_PAUTHABI: + return "aeabi_pauthabi"; + case VENDOR_UNKNOWN: + return ""; + default: + assert(0 && "Vendor name error"); + return ""; + } +} +VendorID getVendorID(StringRef Vendor) { + return StringSwitch(Vendor) + .Case("aeabi_feature_and_bits", AEABI_FEATURE_AND_BITS) + .Case("aeabi_pauthabi", AEABI_PAUTHABI) + .Default(VENDOR_UNKNOWN); +} + +StringRef getOptionalStr(unsigned Optional) { + switch (Optional) { + case REQUIRED: + return "required"; + case OPTIONAL: + return "optional"; + case OPTIONAL_NOT_FOUND: + default: + return ""; + } +} +SubsectionOptional getOptionalID(StringRef Optional) { + return StringSwitch(Optional) + .Case("required", REQUIRED) + .Case("optional", OPTIONAL) + .Default(OPTIONAL_NOT_FOUND); +} +StringRef getSubsectionOptionalUnknownError() { + return "unknown AArch64 build attributes optionality, expected " + "required|optional"; +} + +StringRef getTypeStr(unsigned Type) { + switch (Type) { + case ULEB128: + return "uleb128"; + case NTBS: + return "ntbs"; + case TYPE_NOT_FOUND: + default: + return ""; + } +} +SubsectionType getTypeID(StringRef Type) { + return StringSwitch(Type) + .Cases("uleb128", "ULEB128", ULEB128) + .Cases("ntbs", "NTBS", NTBS) + .Default(TYPE_NOT_FOUND); +} +StringRef getSubsectionTypeUnknownError() { + return "unknown AArch64 build attributes type, expected uleb128|ntbs"; +} + +StringRef getPauthABITagsStr(unsigned PauthABITag) { + switch (PauthABITag) { + case TAG_PAUTH_PLATFORM: + return "Tag_PAuth_Platform"; + case TAG_PAUTH_SCHEMA: + return "Tag_PAuth_Schema"; + case PAUTHABI_TAG_NOT_FOUND: + default: + return ""; + } +} +PauthABITags getPauthABITagsID(StringRef PauthABITag) { + return StringSwitch(PauthABITag) + .Case("Tag_PAuth_Platform", TAG_PAUTH_PLATFORM) + .Case("Tag_PAuth_Schema", TAG_PAUTH_SCHEMA) + .Default(PAUTHABI_TAG_NOT_FOUND); +} + +StringRef getFeatureAndBitsTagsStr(unsigned FeatureAndBitsTag) { + switch (FeatureAndBitsTag) { + case TAG_FEATURE_BTI: + return "Tag_Feature_BTI"; + case TAG_FEATURE_PAC: + return "Tag_Feature_PAC"; + case TAG_FEATURE_GCS: + return "Tag_Feature_GCS"; + case FEATURE_AND_BITS_TAG_NOT_FOUND: + default: + return ""; + } +} +FeatureAndBitsTags getFeatureAndBitsTagsID(StringRef FeatureAndBitsTag) { + return StringSwitch(FeatureAndBitsTag) + .Case("Tag_Feature_BTI", TAG_FEATURE_BTI) + .Case("Tag_Feature_PAC", TAG_FEATURE_PAC) + .Case("Tag_Feature_GCS", TAG_FEATURE_GCS) + .Default(FEATURE_AND_BITS_TAG_NOT_FOUND); +} +} // namespace AArch64BuildAttributes +} // namespace llvm diff --git a/llvm/lib/Support/CMakeLists.txt b/llvm/lib/Support/CMakeLists.txt index 2ecaea4b02bf6..122240c27b1fc 100644 --- a/llvm/lib/Support/CMakeLists.txt +++ b/llvm/lib/Support/CMakeLists.txt @@ -144,6 +144,7 @@ add_llvm_component_library(LLVMSupport APInt.cpp APSInt.cpp ARMBuildAttrs.cpp + AArch64BuildAttributes.cpp ARMAttributeParser.cpp ARMWinEH.cpp Allocator.cpp diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp index 69d07f27fa8e1..b1c586c5daf07 100644 --- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp +++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp @@ -200,6 +200,10 @@ 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,53 @@ 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(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( - 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 |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_BTI_Flag; + GNUFlags |= ELF::GNU_PROPERTY_AARCH64_FEATURE_1_BTI; + } + } if (const auto *GCS = mdconst::extract_or_null( - 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 |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_GCS_Flag; + GNUFlags |= ELF::GNU_PROPERTY_AARCH64_FEATURE_1_GCS; + } + } if (const auto *Sign = mdconst::extract_or_null( - 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 |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_PAC_Flag; + GNUFlags |= ELF::GNU_PROPERTY_AARCH64_FEATURE_1_PAC; + } + } uint64_t PAuthABIPlatform = -1; if (const auto *PAP = mdconst::extract_or_null( - 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( - 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(OutStreamer->getTargetStreamer()); - TS->emitNoteSection(Flags, PAuthABIPlatform, PAuthABIVersion); + TS->emitNoteSection(GNUFlags, PAuthABIPlatform, PAuthABIVersion); } void AArch64AsmPrinter::emitFunctionHeaderComment() { @@ -434,6 +455,58 @@ 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 = (uint64_t(-1) == PAuthABIPlatform) ? 0 : PAuthABIPlatform; + PAuthABIVersion = (uint64_t(-1) == PAuthABIVersion) ? 0 : PAuthABIVersion; + + if (PAuthABIPlatform || PAuthABIVersion) { + TS->emitAtributesSubsection( + AArch64BuildAttributes::getVendorName( + AArch64BuildAttributes::AEABI_PAUTHABI), + AArch64BuildAttributes::SubsectionOptional::REQUIRED, + AArch64BuildAttributes::SubsectionType::ULEB128); + TS->emitAttribute(AArch64BuildAttributes::getVendorName( + AArch64BuildAttributes::AEABI_PAUTHABI), + AArch64BuildAttributes::TAG_PAUTH_PLATFORM, + PAuthABIPlatform, "", false); + TS->emitAttribute(AArch64BuildAttributes::getVendorName( + AArch64BuildAttributes::AEABI_PAUTHABI), + AArch64BuildAttributes::TAG_PAUTH_SCHEMA, PAuthABIVersion, + "", false); + } + + unsigned BTIValue = + (Flags & AArch64BuildAttributes::Feature_BTI_Flag) ? 1 : 0; + unsigned PACValue = + (Flags & AArch64BuildAttributes::Feature_PAC_Flag) ? 1 : 0; + unsigned GCSValue = + (Flags & AArch64BuildAttributes::Feature_GCS_Flag) ? 1 : 0; + + if (BTIValue || PACValue || GCSValue) { + TS->emitAtributesSubsection( + AArch64BuildAttributes::getVendorName( + AArch64BuildAttributes::AEABI_FEATURE_AND_BITS), + AArch64BuildAttributes::SubsectionOptional::OPTIONAL, + AArch64BuildAttributes::SubsectionType::ULEB128); + TS->emitAttribute(AArch64BuildAttributes::getVendorName( + AArch64BuildAttributes::AEABI_FEATURE_AND_BITS), + AArch64BuildAttributes::TAG_FEATURE_BTI, BTIValue, "", + false); + TS->emitAttribute(AArch64BuildAttributes::getVendorName( + AArch64BuildAttributes::AEABI_FEATURE_AND_BITS), + AArch64BuildAttributes::TAG_FEATURE_PAC, PACValue, "", + false); + TS->emitAttribute(AArch64BuildAttributes::getVendorName( + AArch64BuildAttributes::AEABI_FEATURE_AND_BITS), + AArch64BuildAttributes::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/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp index 93c85ba62f90e..4a47f2cde6d66 100644 --- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -42,7 +42,7 @@ #include "llvm/MC/MCTargetOptions.h" #include "llvm/MC/MCValue.h" #include "llvm/MC/TargetRegistry.h" -#include "llvm/Support/Casting.h" +#include "llvm/Support/AArch64BuildAttributes.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" @@ -228,6 +228,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 &Loc); @@ -6975,6 +6977,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(); @@ -7070,6 +7073,13 @@ bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) { parseDirectiveSEHSaveAnyReg(Loc, true, true); else return true; + } else if (IsELF) { + if (IDVal == ".aeabi_subsection") + parseDirectiveAeabiSubSectionHeader(Loc); + else if (IDVal == ".aeabi_attribute") + parseDirectiveAeabiAArch64Attr(Loc); + else + return true; } else return true; return false; @@ -7806,6 +7816,265 @@ 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; + AArch64BuildAttributes::VendorID SubsectionNameID; + if (Parser.getTok().is(AsmToken::Identifier)) { + SubsectionName = Parser.getTok().getIdentifier(); + SubsectionNameID = AArch64BuildAttributes::getVendorID(SubsectionName); + } else { + Error(Parser.getTok().getLoc(), "subsection name 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()) { + return true; + } + + std::unique_ptr SubsectionExists = + getTargetStreamer().getAtributesSubsectionByName(SubsectionName); + + // Consume the first parameter (optionality parameter) + AArch64BuildAttributes::SubsectionOptional IsOptional; + // options: optional/required + if (Parser.getTok().is(AsmToken::Identifier)) { + StringRef Optionality = Parser.getTok().getIdentifier(); + IsOptional = AArch64BuildAttributes::getOptionalID(Optionality); + if (AArch64BuildAttributes::OPTIONAL_NOT_FOUND == IsOptional) { + Error(Parser.getTok().getLoc(), + AArch64BuildAttributes::getSubsectionOptionalUnknownError() + ": " + + Optionality); + return true; + } + if (SubsectionExists) { + if (IsOptional != SubsectionExists->IsOptional) { + Error(Parser.getTok().getLoc(), + "optionality mismatch! subsection '" + SubsectionName + + "' already exists with optionality defined as '" + + AArch64BuildAttributes::getOptionalStr( + SubsectionExists->IsOptional) + + "' and not '" + + AArch64BuildAttributes::getOptionalStr(IsOptional) + "'"); + return true; + } + } + } else { + Error(Parser.getTok().getLoc(), + "optionality parameter not found, expected required|optional"); + return true; + } + // Check for possible IsOptional unaccepted values for known subsections + if (AArch64BuildAttributes::AEABI_FEATURE_AND_BITS == SubsectionNameID) { + if (AArch64BuildAttributes::REQUIRED == IsOptional) { + Error(Parser.getTok().getLoc(), + "aeabi_feature_and_bits must be marked as optional"); + return true; + } + } + if (AArch64BuildAttributes::AEABI_PAUTHABI == SubsectionNameID) { + if (AArch64BuildAttributes::OPTIONAL == IsOptional) { + Error(Parser.getTok().getLoc(), + "aeabi_pauthabi must be marked as required"); + return true; + } + } + Parser.Lex(); + // consume a comma + if (Parser.parseComma()) { + return true; + } + + // Consume the second parameter (type parameter) + AArch64BuildAttributes::SubsectionType Type; + if (Parser.getTok().is(AsmToken::Identifier)) { + StringRef Name = Parser.getTok().getIdentifier(); + Type = AArch64BuildAttributes::getTypeID(Name); + if (AArch64BuildAttributes::TYPE_NOT_FOUND == Type) { + Error(Parser.getTok().getLoc(), + AArch64BuildAttributes::getSubsectionTypeUnknownError() + ": " + + Name); + return true; + } + if (SubsectionExists) { + if (Type != SubsectionExists->ParameterType) { + Error(Parser.getTok().getLoc(), + "type mismatch! subsection '" + SubsectionName + + "' already exists with type defined as '" + + AArch64BuildAttributes::getTypeStr( + SubsectionExists->ParameterType) + + "' and not '" + AArch64BuildAttributes::getTypeStr(Type) + + "'"); + return true; + } + } + } else { + Error(Parser.getTok().getLoc(), + "type parameter not found, expected uleb128|ntbs"); + return true; + } + // Check for possible unaccepted 'type' values for known subsections + if (AArch64BuildAttributes::AEABI_FEATURE_AND_BITS == SubsectionNameID || + AArch64BuildAttributes::AEABI_PAUTHABI == SubsectionNameID) { + if (AArch64BuildAttributes::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().emitAtributesSubsection(SubsectionName, IsOptional, Type); + + return false; +} + +bool AArch64AsmParser::parseDirectiveAeabiAArch64Attr(SMLoc L) { + // Expecting 2 Tokens: after '.aeabi_attribute', e.g.: + // .aeabi_attribute (1)Tag_Feature_BTI, (2)[uleb128|ntbs] + // separated by a comma. + MCAsmParser &Parser = getParser(); + + std::unique_ptr ActiveSubsection = + getTargetStreamer().getActiveAtributesSubsection(); + if (nullptr == ActiveSubsection) { + Error(Parser.getTok().getLoc(), + "no active subsection, build attribute can not be added"); + return true; + } + StringRef ActiveSubsectionName = ActiveSubsection->VendorName; + unsigned ActiveSubsectionType = ActiveSubsection->ParameterType; + + unsigned ActiveSubsectionID = AArch64BuildAttributes::VENDOR_UNKNOWN; + if (AArch64BuildAttributes::getVendorName( + AArch64BuildAttributes::AEABI_PAUTHABI) == ActiveSubsectionName) + ActiveSubsectionID = AArch64BuildAttributes::AEABI_PAUTHABI; + if (AArch64BuildAttributes::getVendorName( + AArch64BuildAttributes::AEABI_FEATURE_AND_BITS) == + ActiveSubsectionName) + ActiveSubsectionID = AArch64BuildAttributes::AEABI_FEATURE_AND_BITS; + + StringRef TagStr = ""; + unsigned Tag; + if (Parser.getTok().is(AsmToken::Identifier)) { + TagStr = Parser.getTok().getIdentifier(); + switch (ActiveSubsectionID) { + default: + assert(0 && "Subsection name error"); + break; + case AArch64BuildAttributes::VENDOR_UNKNOWN: + // Private subsection, accept any tag. + break; + case AArch64BuildAttributes::AEABI_PAUTHABI: + Tag = AArch64BuildAttributes::getPauthABITagsID(TagStr); + if (AArch64BuildAttributes::PAUTHABI_TAG_NOT_FOUND == Tag) { + Error(Parser.getTok().getLoc(), "unknown AArch64 build attribute '" + + TagStr + "' for subsection '" + + ActiveSubsectionName + "'"); + return true; + } + break; + case AArch64BuildAttributes::AEABI_FEATURE_AND_BITS: + Tag = AArch64BuildAttributes::getFeatureAndBitsTagsID(TagStr); + if (AArch64BuildAttributes::FEATURE_AND_BITS_TAG_NOT_FOUND == Tag) { + Error(Parser.getTok().getLoc(), "unknown AArch64 build attribute '" + + TagStr + "' for subsection '" + + ActiveSubsectionName + "'"); + return true; + } + break; + } + } 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()) { + return true; + } + + // Consume the second parameter (attribute value) + unsigned ValueInt = unsigned(-1); + std::string ValueStr = ""; + if (Parser.getTok().is(AsmToken::Integer)) { + if (AArch64BuildAttributes::NTBS == ActiveSubsectionType) { + Error( + Parser.getTok().getLoc(), + "active subsection type is NTBS (string), found ULEB128 (unsigned)"); + return true; + } + ValueInt = getTok().getIntVal(); + } else if (Parser.getTok().is(AsmToken::Identifier)) { + if (AArch64BuildAttributes::ULEB128 == ActiveSubsectionType) { + Error( + Parser.getTok().getLoc(), + "active subsection type is ULEB128 (unsigned), found NTBS (string)"); + return true; + } + ValueStr = Parser.getTok().getIdentifier(); + } else if (Parser.getTok().is(AsmToken::String)) { + if (AArch64BuildAttributes::ULEB128 == ActiveSubsectionType) { + Error( + Parser.getTok().getLoc(), + "active subsection type is ULEB128 (unsigned), found NTBS (string)"); + return true; + } + ValueStr = Parser.getTok().getString(); + } else { + Error(Parser.getTok().getLoc(), "AArch64 build attributes value not found"); + return true; + } + // Check for possible unaccepted values for known tags (AEABI_PAUTHABI, + // AEABI_FEATURE_AND_BITS) + if (!(ActiveSubsectionID == AArch64BuildAttributes::VENDOR_UNKNOWN) && + TagStr != "") { // TagStr was a recognized string + if (0 != ValueInt && 1 != ValueInt) { + Error(Parser.getTok().getLoc(), + "unknown AArch64 build attributes Value for Tag '" + TagStr + + "' options are 0|1"); + 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 tag and value " + "attribute directive"); + return true; + } + + if (unsigned(-1) != ValueInt) { + getTargetStreamer().emitAttribute(ActiveSubsectionName, Tag, ValueInt, "", + false); + } + + if ("" != ValueStr) { + getTargetStreamer().emitAttribute(ActiveSubsectionName, Tag, unsigned(-1), + ValueStr, 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 5bae846824548..9f7a60074daeb 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/AArch64BuildAttributes.h" #include "llvm/Support/Casting.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/raw_ostream.h" @@ -45,6 +46,7 @@ class AArch64ELFStreamer; class AArch64TargetAsmStreamer : public AArch64TargetStreamer { formatted_raw_ostream &OS; + std::string VendorTag; void emitInst(uint32_t Inst) override; @@ -148,13 +150,137 @@ class AArch64TargetAsmStreamer : public AArch64TargetStreamer { OS << "\t.seh_save_any_reg_px\tq" << Reg << ", " << Offset << "\n"; } + void emitAttribute(StringRef VendorName, unsigned Tag, unsigned Value, + std::string String, bool Override) override { + + // AArch64 build attributes for assembly attribute form: + // .aeabi_attribute tag, value + if (unsigned(-1) == Value && "" == String) { + assert(0 && "Arguments error"); + return; + } + + unsigned VendorID = AArch64BuildAttributes::getVendorID(VendorName); + + switch (VendorID) { + default: + assert(0 && "Subsection name error"); + break; + case AArch64BuildAttributes::VENDOR_UNKNOWN: + if (unsigned(-1) != Value) { + OS << "\t.aeabi_attribute" << "\t" << Tag << ", " << Value; + AArch64TargetStreamer::emitAttribute(VendorName, Tag, Value, "", + Override); + } + if ("" != String) { + OS << "\t.aeabi_attribute" << "\t" << Tag << ", " << String; + AArch64TargetStreamer::emitAttribute(VendorName, Tag, unsigned(-1), + String, Override); + } + break; + // Note: AEABI_FEATURE_AND_BITS takes only unsigned values + case AArch64BuildAttributes::AEABI_FEATURE_AND_BITS: + switch (Tag) { + default: // allow emitting any attribute by number + OS << "\t.aeabi_attribute" << "\t" << Tag << ", " << Value; + // Keep the data structure consistent with the case of ELF emission + // (important for llvm-mc asm parsing) + AArch64TargetStreamer::emitAttribute(VendorName, Tag, Value, "", + Override); + break; + case AArch64BuildAttributes::TAG_FEATURE_BTI: + case AArch64BuildAttributes::TAG_FEATURE_GCS: + case AArch64BuildAttributes::TAG_FEATURE_PAC: + OS << "\t.aeabi_attribute" << "\t" + << AArch64BuildAttributes::getFeatureAndBitsTagsStr(Tag) << ", " + << Value; + AArch64TargetStreamer::emitAttribute(VendorName, Tag, Value, "", + Override); + break; + } + break; + // Note: AEABI_PAUTHABI takes only unsigned values + case AArch64BuildAttributes::AEABI_PAUTHABI: + switch (Tag) { + default: // allow emitting any attribute by number + OS << "\t.aeabi_attribute" << "\t" << Tag << ", " << Value; + // Keep the data structure consistent with the case of ELF emission + // (important for llvm-mc asm parsing) + AArch64TargetStreamer::emitAttribute(VendorName, Tag, Value, "", + Override); + break; + case AArch64BuildAttributes::TAG_PAUTH_PLATFORM: + case AArch64BuildAttributes::TAG_PAUTH_SCHEMA: + OS << "\t.aeabi_attribute" << "\t" + << AArch64BuildAttributes::getPauthABITagsStr(Tag) << ", " << Value; + AArch64TargetStreamer::emitAttribute(VendorName, Tag, Value, "", + Override); + break; + } + break; + } + OS << "\n"; + } + + void emitAtributesSubsection( + StringRef SubsectionName, + AArch64BuildAttributes::SubsectionOptional Optional, + AArch64BuildAttributes::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) + unsigned SubsectionID = AArch64BuildAttributes::getVendorID(SubsectionName); + + assert((0 == Optional || 1 == Optional) && + AArch64BuildAttributes::getSubsectionOptionalUnknownError().data()); + assert((0 == ParameterType || 1 == ParameterType) && + AArch64BuildAttributes::getSubsectionTypeUnknownError().data()); + + std::string SubsectionTag = ".aeabi_subsection"; + StringRef OptionalStr = getOptionalStr(Optional); + StringRef ParameterStr = getTypeStr(ParameterType); + + switch (SubsectionID) { + default: { + // Treated as a private subsection + break; + } + case AArch64BuildAttributes::AEABI_PAUTHABI: { + assert(AArch64BuildAttributes::REQUIRED == Optional && + "subsection .aeabi-pauthabi should be marked as " + "required and not as optional"); + assert(AArch64BuildAttributes::ULEB128 == ParameterType && + "subsection .aeabi-pauthabi should be " + "marked as uleb128 and not as ntbs"); + break; + } + case AArch64BuildAttributes::AEABI_FEATURE_AND_BITS: { + assert(AArch64BuildAttributes::OPTIONAL == Optional && + "subsection .aeabi_feature_and_bits should be " + "marked as optional and not as required"); + assert(AArch64BuildAttributes::ULEB128 == ParameterType && + "subsection .aeabi_feature_and_bits should " + "be marked as uleb128 and not as ntbs"); + break; + } + } + 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::emitAtributesSubsection(SubsectionName, Optional, + ParameterType); + 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) {} void AArch64TargetAsmStreamer::emitInst(uint32_t Inst) { OS << "\t.inst\t0x" << Twine::utohexstr(Inst) << "\n"; @@ -294,6 +420,23 @@ AArch64ELFStreamer &AArch64TargetELFStreamer::getStreamer() { return static_cast(Streamer); } +void AArch64TargetELFStreamer::emitAtributesSubsection( + StringRef VendorName, AArch64BuildAttributes::SubsectionOptional IsOptional, + AArch64BuildAttributes::SubsectionType ParameterType) { + AArch64TargetStreamer::emitAtributesSubsection(VendorName, IsOptional, + ParameterType); +} + +void AArch64TargetELFStreamer::emitAttribute(StringRef VendorName, unsigned Tag, + unsigned Value, std::string String, + bool Override) { + if (unsigned(-1) != Value) + AArch64TargetStreamer::emitAttribute(VendorName, Tag, Value, "", Override); + if ("" != String) + AArch64TargetStreamer::emitAttribute(VendorName, Tag, unsigned(-1), String, + Override); +} + void AArch64TargetELFStreamer::emitInst(uint32_t Inst) { getStreamer().emitInst(Inst); } @@ -309,6 +452,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.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.cpp index 7bd89c9e29a72..74ffe5f97f1b6 100644 --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.cpp +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.cpp @@ -151,3 +151,107 @@ llvm::createAArch64ObjectTargetStreamer(MCStreamer &S, MCTargetStreamer *llvm::createAArch64NullTargetStreamer(MCStreamer &S) { return new AArch64TargetStreamer(S); } + +void AArch64TargetStreamer::emitAtributesSubsection( + StringRef VendorName, AArch64BuildAttributes::SubsectionOptional IsOptional, + AArch64BuildAttributes::SubsectionType ParameterType) { + + // If exists, return. + for (MCELFStreamer::AttributeSubSection &SubSection : AttributeSubSections) { + if (VendorName == SubSection.VendorName) { + activateAtributesSubsection(VendorName); + return; + } + } + // else, add the subsection + MCELFStreamer::AttributeSubSection AttSubSection; + AttSubSection.VendorName = VendorName; + AttSubSection.IsOptional = IsOptional; + AttSubSection.ParameterType = ParameterType; + AttributeSubSections.push_back(AttSubSection); + activateAtributesSubsection(VendorName); +} + +std::unique_ptr +AArch64TargetStreamer::getActiveAtributesSubsection() { + for (MCELFStreamer::AttributeSubSection &SubSection : AttributeSubSections) { + if (SubSection.IsActive) { + return std::make_unique(SubSection); + } + } + return nullptr; +} + +std::unique_ptr +AArch64TargetStreamer::getAtributesSubsectionByName(StringRef Name) { + for (MCELFStreamer::AttributeSubSection &SubSection : AttributeSubSections) { + if (Name == SubSection.VendorName) { + return std::make_unique(SubSection); + } + } + return nullptr; +} + +void AArch64TargetStreamer::emitAttribute(StringRef VendorName, unsigned Tag, + unsigned Value, std::string String, + bool Override) { + + if (unsigned(-1) == Value && "" == String) { + assert(0 && "Arguments error"); + return; + } + 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 ((unsigned(-1) != Value && Item.IntValue != Value) || + ("" != String && Item.StringValue != String)) { + assert(0 && + "Can not add AArch64 build attribute: An attribute with " + "the same tag and a different value already exists"); + return; + } else { + // Case Item.IntValue == Value, no need to emit twice + assert(0 && + "AArch64 build attribute: An attribute with the same tag " + "and a same value already exists"); + return; + } + } + } + } + if (unsigned(-1) != Value) + SubSection.Content.push_back(MCELFStreamer::AttributeItem( + MCELFStreamer::AttributeItem::NumericAttribute, Tag, Value, "")); + if ("" != String) + SubSection.Content.push_back(MCELFStreamer::AttributeItem( + MCELFStreamer::AttributeItem::TextAttribute, Tag, unsigned(-1), + String)); + return; + } + } + assert(0 && "Can not add AArch64 build attribute: required subsection does " + "not exist"); +} + +void AArch64TargetStreamer::activateAtributesSubsection(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 1c0f5d848c00c..b2b9afe867073 100644 --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h @@ -10,7 +10,12 @@ #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 "llvm/MC/MCStreamer.h" +#include "llvm/Support/AArch64BuildAttributes.h" +#include namespace { class AArch64ELFStreamer; @@ -89,6 +94,24 @@ class AArch64TargetStreamer : public MCTargetStreamer { virtual void emitARM64WinCFISaveAnyRegQX(unsigned Reg, int Offset) {} virtual void emitARM64WinCFISaveAnyRegQPX(unsigned Reg, int Offset) {} + /// Build attributes implementation + virtual void + emitAtributesSubsection(StringRef VendorName, + AArch64BuildAttributes::SubsectionOptional IsOptional, + AArch64BuildAttributes::SubsectionType ParameterType); + virtual void emitAttribute(StringRef VendorName, unsigned Tag, unsigned Value, + std::string String, bool Override); + void activateAtributesSubsection(StringRef VendorName); + std::unique_ptr + getActiveAtributesSubsection(); + std::unique_ptr + getAtributesSubsectionByName(StringRef Name); + void + insertAttributeInPlace(const MCELFStreamer::AttributeItem &Attr, + MCELFStreamer::AttributeSubSection &AttSubSection); + + SmallVector AttributeSubSections; + private: std::unique_ptr ConstantPools; }; @@ -97,6 +120,15 @@ class AArch64TargetELFStreamer : public AArch64TargetStreamer { private: AArch64ELFStreamer &getStreamer(); + MCSection *AttributeSection = nullptr; + + /// Build attributes implementation + void emitAtributesSubsection( + StringRef VendorName, + AArch64BuildAttributes::SubsectionOptional IsOptional, + AArch64BuildAttributes::SubsectionType ParameterType) override; + void emitAttribute(StringRef VendorName, unsigned Tag, unsigned Value, + std::string String, bool Override = false) override; void emitInst(uint32_t Inst) override; void emitDirectiveVariantPCS(MCSymbol *Symbol) override; void finish() override; diff --git a/llvm/test/CodeGen/AArch64/aarch64-build-attributes-all.ll b/llvm/test/CodeGen/AArch64/aarch64-build-attributes-all.ll new file mode 100644 index 0000000000000..81ece7aec8793 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/aarch64-build-attributes-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-bti.ll b/llvm/test/CodeGen/AArch64/aarch64-build-attributes-bti.ll new file mode 100644 index 0000000000000..e719e06553cc0 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/aarch64-build-attributes-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-gcs.ll b/llvm/test/CodeGen/AArch64/aarch64-build-attributes-gcs.ll new file mode 100644 index 0000000000000..6f231025a11e3 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/aarch64-build-attributes-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-pac.ll b/llvm/test/CodeGen/AArch64/aarch64-build-attributes-pac.ll new file mode 100644 index 0000000000000..54ff12655eb23 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/aarch64-build-attributes-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} diff --git a/llvm/test/CodeGen/AArch64/aarch64-build-attributes-pauthabi.ll b/llvm/test/CodeGen/AArch64/aarch64-build-attributes-pauthabi.ll new file mode 100644 index 0000000000000..7e41167e8fff5 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/aarch64-build-attributes-pauthabi.ll @@ -0,0 +1,19 @@ +; 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_pauthabi, required, uleb128 +; ASM-NEXT: .aeabi_attribute Tag_PAuth_Platform, 2 +; ASM-NEXT: .aeabi_attribute Tag_PAuth_Schema, 31 + +; ELF: Hex dump of section '.ARM.attributes': +; ELF-NEXT: 0x00000000 41190000 00616561 62695f70 61757468 A....aeabi_pauth +; ELF-NEXT: 0x00000010 61626900 00000102 021f + + +target triple = "aarch64-unknown-none-elf" + +!llvm.module.flags = !{!1, !2} + +!1 = !{i32 1, !"aarch64-elf-pauthabi-platform", i32 2} +!2 = !{i32 1, !"aarch64-elf-pauthabi-version", i32 31} 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 0000000000000..a895821f3b05d --- /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 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 0000000000000..25573a0cabeca --- /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 diff --git a/llvm/test/MC/AArch64/aarch64-build-attributes-asm-err-attrs.s b/llvm/test/MC/AArch64/aarch64-build-attributes-asm-err-attrs.s new file mode 100644 index 0000000000000..e8daec0525591 --- /dev/null +++ b/llvm/test/MC/AArch64/aarch64-build-attributes-asm-err-attrs.s @@ -0,0 +1,70 @@ +// RUN: not llvm-mc -triple=aarch64 %s 2>&1 | FileCheck --check-prefix=ERR %s + +.aeabi_attribute Tag_Feature_BTI, 1 +// ERR: error: no active subsection, build attribute can not be added +// ERR-NEXT: .aeabi_attribute Tag_Feature_BTI, 1 + +.aeabi_subsection aeabi_pauthabi, required, uleb128 +.aeabi_attribute Tag_Feature_BTI, 1 +// ERR: error: unknown AArch64 build attribute 'Tag_Feature_BTI' for subsection 'aeabi_pauthabi' +// ERR-NEXT: .aeabi_attribute Tag_Feature_BTI, 1 + +.aeabi_attribute Tag_PAuth_Platform, 4 +// ERR: error: unknown AArch64 build attributes Value for Tag 'Tag_PAuth_Platform' options are 0|1 +// ERR-NEXT: .aeabi_attribute Tag_PAuth_Platform, 4 + +.aeabi_attribute a, 1 +// ERR: error: unknown AArch64 build attribute 'a' for subsection 'aeabi_pauthabi' +// ERR-NEXT: .aeabi_attribute a, 1 + +.aeabi_attribute Tag_PAuth_Platform, Tag_PAuth_Platform +// ERR: error: active subsection type is ULEB128 (unsigned), found NTBS (string) +// ERR-NEXT: .aeabi_attribute Tag_PAuth_Platform, Tag_PAuth_Platform + +.aeabi_attribute Tag_PAuth_Platform, a +// ERR: error: active subsection type is ULEB128 (unsigned), found NTBS (string) +// ERR-NEXT: .aeabi_attribute Tag_PAuth_Platform, a + +.aeabi_attribute Tag_PAuth_Platform, +// ERR: error: AArch64 build attributes value not found +// ERR-NEXT: .aeabi_attribute Tag_PAuth_Platform, + +.aeabi_attribute Tag_PAuth_Platform +// ERR: error: expected comma +// ERR-NEXT: .aeabi_attribute Tag_PAuth_Platform + +.aeabi_attribute +// ERR: error: AArch64 build attributes tag not found +// ERR-NEXT: .aeabi_attribute + +.aeabi_subsection aeabi_feature_and_bits, optional, uleb128 +.aeabi_attribute Tag_PAuth_Platform, 1 +// ERR: unknown AArch64 build attribute 'Tag_PAuth_Platform' for subsection 'aeabi_feature_and_bits' + +.aeabi_attribute a, 1 +// ERR: error: unknown AArch64 build attribute 'a' for subsection 'aeabi_feature_and_bits' + +.aeabi_attribute Tag_Feature_BTI, Tag_Feature_BTI +// ERR: error: active subsection type is ULEB128 (unsigned), found NTBS (string) +// ERR-NEXT: .aeabi_attribute Tag_Feature_BTI, Tag_Feature_BTI + +.aeabi_attribute Tag_Feature_BTI, a +// ERR: error: active subsection type is ULEB128 (unsigned), found NTBS (string) +// ERR-NEXT: .aeabi_attribute Tag_Feature_BTI, a + +.aeabi_attribute Tag_Feature_BTI, +// ERR: error: AArch64 build attributes value not found +// ERR-NEXT: .aeabi_attribute Tag_Feature_BTI, + +.aeabi_attribute Tag_Feature_BTI +// ERR: error: expected comma +// ERR-NEXT: .aeabi_attribute Tag_Feature_BTI + +.aeabi_attribute +// ERR: error: AArch64 build attributes tag not found +// ERR-NEXT: .aeabi_attribute + +.aeabi_subsection aeabi_pauthabi, required, uleb128 +.aeabi_attribute Tag_PAuth_Platform, 1 some_text +// ERR: error: unexpected token for AArch64 build attributes tag and value attribute directive +// ERR-NEXT: .aeabi_attribute Tag_PAuth_Platform, 1 some_text \ No newline at end of file diff --git a/llvm/test/MC/AArch64/aarch64-build-attributes-asm-err-headers.s b/llvm/test/MC/AArch64/aarch64-build-attributes-asm-err-headers.s new file mode 100644 index 0000000000000..9e6dca341e9f8 --- /dev/null +++ b/llvm/test/MC/AArch64/aarch64-build-attributes-asm-err-headers.s @@ -0,0 +1,61 @@ +// RUN: not llvm-mc -triple=aarch64 %s 2>&1 | FileCheck --check-prefix=ERR %s + +.aeabi_subsection aeabi_pauthabi, optional, uleb128 +// ERR: error: aeabi_pauthabi must be marked as required +// ERR-NEXT: .aeabi_subsection aeabi_pauthabi, optional, uleb128 + +.aeabi_subsection aeabi_pauthabi, required, ntbs +// ERR: error: aeabi_pauthabi must be marked as ULEB128 +// ERR-NEXT: .aeabi_subsection aeabi_pauthabi, required, ntbs + +.aeabi_subsection aeabi_feature_and_bits, required, uleb128 +// ERR: error: aeabi_feature_and_bits must be marked as optional +// ERR-NEXT: .aeabi_subsection aeabi_feature_and_bits, required, uleb128 + +.aeabi_subsection aeabi_feature_and_bits, optional, ntbs +// ERR: error: aeabi_feature_and_bits must be marked as ULEB128 +// ERR-NEXT: .aeabi_subsection aeabi_feature_and_bits, optional, ntbs + +.aeabi_subsection 1, required, uleb128 +// ERR: error: subsection name not found +// ERR-NEXT: .aeabi_subsection 1, required, uleb128 + +.aeabi_subsection , required, uleb128 +// ERR: error: subsection name not found +// ERR-NEXT: .aeabi_subsection , required, uleb128 + +.aeabi_subsection aeabi_pauthabi, a, uleb128 +// ERR: error: unknown AArch64 build attributes optionality, expected required|optional: a +// ERR-NEXT: .aeabi_subsection aeabi_pauthabi, a, uleb128 + +.aeabi_subsection aeabi_pauthabi, a, uleb128 +// ERR: error: unknown AArch64 build attributes optionality, expected required|optional: a +// ERR-NEXT: .aeabi_subsection aeabi_pauthabi, a, uleb128 + +.aeabi_subsection aeabi_pauthabi, 1, uleb128 +// ERR: error: optionality parameter not found, expected required|optional +// ERR-NEXT: .aeabi_subsection aeabi_pauthabi, 1, uleb128 + +.aeabi_subsection aeabi_pauthabi, ,uleb128 +// ERR: error: optionality parameter not found, expected required|optional +// ERR-NEXT: .aeabi_subsection aeabi_pauthabi, ,uleb128 + +.aeabi_subsection aeabi_pauthabi,uleb128 +// ERR: error: unknown AArch64 build attributes optionality, expected required|optional: uleb128 +// ERR-NEXT: .aeabi_subsection aeabi_pauthabi,uleb128 + +.aeabi_subsection aeabi_pauthabi uleb128 +// ERR: expected comma +// ERR-NEXT: .aeabi_subsection aeabi_pauthabi uleb128 + +.aeabi_subsection aeabi_pauthabi, required +// ERR: error: expected comma +// ERR-NEXT: .aeabi_subsection aeabi_pauthabi, required + +.aeabi_subsection aeabi_pauthabi, required, +// ERR: error: type parameter not found, expected uleb128|ntbs +// ERR-NEXT: .aeabi_subsection aeabi_pauthabi, required, + +.aeabi_subsection aeabi_pauthabi, required, a +// ERR: error: unknown AArch64 build attributes type, expected uleb128|ntbs: a +// ERR-NEXT: .aeabi_subsection aeabi_pauthabi, required, a 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 0000000000000..62789c514dc33 --- /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 0000000000000..07c89670373de --- /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-numerical-tags.s b/llvm/test/MC/AArch64/aarch64-build-attributes-asm-numerical-tags.s new file mode 100644 index 0000000000000..2cdae778df5de --- /dev/null +++ b/llvm/test/MC/AArch64/aarch64-build-attributes-asm-numerical-tags.s @@ -0,0 +1,41 @@ +// RUN: llvm-mc -triple=aarch64 %s -o - | FileCheck %s --check-prefix=ASM + +// ASM: .text +// ASM: .aeabi_subsection aeabi_pauthabi, required, uleb128 +// ASM: .aeabi_attribute 0, 1 +// ASM: .aeabi_attribute Tag_PAuth_Platform, 1 +// ASM: .aeabi_attribute Tag_PAuth_Schema, 1 +// ASM: .aeabi_attribute 3, 1 +// ASM: .aeabi_attribute 4, 1 +// ASM: .aeabi_attribute 5, 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 +// ASM: .aeabi_attribute 3, 1 +// ASM: .aeabi_attribute 4, 1 +// ASM: .aeabi_attribute 5, 1 + +// ELF: Hex dump of section '.ARM.attributes': +// ELF-NEXT: 0x00000000 41210000 00616561 62695f70 61757468 A!...aeabi_pauth +// ELF-NEXT: 0x00000010 61626900 00000001 01010201 03010401 abi............. +// ELF-NEXT: 0x00000020 05012900 00006165 6162695f 66656174 ..)...aeabi_feat +// ELF-NEXT: 0x00000030 7572655f 616e645f 62697473 00010000 ure_and_bits.... +// ELF-NEXT: 0x00000040 01010102 01030104 010501 + + +.text +.aeabi_subsection aeabi_pauthabi, required, uleb128 +.aeabi_attribute 0, 1 +.aeabi_attribute 1, 1 +.aeabi_attribute 2, 1 +.aeabi_attribute 3, 1 +.aeabi_attribute 4, 1 +.aeabi_attribute 5, 1 +.aeabi_subsection aeabi_feature_and_bits, optional, uleb128 +.aeabi_attribute 0, 1 +.aeabi_attribute 1, 1 +.aeabi_attribute 2, 1 +.aeabi_attribute 3, 1 +.aeabi_attribute 4, 1 +.aeabi_attribute 5, 1 \ 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 0000000000000..08ea2173ab86c --- /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_PAC, 0 +// ASM: .aeabi_subsection aeabi_feature_and_bits, optional, uleb128 +// ASM: .aeabi_attribute 7, 1 +// ASM: .aeabi_subsection aeabi_pauthabi, required, uleb128 +// ASM: .aeabi_attribute 7, 0 + +// ELF: Hex dump of section '.ARM.attributes': +// ELF-NEXT: 0x00000000 411b0000 00616561 62695f70 61757468 A....aeabi_pauth +// ELF-NEXT: 0x00000010 61626900 00000201 01010700 25000000 abi.........%... +// ELF-NEXT: 0x00000020 61656162 695f6665 61747572 655f616e aeabi_feature_an +// ELF-NEXT: 0x00000030 645f6269 74730001 00000102 01010007 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_PAC, 0 +.aeabi_subsection aeabi_feature_and_bits, optional, uleb128 +.aeabi_attribute 7, 1 +.aeabi_subsection aeabi_pauthabi, required, uleb128 +.aeabi_attribute 7, 0 \ 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 0000000000000..483cae0e09cc7 --- /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 diff --git a/llvm/test/MC/AArch64/aarch64-build-attributes-asm-private-subsections-err.s b/llvm/test/MC/AArch64/aarch64-build-attributes-asm-private-subsections-err.s new file mode 100644 index 0000000000000..2b4cbcc721acd --- /dev/null +++ b/llvm/test/MC/AArch64/aarch64-build-attributes-asm-private-subsections-err.s @@ -0,0 +1,28 @@ +// RUN: not llvm-mc -triple=aarch64 %s 2>&1 | FileCheck --check-prefix=ERR %s + +.aeabi_subsection private_subsection, optional, uleb128 + +.aeabi_subsection private_subsection, required, uleb128 +// ERR: error: optionality mismatch! subsection 'private_subsection' already exists with optionality defined as 'optional' and not 'required' +// ERR-NEXT: .aeabi_subsection private_subsection, required, uleb128 + +.aeabi_subsection private_subsection, optional, ntbs +// ERR: error: type mismatch! subsection 'private_subsection' already exists with type defined as 'uleb128' and not 'ntbs' +// ERR-NEXT: .aeabi_subsection private_subsection, optional, ntbs + +.aeabi_subsection private_subsection_1, optional, ntbs +.aeabi_attribute 324, 1 +// ERR: error: active subsection type is NTBS (string), found ULEB128 (unsigned) +// ERR-NEXT: .aeabi_attribute 324, 1 + +.aeabi_subsection foo, optional, uleb128 +.aeabi_subsection bar, optional, uleb128 +.aeabi_subsection foo, required, uleb128 +// ERR: error: optionality mismatch! subsection 'foo' already exists with optionality defined as 'optional' and not 'required' +// ERR-NEXT: .aeabi_subsection foo, required, uleb128 + +.aeabi_subsection goo, optional, ntbs +.aeabi_subsection zar, optional, ntbs +.aeabi_subsection goo, optional, uleb128 +// ERR: error: type mismatch! subsection 'goo' already exists with type defined as 'ntbs' and not 'uleb128' +// ERR-NEXT: .aeabi_subsection goo, optional, uleb128 \ No newline at end of file diff --git a/llvm/test/MC/AArch64/aarch64-build-attributes-asm-private-subsections.s b/llvm/test/MC/AArch64/aarch64-build-attributes-asm-private-subsections.s new file mode 100644 index 0000000000000..229033a9f6b70 --- /dev/null +++ b/llvm/test/MC/AArch64/aarch64-build-attributes-asm-private-subsections.s @@ -0,0 +1,51 @@ +// 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 private_subsection_1, optional, uleb128 +// ASM: .aeabi_attribute 12, 257 +// ASM: .aeabi_subsection private_subsection_2, required, uleb128 +// ASM: .aeabi_attribute 76, 257 +// ASM: .aeabi_subsection private_subsection_3, optional, ntbs +// ASM: .aeabi_attribute 34, hello_llvm +// ASM: .aeabi_subsection private_subsection_4, required, ntbs +// ASM: .aeabi_attribute 777, "hello_llvm" +// ASM: .aeabi_subsection private_subsection_1, optional, uleb128 +// ASM: .aeabi_attribute 876, 257 +// ASM: .aeabi_subsection private_subsection_2, required, uleb128 +// ASM: .aeabi_attribute 876, 257 +// ASM: .aeabi_subsection private_subsection_3, optional, ntbs +// ASM: .aeabi_attribute 876, "hello_llvm" +// ASM: .aeabi_subsection private_subsection_4, required, ntbs +// ASM: .aeabi_attribute 876, hello_llvm + +// ELF: Hex dump of section '.ARM.attributes': +// ELF-NEXT: 0x00000000 41220000 00707269 76617465 5f737562 A"...private_sub +// ELF-NEXT: 0x00000010 73656374 696f6e5f 31000100 0c8102ec section_1....... +// ELF-NEXT: 0x00000020 06810222 00000070 72697661 74655f73 ..."...private_s +// ELF-NEXT: 0x00000030 75627365 6374696f 6e5f3200 00004c81 ubsection_2...L. +// ELF-NEXT: 0x00000040 02ec0681 02360000 00707269 76617465 .....6...private +// ELF-NEXT: 0x00000050 5f737562 73656374 696f6e5f 33000101 _subsection_3... +// ELF-NEXT: 0x00000060 2268656c 6c6f5f6c 6c766d00 ec062268 "hello_llvm..."h +// ELF-NEXT: 0x00000070 656c6c6f 5f6c6c76 6d220037 00000070 ello_llvm".7...p +// ELF-NEXT: 0x00000080 72697661 74655f73 75627365 6374696f rivate_subsectio +// ELF-NEXT: 0x00000090 6e5f3400 00018906 2268656c 6c6f5f6c n_4....."hello_l +// ELF-NEXT: 0x000000a0 6c766d22 00ec0668 656c6c6f 5f6c6c76 lvm"...hello_llv +// ELF-NEXT: 0x000000b0 6d00 m. + + +.aeabi_subsection private_subsection_1, optional, uleb128 +.aeabi_attribute 12, 257 +.aeabi_subsection private_subsection_2, required, uleb128 +.aeabi_attribute 76, 257 +.aeabi_subsection private_subsection_3, optional, ntbs +.aeabi_attribute 34, hello_llvm +.aeabi_subsection private_subsection_4, required, ntbs +.aeabi_attribute 777, "hello_llvm" +.aeabi_subsection private_subsection_1, optional, uleb128 +.aeabi_attribute 876, 257 +.aeabi_subsection private_subsection_2, required, uleb128 +.aeabi_attribute 876, 257 +.aeabi_subsection private_subsection_3, optional, ntbs +.aeabi_attribute 876, "hello_llvm" +.aeabi_subsection private_subsection_4, required, ntbs +.aeabi_attribute 876, hello_llvm diff --git a/llvm/utils/gn/secondary/llvm/lib/Support/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/Support/BUILD.gn index d152aec19d1b5..008715a0b3dea 100644 --- a/llvm/utils/gn/secondary/llvm/lib/Support/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/lib/Support/BUILD.gn @@ -33,6 +33,7 @@ static_library("Support") { "Windows", ] sources = [ + "AArch64BuildAttributes.cpp" "ABIBreak.cpp", "AMDGPUMetadata.cpp", "APFixedPoint.cpp", @@ -41,6 +42,7 @@ static_library("Support") { "APSInt.cpp", "ARMAttributeParser.cpp", "ARMBuildAttrs.cpp", + "AArch64BuildAttributes.cpp", "ARMWinEH.cpp", "Allocator.cpp", "AutoConvert.cpp",