diff options
Diffstat (limited to 'llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp')
-rw-r--r-- | llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp | 103 |
1 files changed, 102 insertions, 1 deletions
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp index 40fa195f37909..079dc919928ad 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp @@ -15,14 +15,18 @@ #include "RISCVMCTargetDesc.h" #include "Utils/RISCVBaseInfo.h" #include "llvm/BinaryFormat/ELF.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Support/LEB128.h" +#include "llvm/Support/RISCVAttributes.h" using namespace llvm; // This part is for ELF object output. RISCVTargetELFStreamer::RISCVTargetELFStreamer(MCStreamer &S, const MCSubtargetInfo &STI) - : RISCVTargetStreamer(S) { + : RISCVTargetStreamer(S), CurrentVendor("riscv") { MCAssembler &MCA = getStreamer().getAssembler(); const FeatureBitset &Features = STI.getFeatureBits(); auto &MAB = static_cast<RISCVAsmBackend &>(MCA.getBackend()); @@ -62,7 +66,104 @@ MCELFStreamer &RISCVTargetELFStreamer::getStreamer() { void RISCVTargetELFStreamer::emitDirectiveOptionPush() {} void RISCVTargetELFStreamer::emitDirectiveOptionPop() {} +void RISCVTargetELFStreamer::emitDirectiveOptionPIC() {} +void RISCVTargetELFStreamer::emitDirectiveOptionNoPIC() {} void RISCVTargetELFStreamer::emitDirectiveOptionRVC() {} void RISCVTargetELFStreamer::emitDirectiveOptionNoRVC() {} void RISCVTargetELFStreamer::emitDirectiveOptionRelax() {} void RISCVTargetELFStreamer::emitDirectiveOptionNoRelax() {} + +void RISCVTargetELFStreamer::emitAttribute(unsigned Attribute, unsigned Value) { + setAttributeItem(Attribute, Value, /*OverwriteExisting=*/true); +} + +void RISCVTargetELFStreamer::emitTextAttribute(unsigned Attribute, + StringRef String) { + setAttributeItem(Attribute, String, /*OverwriteExisting=*/true); +} + +void RISCVTargetELFStreamer::emitIntTextAttribute(unsigned Attribute, + unsigned IntValue, + StringRef StringValue) { + setAttributeItems(Attribute, IntValue, StringValue, + /*OverwriteExisting=*/true); +} + +void RISCVTargetELFStreamer::finishAttributeSection() { + if (Contents.empty()) + return; + + if (AttributeSection) { + Streamer.SwitchSection(AttributeSection); + } else { + MCAssembler &MCA = getStreamer().getAssembler(); + AttributeSection = MCA.getContext().getELFSection( + ".riscv.attributes", ELF::SHT_RISCV_ATTRIBUTES, 0); + Streamer.SwitchSection(AttributeSection); + + Streamer.emitInt8(ELFAttrs::Format_Version); + } + + // 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(ELFAttrs::File); + Streamer.emitInt32(TagHeaderSize + ContentsSize); + + // Size should have been accounted for already, now + // emit each field as its type (ULEB or String). + for (AttributeItem item : Contents) { + Streamer.emitULEB128IntValue(item.Tag); + switch (item.Type) { + default: + llvm_unreachable("Invalid attribute type"); + case AttributeType::Numeric: + Streamer.emitULEB128IntValue(item.IntValue); + break; + case AttributeType::Text: + Streamer.emitBytes(item.StringValue); + Streamer.emitInt8(0); // '\0' + break; + case AttributeType::NumericAndText: + Streamer.emitULEB128IntValue(item.IntValue); + Streamer.emitBytes(item.StringValue); + Streamer.emitInt8(0); // '\0' + break; + } + } + + Contents.clear(); +} + +size_t RISCVTargetELFStreamer::calculateContentSize() const { + size_t Result = 0; + for (AttributeItem item : Contents) { + switch (item.Type) { + case AttributeType::Hidden: + break; + case AttributeType::Numeric: + Result += getULEB128Size(item.Tag); + Result += getULEB128Size(item.IntValue); + break; + case AttributeType::Text: + Result += getULEB128Size(item.Tag); + Result += item.StringValue.size() + 1; // string + '\0' + break; + case AttributeType::NumericAndText: + Result += getULEB128Size(item.Tag); + Result += getULEB128Size(item.IntValue); + Result += item.StringValue.size() + 1; // string + '\0'; + break; + } + } + return Result; +} |