-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[LLVM][Clang][AArch64] Implement AArch64 build attributes #118771
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
a10af46
c1c4c46
8bc5b42
6e09e35
3450b35
b323e83
4505446
e86ca8d
f4f1b1b
b651b3c
7cde215
07b1f74
06215d9
3b9f53e
a09c731
22bee6f
56f496b
5082f08
85819a6
0fde842
330cb79
1535a88
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,10 +21,49 @@ | |
| #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 +127,17 @@ 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, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -635,10 +635,11 @@ void MCELFStreamer::emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, | |
| llvm_unreachable("ELF doesn't support this directive"); | ||
| } | ||
|
|
||
| void MCELFStreamer::setAttributeItem(unsigned Attribute, unsigned Value, | ||
| bool OverwriteExisting) { | ||
| void MCELFStreamer::setAttributeItem( | ||
| unsigned Attribute, unsigned Value, 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; | ||
|
|
@@ -652,10 +653,11 @@ void MCELFStreamer::setAttributeItem(unsigned Attribute, unsigned Value, | |
| Contents.push_back(Item); | ||
| } | ||
|
|
||
| void MCELFStreamer::setAttributeItem(unsigned Attribute, StringRef Value, | ||
| bool OverwriteExisting) { | ||
| void MCELFStreamer::setAttributeItem( | ||
| unsigned Attribute, StringRef Value, 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; | ||
|
|
@@ -669,11 +671,11 @@ void MCELFStreamer::setAttributeItem(unsigned Attribute, StringRef Value, | |
| Contents.push_back(Item); | ||
| } | ||
|
|
||
| void MCELFStreamer::setAttributeItems(unsigned Attribute, unsigned IntValue, | ||
| StringRef StringValue, | ||
| bool OverwriteExisting) { | ||
| 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)) { | ||
| if (AttributeItem *Item = getAttributeItem(Attribute, Attributes)) { | ||
| if (!OverwriteExisting) | ||
| return; | ||
| Item->Type = AttributeItem::NumericAndTextAttributes; | ||
|
|
@@ -689,15 +691,16 @@ 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) { | ||
| size_t MCELFStreamer::calculateContentSize( | ||
| SmallVector<AttributeItem, 64> &AttrsVec) const { | ||
| size_t Result = 0; | ||
| for (const AttributeItem &Item : AttrsVec) { | ||
| switch (Item.Type) { | ||
|
|
@@ -783,6 +786,65 @@ 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, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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 | ||
|
|
||
| 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 | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You have added enums for these in ARMBuildAttributes.h, should they be used here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that is a good idea.
Changing the relevant locations.