106c3fb27SDimitry Andric //===-- RISCVELFStreamer.cpp - RISC-V ELF Target Streamer Methods ---------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
906c3fb27SDimitry Andric // This file provides RISC-V specific target streamer methods.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric
130b57cec5SDimitry Andric #include "RISCVELFStreamer.h"
14e8d8bef9SDimitry Andric #include "RISCVAsmBackend.h"
15e8d8bef9SDimitry Andric #include "RISCVBaseInfo.h"
160b57cec5SDimitry Andric #include "RISCVMCTargetDesc.h"
170b57cec5SDimitry Andric #include "llvm/BinaryFormat/ELF.h"
18fe6060f1SDimitry Andric #include "llvm/MC/MCAsmBackend.h"
1981ad6265SDimitry Andric #include "llvm/MC/MCAssembler.h"
20fe6060f1SDimitry Andric #include "llvm/MC/MCCodeEmitter.h"
215ffd83dbSDimitry Andric #include "llvm/MC/MCContext.h"
22fe6060f1SDimitry Andric #include "llvm/MC/MCObjectWriter.h"
235ffd83dbSDimitry Andric #include "llvm/MC/MCSectionELF.h"
240b57cec5SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
25fe6060f1SDimitry Andric #include "llvm/MC/MCValue.h"
265ffd83dbSDimitry Andric #include "llvm/Support/LEB128.h"
275ffd83dbSDimitry Andric #include "llvm/Support/RISCVAttributes.h"
280b57cec5SDimitry Andric
290b57cec5SDimitry Andric using namespace llvm;
300b57cec5SDimitry Andric
310b57cec5SDimitry Andric // This part is for ELF object output.
RISCVTargetELFStreamer(MCStreamer & S,const MCSubtargetInfo & STI)320b57cec5SDimitry Andric RISCVTargetELFStreamer::RISCVTargetELFStreamer(MCStreamer &S,
330b57cec5SDimitry Andric const MCSubtargetInfo &STI)
343a079333SDimitry Andric : RISCVTargetStreamer(S), CurrentVendor("riscv") {
350b57cec5SDimitry Andric MCAssembler &MCA = getStreamer().getAssembler();
360b57cec5SDimitry Andric const FeatureBitset &Features = STI.getFeatureBits();
370b57cec5SDimitry Andric auto &MAB = static_cast<RISCVAsmBackend &>(MCA.getBackend());
3881ad6265SDimitry Andric setTargetABI(RISCVABI::computeTargetABI(STI.getTargetTriple(), Features,
3981ad6265SDimitry Andric MAB.getTargetOptions().getABIName()));
403a079333SDimitry Andric setFlagsFromFeatures(STI);
41297eecfbSDimitry Andric // `j label` in `.option norelax; j label; .option relax; ...; label:` needs a
42297eecfbSDimitry Andric // relocation to ensure the jump target is correct after linking. This is due
43297eecfbSDimitry Andric // to a limitation that shouldForceRelocation has to make the decision upfront
44297eecfbSDimitry Andric // without knowing a possibly future .option relax. When RISCVAsmParser is used,
45297eecfbSDimitry Andric // its ParseInstruction may call setForceRelocs as well.
46297eecfbSDimitry Andric if (STI.hasFeature(RISCV::FeatureRelax))
47297eecfbSDimitry Andric static_cast<RISCVAsmBackend &>(MAB).setForceRelocs();
480b57cec5SDimitry Andric }
490b57cec5SDimitry Andric
getStreamer()50bdd1243dSDimitry Andric RISCVELFStreamer &RISCVTargetELFStreamer::getStreamer() {
51bdd1243dSDimitry Andric return static_cast<RISCVELFStreamer &>(Streamer);
520b57cec5SDimitry Andric }
530b57cec5SDimitry Andric
emitDirectiveOptionPush()540b57cec5SDimitry Andric void RISCVTargetELFStreamer::emitDirectiveOptionPush() {}
emitDirectiveOptionPop()550b57cec5SDimitry Andric void RISCVTargetELFStreamer::emitDirectiveOptionPop() {}
emitDirectiveOptionPIC()565ffd83dbSDimitry Andric void RISCVTargetELFStreamer::emitDirectiveOptionPIC() {}
emitDirectiveOptionNoPIC()575ffd83dbSDimitry Andric void RISCVTargetELFStreamer::emitDirectiveOptionNoPIC() {}
emitDirectiveOptionRVC()580b57cec5SDimitry Andric void RISCVTargetELFStreamer::emitDirectiveOptionRVC() {}
emitDirectiveOptionNoRVC()590b57cec5SDimitry Andric void RISCVTargetELFStreamer::emitDirectiveOptionNoRVC() {}
emitDirectiveOptionRelax()600b57cec5SDimitry Andric void RISCVTargetELFStreamer::emitDirectiveOptionRelax() {}
emitDirectiveOptionNoRelax()610b57cec5SDimitry Andric void RISCVTargetELFStreamer::emitDirectiveOptionNoRelax() {}
625ffd83dbSDimitry Andric
emitAttribute(unsigned Attribute,unsigned Value)635ffd83dbSDimitry Andric void RISCVTargetELFStreamer::emitAttribute(unsigned Attribute, unsigned Value) {
6406c3fb27SDimitry Andric getStreamer().setAttributeItem(Attribute, Value, /*OverwriteExisting=*/true);
655ffd83dbSDimitry Andric }
665ffd83dbSDimitry Andric
emitTextAttribute(unsigned Attribute,StringRef String)675ffd83dbSDimitry Andric void RISCVTargetELFStreamer::emitTextAttribute(unsigned Attribute,
685ffd83dbSDimitry Andric StringRef String) {
6906c3fb27SDimitry Andric getStreamer().setAttributeItem(Attribute, String, /*OverwriteExisting=*/true);
705ffd83dbSDimitry Andric }
715ffd83dbSDimitry Andric
emitIntTextAttribute(unsigned Attribute,unsigned IntValue,StringRef StringValue)725ffd83dbSDimitry Andric void RISCVTargetELFStreamer::emitIntTextAttribute(unsigned Attribute,
735ffd83dbSDimitry Andric unsigned IntValue,
745ffd83dbSDimitry Andric StringRef StringValue) {
7506c3fb27SDimitry Andric getStreamer().setAttributeItems(Attribute, IntValue, StringValue,
765ffd83dbSDimitry Andric /*OverwriteExisting=*/true);
775ffd83dbSDimitry Andric }
785ffd83dbSDimitry Andric
finishAttributeSection()795ffd83dbSDimitry Andric void RISCVTargetELFStreamer::finishAttributeSection() {
8006c3fb27SDimitry Andric RISCVELFStreamer &S = getStreamer();
8106c3fb27SDimitry Andric if (S.Contents.empty())
825ffd83dbSDimitry Andric return;
835ffd83dbSDimitry Andric
8406c3fb27SDimitry Andric S.emitAttributesSection(CurrentVendor, ".riscv.attributes",
8506c3fb27SDimitry Andric ELF::SHT_RISCV_ATTRIBUTES, AttributeSection);
865ffd83dbSDimitry Andric }
87fe6060f1SDimitry Andric
finish()8881ad6265SDimitry Andric void RISCVTargetELFStreamer::finish() {
8981ad6265SDimitry Andric RISCVTargetStreamer::finish();
90*0fca6ea1SDimitry Andric ELFObjectWriter &W = getStreamer().getWriter();
9181ad6265SDimitry Andric RISCVABI::ABI ABI = getTargetABI();
9281ad6265SDimitry Andric
93*0fca6ea1SDimitry Andric unsigned EFlags = W.getELFHeaderEFlags();
9481ad6265SDimitry Andric
953a079333SDimitry Andric if (hasRVC())
9681ad6265SDimitry Andric EFlags |= ELF::EF_RISCV_RVC;
973a079333SDimitry Andric if (hasTSO())
98bdd1243dSDimitry Andric EFlags |= ELF::EF_RISCV_TSO;
9981ad6265SDimitry Andric
10081ad6265SDimitry Andric switch (ABI) {
10181ad6265SDimitry Andric case RISCVABI::ABI_ILP32:
10281ad6265SDimitry Andric case RISCVABI::ABI_LP64:
10381ad6265SDimitry Andric break;
10481ad6265SDimitry Andric case RISCVABI::ABI_ILP32F:
10581ad6265SDimitry Andric case RISCVABI::ABI_LP64F:
10681ad6265SDimitry Andric EFlags |= ELF::EF_RISCV_FLOAT_ABI_SINGLE;
10781ad6265SDimitry Andric break;
10881ad6265SDimitry Andric case RISCVABI::ABI_ILP32D:
10981ad6265SDimitry Andric case RISCVABI::ABI_LP64D:
11081ad6265SDimitry Andric EFlags |= ELF::EF_RISCV_FLOAT_ABI_DOUBLE;
11181ad6265SDimitry Andric break;
11281ad6265SDimitry Andric case RISCVABI::ABI_ILP32E:
11306c3fb27SDimitry Andric case RISCVABI::ABI_LP64E:
11481ad6265SDimitry Andric EFlags |= ELF::EF_RISCV_RVE;
11581ad6265SDimitry Andric break;
11681ad6265SDimitry Andric case RISCVABI::ABI_Unknown:
11781ad6265SDimitry Andric llvm_unreachable("Improperly initialised target ABI");
11881ad6265SDimitry Andric }
11981ad6265SDimitry Andric
120*0fca6ea1SDimitry Andric W.setELFHeaderEFlags(EFlags);
12181ad6265SDimitry Andric }
12281ad6265SDimitry Andric
reset()12381ad6265SDimitry Andric void RISCVTargetELFStreamer::reset() {
12481ad6265SDimitry Andric AttributeSection = nullptr;
12581ad6265SDimitry Andric }
12681ad6265SDimitry Andric
emitDirectiveVariantCC(MCSymbol & Symbol)127bdd1243dSDimitry Andric void RISCVTargetELFStreamer::emitDirectiveVariantCC(MCSymbol &Symbol) {
128bdd1243dSDimitry Andric getStreamer().getAssembler().registerSymbol(Symbol);
129bdd1243dSDimitry Andric cast<MCSymbolELF>(Symbol).setOther(ELF::STO_RISCV_VARIANT_CC);
130bdd1243dSDimitry Andric }
131bdd1243dSDimitry Andric
reset()132bdd1243dSDimitry Andric void RISCVELFStreamer::reset() {
13381ad6265SDimitry Andric static_cast<RISCVTargetStreamer *>(getTargetStreamer())->reset();
13481ad6265SDimitry Andric MCELFStreamer::reset();
1355f757f3fSDimitry Andric LastMappingSymbols.clear();
1365f757f3fSDimitry Andric LastEMS = EMS_None;
1375f757f3fSDimitry Andric }
1385f757f3fSDimitry Andric
emitDataMappingSymbol()1395f757f3fSDimitry Andric void RISCVELFStreamer::emitDataMappingSymbol() {
1405f757f3fSDimitry Andric if (LastEMS == EMS_Data)
1415f757f3fSDimitry Andric return;
1425f757f3fSDimitry Andric emitMappingSymbol("$d");
1435f757f3fSDimitry Andric LastEMS = EMS_Data;
1445f757f3fSDimitry Andric }
1455f757f3fSDimitry Andric
emitInstructionsMappingSymbol()1465f757f3fSDimitry Andric void RISCVELFStreamer::emitInstructionsMappingSymbol() {
1475f757f3fSDimitry Andric if (LastEMS == EMS_Instructions)
1485f757f3fSDimitry Andric return;
1495f757f3fSDimitry Andric emitMappingSymbol("$x");
1505f757f3fSDimitry Andric LastEMS = EMS_Instructions;
1515f757f3fSDimitry Andric }
1525f757f3fSDimitry Andric
emitMappingSymbol(StringRef Name)1535f757f3fSDimitry Andric void RISCVELFStreamer::emitMappingSymbol(StringRef Name) {
154*0fca6ea1SDimitry Andric auto *Symbol = cast<MCSymbolELF>(getContext().createLocalSymbol(Name));
1555f757f3fSDimitry Andric emitLabel(Symbol);
1565f757f3fSDimitry Andric Symbol->setType(ELF::STT_NOTYPE);
1575f757f3fSDimitry Andric Symbol->setBinding(ELF::STB_LOCAL);
1585f757f3fSDimitry Andric }
1595f757f3fSDimitry Andric
changeSection(MCSection * Section,uint32_t Subsection)160*0fca6ea1SDimitry Andric void RISCVELFStreamer::changeSection(MCSection *Section, uint32_t Subsection) {
1615f757f3fSDimitry Andric // We have to keep track of the mapping symbol state of any sections we
1625f757f3fSDimitry Andric // use. Each one should start off as EMS_None, which is provided as the
1635f757f3fSDimitry Andric // default constructor by DenseMap::lookup.
1645f757f3fSDimitry Andric LastMappingSymbols[getPreviousSection().first] = LastEMS;
1655f757f3fSDimitry Andric LastEMS = LastMappingSymbols.lookup(Section);
1665f757f3fSDimitry Andric
1675f757f3fSDimitry Andric MCELFStreamer::changeSection(Section, Subsection);
1685f757f3fSDimitry Andric }
1695f757f3fSDimitry Andric
emitInstruction(const MCInst & Inst,const MCSubtargetInfo & STI)1705f757f3fSDimitry Andric void RISCVELFStreamer::emitInstruction(const MCInst &Inst,
1715f757f3fSDimitry Andric const MCSubtargetInfo &STI) {
1725f757f3fSDimitry Andric emitInstructionsMappingSymbol();
1735f757f3fSDimitry Andric MCELFStreamer::emitInstruction(Inst, STI);
1745f757f3fSDimitry Andric }
1755f757f3fSDimitry Andric
emitBytes(StringRef Data)1765f757f3fSDimitry Andric void RISCVELFStreamer::emitBytes(StringRef Data) {
1775f757f3fSDimitry Andric emitDataMappingSymbol();
1785f757f3fSDimitry Andric MCELFStreamer::emitBytes(Data);
1795f757f3fSDimitry Andric }
1805f757f3fSDimitry Andric
emitFill(const MCExpr & NumBytes,uint64_t FillValue,SMLoc Loc)1815f757f3fSDimitry Andric void RISCVELFStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue,
1825f757f3fSDimitry Andric SMLoc Loc) {
1835f757f3fSDimitry Andric emitDataMappingSymbol();
1845f757f3fSDimitry Andric MCELFStreamer::emitFill(NumBytes, FillValue, Loc);
1855f757f3fSDimitry Andric }
1865f757f3fSDimitry Andric
emitValueImpl(const MCExpr * Value,unsigned Size,SMLoc Loc)1875f757f3fSDimitry Andric void RISCVELFStreamer::emitValueImpl(const MCExpr *Value, unsigned Size,
1885f757f3fSDimitry Andric SMLoc Loc) {
1895f757f3fSDimitry Andric emitDataMappingSymbol();
1905f757f3fSDimitry Andric MCELFStreamer::emitValueImpl(Value, Size, Loc);
191fe6060f1SDimitry Andric }
192fe6060f1SDimitry Andric
193fe6060f1SDimitry Andric namespace llvm {
createRISCVELFStreamer(MCContext & C,std::unique_ptr<MCAsmBackend> MAB,std::unique_ptr<MCObjectWriter> MOW,std::unique_ptr<MCCodeEmitter> MCE)194fe6060f1SDimitry Andric MCELFStreamer *createRISCVELFStreamer(MCContext &C,
195fe6060f1SDimitry Andric std::unique_ptr<MCAsmBackend> MAB,
196fe6060f1SDimitry Andric std::unique_ptr<MCObjectWriter> MOW,
197*0fca6ea1SDimitry Andric std::unique_ptr<MCCodeEmitter> MCE) {
198fe6060f1SDimitry Andric RISCVELFStreamer *S =
199fe6060f1SDimitry Andric new RISCVELFStreamer(C, std::move(MAB), std::move(MOW), std::move(MCE));
200fe6060f1SDimitry Andric return S;
201fe6060f1SDimitry Andric }
202fe6060f1SDimitry Andric } // namespace llvm
203