mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 19:52:54 +01:00
[MCStreamer] Move emission of attributes section into MCELFStreamer
Enable the emission of a GNU attributes section by reusing the code for emitting the ARM build attributes section. The GNU attributes follow the exact same section format as the ARM BuildAttributes section, so this can be factored out and reused for GNU attributes generally. The immediate motivation for this is to emit a GNU attributes section for the vector ABI on SystemZ (https://reviews.llvm.org/D105067). Review: Logan Chien, Ulrich Weigand Differential Revision: https://reviews.llvm.org/D102894
This commit is contained in:
parent
cc12b285b6
commit
38b768656f
@ -10,6 +10,7 @@
|
||||
#define LLVM_MC_MCELFSTREAMER_H
|
||||
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/BinaryFormat/ELF.h"
|
||||
#include "llvm/MC/MCDirectives.h"
|
||||
#include "llvm/MC/MCObjectStreamer.h"
|
||||
|
||||
@ -79,6 +80,52 @@ public:
|
||||
void emitBundleLock(bool AlignToEnd) override;
|
||||
void emitBundleUnlock() override;
|
||||
|
||||
/// ELF object attributes section emission support
|
||||
struct AttributeItem {
|
||||
// This structure holds all attributes, accounting for their string /
|
||||
// numeric value, so we can later emit them in declaration order, keeping
|
||||
// all in the same vector.
|
||||
enum {
|
||||
HiddenAttribute = 0,
|
||||
NumericAttribute,
|
||||
TextAttribute,
|
||||
NumericAndTextAttributes
|
||||
} Type;
|
||||
unsigned Tag;
|
||||
unsigned IntValue;
|
||||
std::string StringValue;
|
||||
};
|
||||
|
||||
// Attributes that are added and managed entirely by target.
|
||||
SmallVector<AttributeItem, 64> Contents;
|
||||
void setAttributeItem(unsigned Attribute, unsigned Value,
|
||||
bool OverwriteExisting);
|
||||
void setAttributeItem(unsigned Attribute, StringRef Value,
|
||||
bool OverwriteExisting);
|
||||
void setAttributeItems(unsigned Attribute, unsigned IntValue,
|
||||
StringRef StringValue, bool OverwriteExisting);
|
||||
void emitAttributesSection(StringRef Vendor, const Twine &Section,
|
||||
unsigned Type, MCSection *&AttributeSection) {
|
||||
createAttributesSection(Vendor, Section, Type, AttributeSection, Contents);
|
||||
}
|
||||
|
||||
private:
|
||||
AttributeItem *getAttributeItem(unsigned Attribute);
|
||||
size_t calculateContentSize(SmallVector<AttributeItem, 64> &AttrsVec);
|
||||
void createAttributesSection(StringRef Vendor, const Twine &Section,
|
||||
unsigned Type, MCSection *&AttributeSection,
|
||||
SmallVector<AttributeItem, 64> &AttrsVec);
|
||||
|
||||
// GNU attributes that will get emitted at the end of the asm file.
|
||||
SmallVector<AttributeItem, 64> GNUAttributes;
|
||||
|
||||
public:
|
||||
void emitGNUAttribute(unsigned Tag, unsigned Value) override {
|
||||
AttributeItem Item = {AttributeItem::NumericAttribute, Tag, Value,
|
||||
std::string(StringRef(""))};
|
||||
GNUAttributes.push_back(Item);
|
||||
}
|
||||
|
||||
private:
|
||||
bool isBundleLocked() const;
|
||||
void emitInstToFragment(const MCInst &Inst, const MCSubtargetInfo &) override;
|
||||
|
@ -337,6 +337,9 @@ public:
|
||||
/// \return - False on success.
|
||||
virtual bool parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res,
|
||||
SMLoc &EndLoc) = 0;
|
||||
|
||||
/// Parse a .gnu_attribute.
|
||||
bool parseGNUAttribute(SMLoc L, int64_t &Tag, int64_t &IntegerValue);
|
||||
};
|
||||
|
||||
/// Create an MCAsmParser instance for parsing assembly similar to gas syntax
|
||||
|
@ -618,6 +618,9 @@ public:
|
||||
/// \param Args - Arguments of the LOH.
|
||||
virtual void emitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) {}
|
||||
|
||||
/// Emit a .gnu_attribute directive.
|
||||
virtual void emitGNUAttribute(unsigned Tag, unsigned Value) {}
|
||||
|
||||
/// Emit a common symbol.
|
||||
///
|
||||
/// \param Symbol - The common symbol to emit.
|
||||
|
@ -153,6 +153,8 @@ public:
|
||||
|
||||
void emitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) override;
|
||||
|
||||
void emitGNUAttribute(unsigned Tag, unsigned Value) override;
|
||||
|
||||
StringRef getMnemonic(MCInst &MI) override {
|
||||
return InstPrinter->getMnemonic(&MI).first;
|
||||
}
|
||||
@ -538,6 +540,10 @@ void MCAsmStreamer::emitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) {
|
||||
EmitEOL();
|
||||
}
|
||||
|
||||
void MCAsmStreamer::emitGNUAttribute(unsigned Tag, unsigned Value) {
|
||||
OS << "\t.gnu_attribute " << Tag << ", " << Value << "\n";
|
||||
}
|
||||
|
||||
void MCAsmStreamer::emitAssemblerFlag(MCAssemblerFlag Flag) {
|
||||
switch (Flag) {
|
||||
case MCAF_SyntaxUnified: OS << "\t.syntax unified"; break;
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "llvm/MC/MCSymbolELF.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/LEB128.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <cassert>
|
||||
@ -697,6 +698,13 @@ void MCELFStreamer::emitBundleUnlock() {
|
||||
}
|
||||
|
||||
void MCELFStreamer::finishImpl() {
|
||||
// Emit the .gnu attributes section if any attributes have been added.
|
||||
if (!GNUAttributes.empty()) {
|
||||
MCSection *DummyAttributeSection = nullptr;
|
||||
createAttributesSection("gnu", ".gnu.attributes", ELF::SHT_GNU_ATTRIBUTES,
|
||||
DummyAttributeSection, GNUAttributes);
|
||||
}
|
||||
|
||||
// Ensure the last section gets aligned if necessary.
|
||||
MCSection *CurSection = getCurrentSectionOnly();
|
||||
setSectionAlignmentForBundling(getAssembler(), CurSection);
|
||||
@ -726,6 +734,156 @@ void MCELFStreamer::emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
|
||||
llvm_unreachable("ELF doesn't support this directive");
|
||||
}
|
||||
|
||||
void MCELFStreamer::setAttributeItem(unsigned Attribute, unsigned Value,
|
||||
bool OverwriteExisting) {
|
||||
// Look for existing attribute item
|
||||
if (AttributeItem *Item = getAttributeItem(Attribute)) {
|
||||
if (!OverwriteExisting)
|
||||
return;
|
||||
Item->Type = AttributeItem::NumericAttribute;
|
||||
Item->IntValue = Value;
|
||||
return;
|
||||
}
|
||||
|
||||
// Create new attribute item
|
||||
AttributeItem Item = {AttributeItem::NumericAttribute, Attribute, Value,
|
||||
std::string(StringRef(""))};
|
||||
Contents.push_back(Item);
|
||||
}
|
||||
|
||||
void MCELFStreamer::setAttributeItem(unsigned Attribute, StringRef Value,
|
||||
bool OverwriteExisting) {
|
||||
// Look for existing attribute item
|
||||
if (AttributeItem *Item = getAttributeItem(Attribute)) {
|
||||
if (!OverwriteExisting)
|
||||
return;
|
||||
Item->Type = AttributeItem::TextAttribute;
|
||||
Item->StringValue = std::string(Value);
|
||||
return;
|
||||
}
|
||||
|
||||
// Create new attribute item
|
||||
AttributeItem Item = {AttributeItem::TextAttribute, Attribute, 0,
|
||||
std::string(Value)};
|
||||
Contents.push_back(Item);
|
||||
}
|
||||
|
||||
void MCELFStreamer::setAttributeItems(unsigned Attribute, unsigned IntValue,
|
||||
StringRef StringValue,
|
||||
bool OverwriteExisting) {
|
||||
// Look for existing attribute item
|
||||
if (AttributeItem *Item = getAttributeItem(Attribute)) {
|
||||
if (!OverwriteExisting)
|
||||
return;
|
||||
Item->Type = AttributeItem::NumericAndTextAttributes;
|
||||
Item->IntValue = IntValue;
|
||||
Item->StringValue = std::string(StringValue);
|
||||
return;
|
||||
}
|
||||
|
||||
// Create new attribute item
|
||||
AttributeItem Item = {AttributeItem::NumericAndTextAttributes, Attribute,
|
||||
IntValue, std::string(StringValue)};
|
||||
Contents.push_back(Item);
|
||||
}
|
||||
|
||||
MCELFStreamer::AttributeItem *
|
||||
MCELFStreamer::getAttributeItem(unsigned Attribute) {
|
||||
for (size_t I = 0; I < Contents.size(); ++I)
|
||||
if (Contents[I].Tag == Attribute)
|
||||
return &Contents[I];
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
size_t
|
||||
MCELFStreamer::calculateContentSize(SmallVector<AttributeItem, 64> &AttrsVec) {
|
||||
size_t Result = 0;
|
||||
for (size_t I = 0; I < AttrsVec.size(); ++I) {
|
||||
AttributeItem Item = AttrsVec[I];
|
||||
switch (Item.Type) {
|
||||
case AttributeItem::HiddenAttribute:
|
||||
break;
|
||||
case AttributeItem::NumericAttribute:
|
||||
Result += getULEB128Size(Item.Tag);
|
||||
Result += getULEB128Size(Item.IntValue);
|
||||
break;
|
||||
case AttributeItem::TextAttribute:
|
||||
Result += getULEB128Size(Item.Tag);
|
||||
Result += Item.StringValue.size() + 1; // string + '\0'
|
||||
break;
|
||||
case AttributeItem::NumericAndTextAttributes:
|
||||
Result += getULEB128Size(Item.Tag);
|
||||
Result += getULEB128Size(Item.IntValue);
|
||||
Result += Item.StringValue.size() + 1; // string + '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
void MCELFStreamer::createAttributesSection(
|
||||
StringRef Vendor, const Twine &Section, unsigned Type,
|
||||
MCSection *&AttributeSection, SmallVector<AttributeItem, 64> &AttrsVec) {
|
||||
// <format-version>
|
||||
// [ <section-length> "vendor-name"
|
||||
// [ <file-tag> <size> <attribute>*
|
||||
// | <section-tag> <size> <section-number>* 0 <attribute>*
|
||||
// | <symbol-tag> <size> <symbol-number>* 0 <attribute>*
|
||||
// ]+
|
||||
// ]*
|
||||
|
||||
// Switch section to AttributeSection or get/create the section.
|
||||
if (AttributeSection) {
|
||||
SwitchSection(AttributeSection);
|
||||
} else {
|
||||
AttributeSection = getContext().getELFSection(Section, Type, 0);
|
||||
SwitchSection(AttributeSection);
|
||||
|
||||
// Format version
|
||||
emitInt8(0x41);
|
||||
}
|
||||
|
||||
// Vendor size + Vendor name + '\0'
|
||||
const size_t VendorHeaderSize = 4 + Vendor.size() + 1;
|
||||
|
||||
// Tag + Tag Size
|
||||
const size_t TagHeaderSize = 1 + 4;
|
||||
|
||||
const size_t ContentsSize = calculateContentSize(AttrsVec);
|
||||
|
||||
emitInt32(VendorHeaderSize + TagHeaderSize + ContentsSize);
|
||||
emitBytes(Vendor);
|
||||
emitInt8(0); // '\0'
|
||||
|
||||
emitInt8(ARMBuildAttrs::File);
|
||||
emitInt32(TagHeaderSize + ContentsSize);
|
||||
|
||||
// Size should have been accounted for already, now
|
||||
// emit each field as its type (ULEB or String)
|
||||
for (size_t I = 0; I < AttrsVec.size(); ++I) {
|
||||
AttributeItem Item = AttrsVec[I];
|
||||
emitULEB128IntValue(Item.Tag);
|
||||
switch (Item.Type) {
|
||||
default:
|
||||
llvm_unreachable("Invalid attribute type");
|
||||
case AttributeItem::NumericAttribute:
|
||||
emitULEB128IntValue(Item.IntValue);
|
||||
break;
|
||||
case AttributeItem::TextAttribute:
|
||||
emitBytes(Item.StringValue);
|
||||
emitInt8(0); // '\0'
|
||||
break;
|
||||
case AttributeItem::NumericAndTextAttributes:
|
||||
emitULEB128IntValue(Item.IntValue);
|
||||
emitBytes(Item.StringValue);
|
||||
emitInt8(0); // '\0'
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
AttrsVec.clear();
|
||||
}
|
||||
|
||||
MCStreamer *llvm::createELFStreamer(MCContext &Context,
|
||||
std::unique_ptr<MCAsmBackend> &&MAB,
|
||||
std::unique_ptr<MCObjectWriter> &&OW,
|
||||
|
@ -140,6 +140,25 @@ bool MCAsmParser::parseExpression(const MCExpr *&Res) {
|
||||
return parseExpression(Res, L);
|
||||
}
|
||||
|
||||
bool MCAsmParser::parseGNUAttribute(SMLoc L, int64_t &Tag,
|
||||
int64_t &IntegerValue) {
|
||||
// Parse a .gnu_attribute with numerical tag and value.
|
||||
StringRef S(L.getPointer());
|
||||
SMLoc TagLoc;
|
||||
TagLoc = getTok().getLoc();
|
||||
const AsmToken &Tok = getTok();
|
||||
if (Tok.isNot(AsmToken::Integer))
|
||||
return false;
|
||||
Tag = Tok.getIntVal();
|
||||
Lex(); // Eat the Tag
|
||||
Lex(); // Eat the comma
|
||||
if (Tok.isNot(AsmToken::Integer))
|
||||
return false;
|
||||
IntegerValue = Tok.getIntVal();
|
||||
Lex(); // Eat the IntegerValue
|
||||
return true;
|
||||
}
|
||||
|
||||
void MCParsedAsmOperand::dump() const {
|
||||
// Cannot completely remove virtual function even in release mode.
|
||||
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
|
||||
|
@ -46,7 +46,6 @@
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/FormattedStream.h"
|
||||
#include "llvm/Support/LEB128.h"
|
||||
#include "llvm/Support/TargetParser.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <algorithm>
|
||||
@ -274,104 +273,13 @@ void ARMTargetAsmStreamer::emitUnwindRaw(int64_t Offset,
|
||||
|
||||
class ARMTargetELFStreamer : public ARMTargetStreamer {
|
||||
private:
|
||||
// This structure holds all attributes, accounting for
|
||||
// their string/numeric value, so we can later emit them
|
||||
// in declaration order, keeping all in the same vector
|
||||
struct AttributeItem {
|
||||
enum {
|
||||
HiddenAttribute = 0,
|
||||
NumericAttribute,
|
||||
TextAttribute,
|
||||
NumericAndTextAttributes
|
||||
} Type;
|
||||
unsigned Tag;
|
||||
unsigned IntValue;
|
||||
std::string StringValue;
|
||||
|
||||
static bool LessTag(const AttributeItem &LHS, const AttributeItem &RHS) {
|
||||
// The conformance tag must be emitted first when serialised
|
||||
// into an object file. Specifically, the addenda to the ARM ABI
|
||||
// states that (2.3.7.4):
|
||||
//
|
||||
// "To simplify recognition by consumers in the common case of
|
||||
// claiming conformity for the whole file, this tag should be
|
||||
// emitted first in a file-scope sub-subsection of the first
|
||||
// public subsection of the attributes section."
|
||||
//
|
||||
// So it is special-cased in this comparison predicate when the
|
||||
// attributes are sorted in finishAttributeSection().
|
||||
return (RHS.Tag != ARMBuildAttrs::conformance) &&
|
||||
((LHS.Tag == ARMBuildAttrs::conformance) || (LHS.Tag < RHS.Tag));
|
||||
}
|
||||
};
|
||||
|
||||
StringRef CurrentVendor;
|
||||
unsigned FPU = ARM::FK_INVALID;
|
||||
ARM::ArchKind Arch = ARM::ArchKind::INVALID;
|
||||
ARM::ArchKind EmittedArch = ARM::ArchKind::INVALID;
|
||||
SmallVector<AttributeItem, 64> Contents;
|
||||
|
||||
MCSection *AttributeSection = nullptr;
|
||||
|
||||
AttributeItem *getAttributeItem(unsigned Attribute) {
|
||||
for (size_t i = 0; i < Contents.size(); ++i)
|
||||
if (Contents[i].Tag == Attribute)
|
||||
return &Contents[i];
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void setAttributeItem(unsigned Attribute, unsigned Value,
|
||||
bool OverwriteExisting) {
|
||||
// Look for existing attribute item
|
||||
if (AttributeItem *Item = getAttributeItem(Attribute)) {
|
||||
if (!OverwriteExisting)
|
||||
return;
|
||||
Item->Type = AttributeItem::NumericAttribute;
|
||||
Item->IntValue = Value;
|
||||
return;
|
||||
}
|
||||
|
||||
// Create new attribute item
|
||||
AttributeItem Item = {AttributeItem::NumericAttribute, Attribute, Value,
|
||||
std::string(StringRef(""))};
|
||||
Contents.push_back(Item);
|
||||
}
|
||||
|
||||
void setAttributeItem(unsigned Attribute, StringRef Value,
|
||||
bool OverwriteExisting) {
|
||||
// Look for existing attribute item
|
||||
if (AttributeItem *Item = getAttributeItem(Attribute)) {
|
||||
if (!OverwriteExisting)
|
||||
return;
|
||||
Item->Type = AttributeItem::TextAttribute;
|
||||
Item->StringValue = std::string(Value);
|
||||
return;
|
||||
}
|
||||
|
||||
// Create new attribute item
|
||||
AttributeItem Item = {AttributeItem::TextAttribute, Attribute, 0,
|
||||
std::string(Value)};
|
||||
Contents.push_back(Item);
|
||||
}
|
||||
|
||||
void setAttributeItems(unsigned Attribute, unsigned IntValue,
|
||||
StringRef StringValue, bool OverwriteExisting) {
|
||||
// Look for existing attribute item
|
||||
if (AttributeItem *Item = getAttributeItem(Attribute)) {
|
||||
if (!OverwriteExisting)
|
||||
return;
|
||||
Item->Type = AttributeItem::NumericAndTextAttributes;
|
||||
Item->IntValue = IntValue;
|
||||
Item->StringValue = std::string(StringValue);
|
||||
return;
|
||||
}
|
||||
|
||||
// Create new attribute item
|
||||
AttributeItem Item = {AttributeItem::NumericAndTextAttributes, Attribute,
|
||||
IntValue, std::string(StringValue)};
|
||||
Contents.push_back(Item);
|
||||
}
|
||||
|
||||
void emitArchDefaultAttributes();
|
||||
void emitFPUDefaultAttributes();
|
||||
|
||||
@ -406,8 +314,6 @@ private:
|
||||
void AnnotateTLSDescriptorSequence(const MCSymbolRefExpr *SRE) override;
|
||||
void emitThumbSet(MCSymbol *Symbol, const MCExpr *Value) override;
|
||||
|
||||
size_t calculateContentSize() const;
|
||||
|
||||
// Reset state between object emissions
|
||||
void reset() override;
|
||||
|
||||
@ -777,26 +683,28 @@ void ARMTargetELFStreamer::switchVendor(StringRef Vendor) {
|
||||
if (!CurrentVendor.empty())
|
||||
finishAttributeSection();
|
||||
|
||||
assert(Contents.empty() &&
|
||||
assert(getStreamer().Contents.empty() &&
|
||||
".ARM.attributes should be flushed before changing vendor");
|
||||
CurrentVendor = Vendor;
|
||||
|
||||
}
|
||||
|
||||
void ARMTargetELFStreamer::emitAttribute(unsigned Attribute, unsigned Value) {
|
||||
setAttributeItem(Attribute, Value, /* OverwriteExisting= */ true);
|
||||
getStreamer().setAttributeItem(Attribute, Value,
|
||||
/* OverwriteExisting= */ true);
|
||||
}
|
||||
|
||||
void ARMTargetELFStreamer::emitTextAttribute(unsigned Attribute,
|
||||
StringRef Value) {
|
||||
setAttributeItem(Attribute, Value, /* OverwriteExisting= */ true);
|
||||
getStreamer().setAttributeItem(Attribute, Value,
|
||||
/* OverwriteExisting= */ true);
|
||||
}
|
||||
|
||||
void ARMTargetELFStreamer::emitIntTextAttribute(unsigned Attribute,
|
||||
unsigned IntValue,
|
||||
StringRef StringValue) {
|
||||
setAttributeItems(Attribute, IntValue, StringValue,
|
||||
/* OverwriteExisting= */ true);
|
||||
getStreamer().setAttributeItems(Attribute, IntValue, StringValue,
|
||||
/* OverwriteExisting= */ true);
|
||||
}
|
||||
|
||||
void ARMTargetELFStreamer::emitArch(ARM::ArchKind Value) {
|
||||
@ -809,19 +717,14 @@ void ARMTargetELFStreamer::emitObjectArch(ARM::ArchKind Value) {
|
||||
|
||||
void ARMTargetELFStreamer::emitArchDefaultAttributes() {
|
||||
using namespace ARMBuildAttrs;
|
||||
ARMELFStreamer &S = getStreamer();
|
||||
|
||||
setAttributeItem(CPU_name,
|
||||
ARM::getCPUAttr(Arch),
|
||||
false);
|
||||
S.setAttributeItem(CPU_name, ARM::getCPUAttr(Arch), false);
|
||||
|
||||
if (EmittedArch == ARM::ArchKind::INVALID)
|
||||
setAttributeItem(CPU_arch,
|
||||
ARM::getArchAttr(Arch),
|
||||
false);
|
||||
S.setAttributeItem(CPU_arch, ARM::getArchAttr(Arch), false);
|
||||
else
|
||||
setAttributeItem(CPU_arch,
|
||||
ARM::getArchAttr(EmittedArch),
|
||||
false);
|
||||
S.setAttributeItem(CPU_arch, ARM::getArchAttr(EmittedArch), false);
|
||||
|
||||
switch (Arch) {
|
||||
case ARM::ArchKind::ARMV2:
|
||||
@ -829,7 +732,7 @@ void ARMTargetELFStreamer::emitArchDefaultAttributes() {
|
||||
case ARM::ArchKind::ARMV3:
|
||||
case ARM::ArchKind::ARMV3M:
|
||||
case ARM::ArchKind::ARMV4:
|
||||
setAttributeItem(ARM_ISA_use, Allowed, false);
|
||||
S.setAttributeItem(ARM_ISA_use, Allowed, false);
|
||||
break;
|
||||
|
||||
case ARM::ArchKind::ARMV4T:
|
||||
@ -837,42 +740,42 @@ void ARMTargetELFStreamer::emitArchDefaultAttributes() {
|
||||
case ARM::ArchKind::XSCALE:
|
||||
case ARM::ArchKind::ARMV5TE:
|
||||
case ARM::ArchKind::ARMV6:
|
||||
setAttributeItem(ARM_ISA_use, Allowed, false);
|
||||
setAttributeItem(THUMB_ISA_use, Allowed, false);
|
||||
S.setAttributeItem(ARM_ISA_use, Allowed, false);
|
||||
S.setAttributeItem(THUMB_ISA_use, Allowed, false);
|
||||
break;
|
||||
|
||||
case ARM::ArchKind::ARMV6T2:
|
||||
setAttributeItem(ARM_ISA_use, Allowed, false);
|
||||
setAttributeItem(THUMB_ISA_use, AllowThumb32, false);
|
||||
S.setAttributeItem(ARM_ISA_use, Allowed, false);
|
||||
S.setAttributeItem(THUMB_ISA_use, AllowThumb32, false);
|
||||
break;
|
||||
|
||||
case ARM::ArchKind::ARMV6K:
|
||||
case ARM::ArchKind::ARMV6KZ:
|
||||
setAttributeItem(ARM_ISA_use, Allowed, false);
|
||||
setAttributeItem(THUMB_ISA_use, Allowed, false);
|
||||
setAttributeItem(Virtualization_use, AllowTZ, false);
|
||||
S.setAttributeItem(ARM_ISA_use, Allowed, false);
|
||||
S.setAttributeItem(THUMB_ISA_use, Allowed, false);
|
||||
S.setAttributeItem(Virtualization_use, AllowTZ, false);
|
||||
break;
|
||||
|
||||
case ARM::ArchKind::ARMV6M:
|
||||
setAttributeItem(THUMB_ISA_use, Allowed, false);
|
||||
S.setAttributeItem(THUMB_ISA_use, Allowed, false);
|
||||
break;
|
||||
|
||||
case ARM::ArchKind::ARMV7A:
|
||||
setAttributeItem(CPU_arch_profile, ApplicationProfile, false);
|
||||
setAttributeItem(ARM_ISA_use, Allowed, false);
|
||||
setAttributeItem(THUMB_ISA_use, AllowThumb32, false);
|
||||
S.setAttributeItem(CPU_arch_profile, ApplicationProfile, false);
|
||||
S.setAttributeItem(ARM_ISA_use, Allowed, false);
|
||||
S.setAttributeItem(THUMB_ISA_use, AllowThumb32, false);
|
||||
break;
|
||||
|
||||
case ARM::ArchKind::ARMV7R:
|
||||
setAttributeItem(CPU_arch_profile, RealTimeProfile, false);
|
||||
setAttributeItem(ARM_ISA_use, Allowed, false);
|
||||
setAttributeItem(THUMB_ISA_use, AllowThumb32, false);
|
||||
S.setAttributeItem(CPU_arch_profile, RealTimeProfile, false);
|
||||
S.setAttributeItem(ARM_ISA_use, Allowed, false);
|
||||
S.setAttributeItem(THUMB_ISA_use, AllowThumb32, false);
|
||||
break;
|
||||
|
||||
case ARM::ArchKind::ARMV7EM:
|
||||
case ARM::ArchKind::ARMV7M:
|
||||
setAttributeItem(CPU_arch_profile, MicroControllerProfile, false);
|
||||
setAttributeItem(THUMB_ISA_use, AllowThumb32, false);
|
||||
S.setAttributeItem(CPU_arch_profile, MicroControllerProfile, false);
|
||||
S.setAttributeItem(THUMB_ISA_use, AllowThumb32, false);
|
||||
break;
|
||||
|
||||
case ARM::ArchKind::ARMV8A:
|
||||
@ -882,29 +785,29 @@ void ARMTargetELFStreamer::emitArchDefaultAttributes() {
|
||||
case ARM::ArchKind::ARMV8_4A:
|
||||
case ARM::ArchKind::ARMV8_5A:
|
||||
case ARM::ArchKind::ARMV8_6A:
|
||||
setAttributeItem(CPU_arch_profile, ApplicationProfile, false);
|
||||
setAttributeItem(ARM_ISA_use, Allowed, false);
|
||||
setAttributeItem(THUMB_ISA_use, AllowThumb32, false);
|
||||
setAttributeItem(MPextension_use, Allowed, false);
|
||||
setAttributeItem(Virtualization_use, AllowTZVirtualization, false);
|
||||
S.setAttributeItem(CPU_arch_profile, ApplicationProfile, false);
|
||||
S.setAttributeItem(ARM_ISA_use, Allowed, false);
|
||||
S.setAttributeItem(THUMB_ISA_use, AllowThumb32, false);
|
||||
S.setAttributeItem(MPextension_use, Allowed, false);
|
||||
S.setAttributeItem(Virtualization_use, AllowTZVirtualization, false);
|
||||
break;
|
||||
|
||||
case ARM::ArchKind::ARMV8MBaseline:
|
||||
case ARM::ArchKind::ARMV8MMainline:
|
||||
setAttributeItem(THUMB_ISA_use, AllowThumbDerived, false);
|
||||
setAttributeItem(CPU_arch_profile, MicroControllerProfile, false);
|
||||
S.setAttributeItem(THUMB_ISA_use, AllowThumbDerived, false);
|
||||
S.setAttributeItem(CPU_arch_profile, MicroControllerProfile, false);
|
||||
break;
|
||||
|
||||
case ARM::ArchKind::IWMMXT:
|
||||
setAttributeItem(ARM_ISA_use, Allowed, false);
|
||||
setAttributeItem(THUMB_ISA_use, Allowed, false);
|
||||
setAttributeItem(WMMX_arch, AllowWMMXv1, false);
|
||||
S.setAttributeItem(ARM_ISA_use, Allowed, false);
|
||||
S.setAttributeItem(THUMB_ISA_use, Allowed, false);
|
||||
S.setAttributeItem(WMMX_arch, AllowWMMXv1, false);
|
||||
break;
|
||||
|
||||
case ARM::ArchKind::IWMMXT2:
|
||||
setAttributeItem(ARM_ISA_use, Allowed, false);
|
||||
setAttributeItem(THUMB_ISA_use, Allowed, false);
|
||||
setAttributeItem(WMMX_arch, AllowWMMXv2, false);
|
||||
S.setAttributeItem(ARM_ISA_use, Allowed, false);
|
||||
S.setAttributeItem(THUMB_ISA_use, Allowed, false);
|
||||
S.setAttributeItem(WMMX_arch, AllowWMMXv2, false);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -918,123 +821,106 @@ void ARMTargetELFStreamer::emitFPU(unsigned Value) {
|
||||
}
|
||||
|
||||
void ARMTargetELFStreamer::emitFPUDefaultAttributes() {
|
||||
ARMELFStreamer &S = getStreamer();
|
||||
|
||||
switch (FPU) {
|
||||
case ARM::FK_VFP:
|
||||
case ARM::FK_VFPV2:
|
||||
setAttributeItem(ARMBuildAttrs::FP_arch,
|
||||
ARMBuildAttrs::AllowFPv2,
|
||||
/* OverwriteExisting= */ false);
|
||||
S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv2,
|
||||
/* OverwriteExisting= */ false);
|
||||
break;
|
||||
|
||||
case ARM::FK_VFPV3:
|
||||
setAttributeItem(ARMBuildAttrs::FP_arch,
|
||||
ARMBuildAttrs::AllowFPv3A,
|
||||
/* OverwriteExisting= */ false);
|
||||
S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv3A,
|
||||
/* OverwriteExisting= */ false);
|
||||
break;
|
||||
|
||||
case ARM::FK_VFPV3_FP16:
|
||||
setAttributeItem(ARMBuildAttrs::FP_arch,
|
||||
ARMBuildAttrs::AllowFPv3A,
|
||||
/* OverwriteExisting= */ false);
|
||||
setAttributeItem(ARMBuildAttrs::FP_HP_extension,
|
||||
ARMBuildAttrs::AllowHPFP,
|
||||
/* OverwriteExisting= */ false);
|
||||
S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv3A,
|
||||
/* OverwriteExisting= */ false);
|
||||
S.setAttributeItem(ARMBuildAttrs::FP_HP_extension, ARMBuildAttrs::AllowHPFP,
|
||||
/* OverwriteExisting= */ false);
|
||||
break;
|
||||
|
||||
case ARM::FK_VFPV3_D16:
|
||||
setAttributeItem(ARMBuildAttrs::FP_arch,
|
||||
ARMBuildAttrs::AllowFPv3B,
|
||||
/* OverwriteExisting= */ false);
|
||||
S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv3B,
|
||||
/* OverwriteExisting= */ false);
|
||||
break;
|
||||
|
||||
case ARM::FK_VFPV3_D16_FP16:
|
||||
setAttributeItem(ARMBuildAttrs::FP_arch,
|
||||
ARMBuildAttrs::AllowFPv3B,
|
||||
/* OverwriteExisting= */ false);
|
||||
setAttributeItem(ARMBuildAttrs::FP_HP_extension,
|
||||
ARMBuildAttrs::AllowHPFP,
|
||||
/* OverwriteExisting= */ false);
|
||||
S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv3B,
|
||||
/* OverwriteExisting= */ false);
|
||||
S.setAttributeItem(ARMBuildAttrs::FP_HP_extension, ARMBuildAttrs::AllowHPFP,
|
||||
/* OverwriteExisting= */ false);
|
||||
break;
|
||||
|
||||
case ARM::FK_VFPV3XD:
|
||||
setAttributeItem(ARMBuildAttrs::FP_arch,
|
||||
ARMBuildAttrs::AllowFPv3B,
|
||||
/* OverwriteExisting= */ false);
|
||||
S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv3B,
|
||||
/* OverwriteExisting= */ false);
|
||||
break;
|
||||
case ARM::FK_VFPV3XD_FP16:
|
||||
setAttributeItem(ARMBuildAttrs::FP_arch,
|
||||
ARMBuildAttrs::AllowFPv3B,
|
||||
/* OverwriteExisting= */ false);
|
||||
setAttributeItem(ARMBuildAttrs::FP_HP_extension,
|
||||
ARMBuildAttrs::AllowHPFP,
|
||||
/* OverwriteExisting= */ false);
|
||||
S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv3B,
|
||||
/* OverwriteExisting= */ false);
|
||||
S.setAttributeItem(ARMBuildAttrs::FP_HP_extension, ARMBuildAttrs::AllowHPFP,
|
||||
/* OverwriteExisting= */ false);
|
||||
break;
|
||||
|
||||
case ARM::FK_VFPV4:
|
||||
setAttributeItem(ARMBuildAttrs::FP_arch,
|
||||
ARMBuildAttrs::AllowFPv4A,
|
||||
/* OverwriteExisting= */ false);
|
||||
S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv4A,
|
||||
/* OverwriteExisting= */ false);
|
||||
break;
|
||||
|
||||
// ABI_HardFP_use is handled in ARMAsmPrinter, so _SP_D16 is treated the same
|
||||
// as _D16 here.
|
||||
case ARM::FK_FPV4_SP_D16:
|
||||
case ARM::FK_VFPV4_D16:
|
||||
setAttributeItem(ARMBuildAttrs::FP_arch,
|
||||
ARMBuildAttrs::AllowFPv4B,
|
||||
/* OverwriteExisting= */ false);
|
||||
S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv4B,
|
||||
/* OverwriteExisting= */ false);
|
||||
break;
|
||||
|
||||
case ARM::FK_FP_ARMV8:
|
||||
setAttributeItem(ARMBuildAttrs::FP_arch,
|
||||
ARMBuildAttrs::AllowFPARMv8A,
|
||||
/* OverwriteExisting= */ false);
|
||||
S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPARMv8A,
|
||||
/* OverwriteExisting= */ false);
|
||||
break;
|
||||
|
||||
// FPV5_D16 is identical to FP_ARMV8 except for the number of D registers, so
|
||||
// uses the FP_ARMV8_D16 build attribute.
|
||||
case ARM::FK_FPV5_SP_D16:
|
||||
case ARM::FK_FPV5_D16:
|
||||
setAttributeItem(ARMBuildAttrs::FP_arch,
|
||||
ARMBuildAttrs::AllowFPARMv8B,
|
||||
/* OverwriteExisting= */ false);
|
||||
S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPARMv8B,
|
||||
/* OverwriteExisting= */ false);
|
||||
break;
|
||||
|
||||
case ARM::FK_NEON:
|
||||
setAttributeItem(ARMBuildAttrs::FP_arch,
|
||||
ARMBuildAttrs::AllowFPv3A,
|
||||
/* OverwriteExisting= */ false);
|
||||
setAttributeItem(ARMBuildAttrs::Advanced_SIMD_arch,
|
||||
ARMBuildAttrs::AllowNeon,
|
||||
/* OverwriteExisting= */ false);
|
||||
S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv3A,
|
||||
/* OverwriteExisting= */ false);
|
||||
S.setAttributeItem(ARMBuildAttrs::Advanced_SIMD_arch,
|
||||
ARMBuildAttrs::AllowNeon,
|
||||
/* OverwriteExisting= */ false);
|
||||
break;
|
||||
|
||||
case ARM::FK_NEON_FP16:
|
||||
setAttributeItem(ARMBuildAttrs::FP_arch,
|
||||
ARMBuildAttrs::AllowFPv3A,
|
||||
/* OverwriteExisting= */ false);
|
||||
setAttributeItem(ARMBuildAttrs::Advanced_SIMD_arch,
|
||||
ARMBuildAttrs::AllowNeon,
|
||||
/* OverwriteExisting= */ false);
|
||||
setAttributeItem(ARMBuildAttrs::FP_HP_extension,
|
||||
ARMBuildAttrs::AllowHPFP,
|
||||
/* OverwriteExisting= */ false);
|
||||
S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv3A,
|
||||
/* OverwriteExisting= */ false);
|
||||
S.setAttributeItem(ARMBuildAttrs::Advanced_SIMD_arch,
|
||||
ARMBuildAttrs::AllowNeon,
|
||||
/* OverwriteExisting= */ false);
|
||||
S.setAttributeItem(ARMBuildAttrs::FP_HP_extension, ARMBuildAttrs::AllowHPFP,
|
||||
/* OverwriteExisting= */ false);
|
||||
break;
|
||||
|
||||
case ARM::FK_NEON_VFPV4:
|
||||
setAttributeItem(ARMBuildAttrs::FP_arch,
|
||||
ARMBuildAttrs::AllowFPv4A,
|
||||
/* OverwriteExisting= */ false);
|
||||
setAttributeItem(ARMBuildAttrs::Advanced_SIMD_arch,
|
||||
ARMBuildAttrs::AllowNeon2,
|
||||
/* OverwriteExisting= */ false);
|
||||
S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv4A,
|
||||
/* OverwriteExisting= */ false);
|
||||
S.setAttributeItem(ARMBuildAttrs::Advanced_SIMD_arch,
|
||||
ARMBuildAttrs::AllowNeon2,
|
||||
/* OverwriteExisting= */ false);
|
||||
break;
|
||||
|
||||
case ARM::FK_NEON_FP_ARMV8:
|
||||
case ARM::FK_CRYPTO_NEON_FP_ARMV8:
|
||||
setAttributeItem(ARMBuildAttrs::FP_arch,
|
||||
ARMBuildAttrs::AllowFPARMv8A,
|
||||
/* OverwriteExisting= */ false);
|
||||
S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPARMv8A,
|
||||
/* OverwriteExisting= */ false);
|
||||
// 'Advanced_SIMD_arch' must be emitted not here, but within
|
||||
// ARMAsmPrinter::emitAttributes(), depending on hasV8Ops() and hasV8_1a()
|
||||
break;
|
||||
@ -1049,39 +935,8 @@ void ARMTargetELFStreamer::emitFPUDefaultAttributes() {
|
||||
}
|
||||
}
|
||||
|
||||
size_t ARMTargetELFStreamer::calculateContentSize() const {
|
||||
size_t Result = 0;
|
||||
for (size_t i = 0; i < Contents.size(); ++i) {
|
||||
AttributeItem item = Contents[i];
|
||||
switch (item.Type) {
|
||||
case AttributeItem::HiddenAttribute:
|
||||
break;
|
||||
case AttributeItem::NumericAttribute:
|
||||
Result += getULEB128Size(item.Tag);
|
||||
Result += getULEB128Size(item.IntValue);
|
||||
break;
|
||||
case AttributeItem::TextAttribute:
|
||||
Result += getULEB128Size(item.Tag);
|
||||
Result += item.StringValue.size() + 1; // string + '\0'
|
||||
break;
|
||||
case AttributeItem::NumericAndTextAttributes:
|
||||
Result += getULEB128Size(item.Tag);
|
||||
Result += getULEB128Size(item.IntValue);
|
||||
Result += item.StringValue.size() + 1; // string + '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
void ARMTargetELFStreamer::finishAttributeSection() {
|
||||
// <format-version>
|
||||
// [ <section-length> "vendor-name"
|
||||
// [ <file-tag> <size> <attribute>*
|
||||
// | <section-tag> <size> <section-number>* 0 <attribute>*
|
||||
// | <symbol-tag> <size> <symbol-number>* 0 <attribute>*
|
||||
// ]+
|
||||
// ]*
|
||||
ARMELFStreamer &S = getStreamer();
|
||||
|
||||
if (FPU != ARM::FK_INVALID)
|
||||
emitFPUDefaultAttributes();
|
||||
@ -1089,63 +944,30 @@ void ARMTargetELFStreamer::finishAttributeSection() {
|
||||
if (Arch != ARM::ArchKind::INVALID)
|
||||
emitArchDefaultAttributes();
|
||||
|
||||
if (Contents.empty())
|
||||
if (S.Contents.empty())
|
||||
return;
|
||||
|
||||
llvm::sort(Contents, AttributeItem::LessTag);
|
||||
auto LessTag = [](const MCELFStreamer::AttributeItem &LHS,
|
||||
const MCELFStreamer::AttributeItem &RHS) -> bool {
|
||||
// The conformance tag must be emitted first when serialised into an
|
||||
// object file. Specifically, the addenda to the ARM ABI states that
|
||||
// (2.3.7.4):
|
||||
//
|
||||
// "To simplify recognition by consumers in the common case of claiming
|
||||
// conformity for the whole file, this tag should be emitted first in a
|
||||
// file-scope sub-subsection of the first public subsection of the
|
||||
// attributes section."
|
||||
//
|
||||
// So it is special-cased in this comparison predicate when the
|
||||
// attributes are sorted in finishAttributeSection().
|
||||
return (RHS.Tag != ARMBuildAttrs::conformance) &&
|
||||
((LHS.Tag == ARMBuildAttrs::conformance) || (LHS.Tag < RHS.Tag));
|
||||
};
|
||||
llvm::sort(S.Contents, LessTag);
|
||||
|
||||
ARMELFStreamer &Streamer = getStreamer();
|
||||
S.emitAttributesSection(CurrentVendor, ".ARM.attributes",
|
||||
ELF::SHT_ARM_ATTRIBUTES, AttributeSection);
|
||||
|
||||
// Switch to .ARM.attributes section
|
||||
if (AttributeSection) {
|
||||
Streamer.SwitchSection(AttributeSection);
|
||||
} else {
|
||||
AttributeSection = Streamer.getContext().getELFSection(
|
||||
".ARM.attributes", ELF::SHT_ARM_ATTRIBUTES, 0);
|
||||
Streamer.SwitchSection(AttributeSection);
|
||||
|
||||
// Format version
|
||||
Streamer.emitInt8(0x41);
|
||||
}
|
||||
|
||||
// Vendor size + Vendor name + '\0'
|
||||
const size_t VendorHeaderSize = 4 + CurrentVendor.size() + 1;
|
||||
|
||||
// Tag + Tag Size
|
||||
const size_t TagHeaderSize = 1 + 4;
|
||||
|
||||
const size_t ContentsSize = calculateContentSize();
|
||||
|
||||
Streamer.emitInt32(VendorHeaderSize + TagHeaderSize + ContentsSize);
|
||||
Streamer.emitBytes(CurrentVendor);
|
||||
Streamer.emitInt8(0); // '\0'
|
||||
|
||||
Streamer.emitInt8(ARMBuildAttrs::File);
|
||||
Streamer.emitInt32(TagHeaderSize + ContentsSize);
|
||||
|
||||
// Size should have been accounted for already, now
|
||||
// emit each field as its type (ULEB or String)
|
||||
for (size_t i = 0; i < Contents.size(); ++i) {
|
||||
AttributeItem item = Contents[i];
|
||||
Streamer.emitULEB128IntValue(item.Tag);
|
||||
switch (item.Type) {
|
||||
default: llvm_unreachable("Invalid attribute type");
|
||||
case AttributeItem::NumericAttribute:
|
||||
Streamer.emitULEB128IntValue(item.IntValue);
|
||||
break;
|
||||
case AttributeItem::TextAttribute:
|
||||
Streamer.emitBytes(item.StringValue);
|
||||
Streamer.emitInt8(0); // '\0'
|
||||
break;
|
||||
case AttributeItem::NumericAndTextAttributes:
|
||||
Streamer.emitULEB128IntValue(item.IntValue);
|
||||
Streamer.emitBytes(item.StringValue);
|
||||
Streamer.emitInt8(0); // '\0'
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Contents.clear();
|
||||
FPU = ARM::FK_INVALID;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user