1//===-- RISCVELFStreamer.cpp - RISC-V ELF Target Streamer Methods ---------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file provides RISC-V specific target streamer methods.
10//
11//===----------------------------------------------------------------------===//
12
13#include "RISCVELFStreamer.h"
14#include "RISCVAsmBackend.h"
15#include "RISCVBaseInfo.h"
16#include "RISCVMCTargetDesc.h"
17#include "llvm/BinaryFormat/ELF.h"
18#include "llvm/MC/MCAsmBackend.h"
19#include "llvm/MC/MCAssembler.h"
20#include "llvm/MC/MCCodeEmitter.h"
21#include "llvm/MC/MCContext.h"
22#include "llvm/MC/MCELFObjectWriter.h"
23#include "llvm/MC/MCSubtargetInfo.h"
24
25using namespace llvm;
26
27// This part is for ELF object output.
28RISCVTargetELFStreamer::RISCVTargetELFStreamer(MCStreamer &S,
29 const MCSubtargetInfo &STI)
30 : RISCVTargetStreamer(S), CurrentVendor("riscv") {
31 MCAssembler &MCA = getStreamer().getAssembler();
32 const FeatureBitset &Features = STI.getFeatureBits();
33 auto &MAB = static_cast<RISCVAsmBackend &>(MCA.getBackend());
34 setTargetABI(RISCVABI::computeTargetABI(TT: STI.getTargetTriple(), FeatureBits: Features,
35 ABIName: MAB.getTargetOptions().getABIName()));
36 setFlagsFromFeatures(STI);
37}
38
39RISCVELFStreamer &RISCVTargetELFStreamer::getStreamer() {
40 return static_cast<RISCVELFStreamer &>(Streamer);
41}
42
43void RISCVTargetELFStreamer::emitDirectiveOptionExact() {}
44void RISCVTargetELFStreamer::emitDirectiveOptionNoExact() {}
45void RISCVTargetELFStreamer::emitDirectiveOptionPIC() {}
46void RISCVTargetELFStreamer::emitDirectiveOptionNoPIC() {}
47void RISCVTargetELFStreamer::emitDirectiveOptionPop() {}
48void RISCVTargetELFStreamer::emitDirectiveOptionPush() {}
49void RISCVTargetELFStreamer::emitDirectiveOptionRelax() {}
50void RISCVTargetELFStreamer::emitDirectiveOptionNoRelax() {}
51void RISCVTargetELFStreamer::emitDirectiveOptionRVC() {}
52void RISCVTargetELFStreamer::emitDirectiveOptionNoRVC() {}
53
54void RISCVTargetELFStreamer::emitAttribute(unsigned Attribute, unsigned Value) {
55 getStreamer().setAttributeItem(Attribute, Value, /*OverwriteExisting=*/true);
56}
57
58void RISCVTargetELFStreamer::emitTextAttribute(unsigned Attribute,
59 StringRef String) {
60 getStreamer().setAttributeItem(Attribute, Value: String, /*OverwriteExisting=*/true);
61}
62
63void RISCVTargetELFStreamer::emitIntTextAttribute(unsigned Attribute,
64 unsigned IntValue,
65 StringRef StringValue) {
66 getStreamer().setAttributeItems(Attribute, IntValue, StringValue,
67 /*OverwriteExisting=*/true);
68}
69
70void RISCVTargetELFStreamer::finishAttributeSection() {
71 RISCVELFStreamer &S = getStreamer();
72 if (S.Contents.empty())
73 return;
74
75 S.emitAttributesSection(Vendor: CurrentVendor, Section: ".riscv.attributes",
76 Type: ELF::SHT_RISCV_ATTRIBUTES, AttributeSection);
77}
78
79void RISCVTargetELFStreamer::finish() {
80 RISCVTargetStreamer::finish();
81 ELFObjectWriter &W = getStreamer().getWriter();
82 RISCVABI::ABI ABI = getTargetABI();
83
84 unsigned EFlags = W.getELFHeaderEFlags();
85
86 if (hasRVC())
87 EFlags |= ELF::EF_RISCV_RVC;
88 if (hasTSO())
89 EFlags |= ELF::EF_RISCV_TSO;
90
91 switch (ABI) {
92 case RISCVABI::ABI_ILP32:
93 case RISCVABI::ABI_LP64:
94 break;
95 case RISCVABI::ABI_ILP32F:
96 case RISCVABI::ABI_LP64F:
97 EFlags |= ELF::EF_RISCV_FLOAT_ABI_SINGLE;
98 break;
99 case RISCVABI::ABI_ILP32D:
100 case RISCVABI::ABI_LP64D:
101 EFlags |= ELF::EF_RISCV_FLOAT_ABI_DOUBLE;
102 break;
103 case RISCVABI::ABI_ILP32E:
104 case RISCVABI::ABI_LP64E:
105 EFlags |= ELF::EF_RISCV_RVE;
106 break;
107 case RISCVABI::ABI_Unknown:
108 llvm_unreachable("Improperly initialised target ABI");
109 }
110
111 W.setELFHeaderEFlags(EFlags);
112}
113
114void RISCVTargetELFStreamer::reset() {
115 AttributeSection = nullptr;
116}
117
118void RISCVTargetELFStreamer::emitDirectiveVariantCC(MCSymbol &Symbol) {
119 getStreamer().getAssembler().registerSymbol(Symbol);
120 cast<MCSymbolELF>(Val&: Symbol).setOther(ELF::STO_RISCV_VARIANT_CC);
121}
122
123void RISCVELFStreamer::reset() {
124 static_cast<RISCVTargetStreamer *>(getTargetStreamer())->reset();
125 MCELFStreamer::reset();
126 LastMappingSymbols.clear();
127 LastEMS = EMS_None;
128}
129
130void RISCVELFStreamer::emitDataMappingSymbol() {
131 if (LastEMS == EMS_Data)
132 return;
133 emitMappingSymbol(Name: "$d");
134 LastEMS = EMS_Data;
135}
136
137void RISCVELFStreamer::emitInstructionsMappingSymbol() {
138 if (LastEMS == EMS_Instructions)
139 return;
140 emitMappingSymbol(Name: "$x");
141 LastEMS = EMS_Instructions;
142}
143
144void RISCVELFStreamer::emitMappingSymbol(StringRef Name) {
145 auto *Symbol = cast<MCSymbolELF>(Val: getContext().createLocalSymbol(Name));
146 emitLabel(Symbol);
147 Symbol->setType(ELF::STT_NOTYPE);
148 Symbol->setBinding(ELF::STB_LOCAL);
149}
150
151void RISCVELFStreamer::changeSection(MCSection *Section, uint32_t Subsection) {
152 // We have to keep track of the mapping symbol state of any sections we
153 // use. Each one should start off as EMS_None, which is provided as the
154 // default constructor by DenseMap::lookup.
155 LastMappingSymbols[getPreviousSection().first] = LastEMS;
156 LastEMS = LastMappingSymbols.lookup(Val: Section);
157
158 MCELFStreamer::changeSection(Section, Subsection);
159}
160
161void RISCVELFStreamer::emitInstruction(const MCInst &Inst,
162 const MCSubtargetInfo &STI) {
163 emitInstructionsMappingSymbol();
164 MCELFStreamer::emitInstruction(Inst, STI);
165}
166
167void RISCVELFStreamer::emitBytes(StringRef Data) {
168 emitDataMappingSymbol();
169 MCELFStreamer::emitBytes(Data);
170}
171
172void RISCVELFStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue,
173 SMLoc Loc) {
174 emitDataMappingSymbol();
175 MCELFStreamer::emitFill(NumBytes, FillValue, Loc);
176}
177
178void RISCVELFStreamer::emitValueImpl(const MCExpr *Value, unsigned Size,
179 SMLoc Loc) {
180 emitDataMappingSymbol();
181 MCELFStreamer::emitValueImpl(Value, Size, Loc);
182}
183
184MCStreamer *llvm::createRISCVELFStreamer(const Triple &, MCContext &C,
185 std::unique_ptr<MCAsmBackend> &&MAB,
186 std::unique_ptr<MCObjectWriter> &&MOW,
187 std::unique_ptr<MCCodeEmitter> &&MCE) {
188 return new RISCVELFStreamer(C, std::move(MAB), std::move(MOW),
189 std::move(MCE));
190}
191