//===-- 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 "MCTargetDesc/RISCVAsmBackend.h" #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), CurrentVendor("riscv") { MCAssembler &MCA = getStreamer().getAssembler(); const FeatureBitset &Features = STI.getFeatureBits(); auto &MAB = static_cast(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(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; }