| //===-- RISCVELFStreamer.cpp - RISCV ELF Target Streamer Methods ----------===// |
| // |
| // 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 provides RISCV specific target streamer methods. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "RISCVELFStreamer.h" |
| #include "RISCVAsmBackend.h" |
| #include "RISCVBaseInfo.h" |
| #include "RISCVMCTargetDesc.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), CurrentVendor("riscv") { |
| MCAssembler &MCA = getStreamer().getAssembler(); |
| const FeatureBitset &Features = STI.getFeatureBits(); |
| auto &MAB = static_cast<RISCVAsmBackend &>(MCA.getBackend()); |
| RISCVABI::ABI ABI = MAB.getTargetABI(); |
| assert(ABI != RISCVABI::ABI_Unknown && "Improperly initialised target ABI"); |
| |
| unsigned EFlags = MCA.getELFHeaderEFlags(); |
| |
| if (Features[RISCV::FeatureStdExtC]) |
| EFlags |= ELF::EF_RISCV_RVC; |
| |
| switch (ABI) { |
| case RISCVABI::ABI_ILP32: |
| case RISCVABI::ABI_LP64: |
| break; |
| case RISCVABI::ABI_ILP32F: |
| case RISCVABI::ABI_LP64F: |
| EFlags |= ELF::EF_RISCV_FLOAT_ABI_SINGLE; |
| break; |
| case RISCVABI::ABI_ILP32D: |
| case RISCVABI::ABI_LP64D: |
| EFlags |= ELF::EF_RISCV_FLOAT_ABI_DOUBLE; |
| break; |
| case RISCVABI::ABI_ILP32E: |
| EFlags |= ELF::EF_RISCV_RVE; |
| break; |
| case RISCVABI::ABI_Unknown: |
| llvm_unreachable("Improperly initialised target ABI"); |
| } |
| |
| MCA.setELFHeaderEFlags(EFlags); |
| } |
| |
| MCELFStreamer &RISCVTargetELFStreamer::getStreamer() { |
| return static_cast<MCELFStreamer &>(Streamer); |
| } |
| |
| 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; |
| } |