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 auto &MAB = static_cast<RISCVAsmBackend &>(MCA.getBackend());
33 StringRef ABIName = MAB.getTargetOptions().getABIName();
34 // We have to recompute the ABI rather than casting STI to RISCVSubtarget
35 // since MC tools like llvm-mc call this when STI is MCSubtargetInfo instead.
36 // Using RISCVSubtarget requires a TargetMachine, which the MC-only tools
37 // deliberately don't link.
38 // TODO: Might be cleaner to have callers set the ABI instead of computing
39 // it twice which introduces a chance of it being out of sync.
40 if (auto ABIOrErr = RISCVABI::computeTargetABI(STI, ABIName)) {
41 setTargetABI(*ABIOrErr);
42 } else {
43 // Do not set TargetABI here if invalid: RISCVSubtarget/RISCVAsmPrinter
44 // (in codegen) or RISCVAsmParser::onBeginOfFile() (in llvm-mc) will
45 // resolve or diagnose it with proper contexts.
46 consumeError(Err: ABIOrErr.takeError());
47 }
48 setFlagsFromFeatures(STI);
49
50 // Compute the initial ISA string. This serves two purposes:
51 // 1. Deduplication: subsequent .option arch/rvc/norvc directives compare
52 // against ArchString to avoid propagating redundant ISA updates.
53 // 2. Initial symbol: seed the streamer's active ISA so a "$x<ArchString>"
54 // mapping symbol is emitted before the first instruction, recording
55 // the full ISA in the object even when no .option directive is present.
56 if (auto ParseResult = RISCVFeatures::parseFeatureBits(STI)) {
57 InitialArchString = (*ParseResult)->toString();
58 ArchString = InitialArchString;
59 getStreamer().setMappingSymbolArch(ArchString);
60 }
61}
62
63RISCVELFStreamer::RISCVELFStreamer(MCContext &C,
64 std::unique_ptr<MCAsmBackend> MAB,
65 std::unique_ptr<MCObjectWriter> MOW,
66 std::unique_ptr<MCCodeEmitter> MCE)
67 : MCELFStreamer(C, std::move(MAB), std::move(MOW), std::move(MCE)) {}
68
69RISCVELFStreamer &RISCVTargetELFStreamer::getStreamer() {
70 return static_cast<RISCVELFStreamer &>(Streamer);
71}
72
73void RISCVTargetELFStreamer::setArchString(StringRef Arch) {
74 if (Arch == ArchString)
75 return;
76 ArchString = std::string(Arch);
77 getStreamer().setMappingSymbolArch(Arch);
78}
79
80void RISCVTargetELFStreamer::emitDirectiveOptionPush() {
81 ArchStringStack.push_back(Elt: ArchString);
82}
83
84void RISCVTargetELFStreamer::emitDirectiveOptionPop() {
85 if (!ArchStringStack.empty())
86 setArchString(ArchStringStack.pop_back_val());
87}
88
89void RISCVTargetELFStreamer::emitDirectiveOptionExact() {}
90void RISCVTargetELFStreamer::emitDirectiveOptionNoExact() {}
91void RISCVTargetELFStreamer::emitDirectiveOptionPIC() {}
92void RISCVTargetELFStreamer::emitDirectiveOptionNoPIC() {}
93void RISCVTargetELFStreamer::emitDirectiveOptionRelax() {}
94void RISCVTargetELFStreamer::emitDirectiveOptionNoRelax() {}
95void RISCVTargetELFStreamer::emitDirectiveOptionRVC() {}
96void RISCVTargetELFStreamer::emitDirectiveOptionNoRVC() {}
97
98void RISCVTargetELFStreamer::emitAttribute(unsigned Attribute, unsigned Value) {
99 getStreamer().setAttributeItem(Attribute, Value, /*OverwriteExisting=*/true);
100}
101
102void RISCVTargetELFStreamer::emitTextAttribute(unsigned Attribute,
103 StringRef String) {
104 getStreamer().setAttributeItem(Attribute, Value: String, /*OverwriteExisting=*/true);
105}
106
107void RISCVTargetELFStreamer::emitIntTextAttribute(unsigned Attribute,
108 unsigned IntValue,
109 StringRef StringValue) {
110 getStreamer().setAttributeItems(Attribute, IntValue, StringValue,
111 /*OverwriteExisting=*/true);
112}
113
114void RISCVTargetELFStreamer::finishAttributeSection() {
115 RISCVELFStreamer &S = getStreamer();
116 if (S.Contents.empty())
117 return;
118
119 S.emitAttributesSection(Vendor: CurrentVendor, Section: ".riscv.attributes",
120 Type: ELF::SHT_RISCV_ATTRIBUTES, AttributeSection);
121}
122
123void RISCVTargetELFStreamer::finish() {
124 RISCVTargetStreamer::finish();
125 ELFObjectWriter &W = getStreamer().getWriter();
126 RISCVABI::ABI ABI = getTargetABI();
127
128 unsigned EFlags = W.getELFHeaderEFlags();
129
130 if (hasRVC())
131 EFlags |= ELF::EF_RISCV_RVC;
132 if (hasTSO())
133 EFlags |= ELF::EF_RISCV_TSO;
134
135 switch (ABI) {
136 case RISCVABI::ABI_ILP32:
137 case RISCVABI::ABI_IL32PC64:
138 case RISCVABI::ABI_LP64:
139 case RISCVABI::ABI_L64PC128:
140 break;
141 case RISCVABI::ABI_ILP32F:
142 case RISCVABI::ABI_IL32PC64F:
143 case RISCVABI::ABI_LP64F:
144 case RISCVABI::ABI_L64PC128F:
145 EFlags |= ELF::EF_RISCV_FLOAT_ABI_SINGLE;
146 break;
147 case RISCVABI::ABI_ILP32D:
148 case RISCVABI::ABI_IL32PC64D:
149 case RISCVABI::ABI_LP64D:
150 case RISCVABI::ABI_L64PC128D:
151 EFlags |= ELF::EF_RISCV_FLOAT_ABI_DOUBLE;
152 break;
153 case RISCVABI::ABI_ILP32E:
154 case RISCVABI::ABI_IL32PC64E:
155 case RISCVABI::ABI_LP64E:
156 case RISCVABI::ABI_CHERIOT:
157 EFlags |= ELF::EF_RISCV_RVE;
158 break;
159 case RISCVABI::ABI_Unknown:
160 llvm_unreachable("Improperly initialised target ABI");
161 }
162
163 W.setELFHeaderEFlags(EFlags);
164}
165
166void RISCVTargetELFStreamer::reset() {
167 AttributeSection = nullptr;
168 ArchString = InitialArchString;
169 ArchStringStack.clear();
170 // Re-seed the streamer's active ISA so the first instruction after reset
171 // still records the full ISA via "$x<ISA>", matching the behaviour set up
172 // in the constructor.
173 if (!InitialArchString.empty())
174 getStreamer().setMappingSymbolArch(InitialArchString);
175}
176
177void RISCVTargetELFStreamer::emitDirectiveVariantCC(MCSymbol &Symbol) {
178 getStreamer().getAssembler().registerSymbol(Symbol);
179 static_cast<MCSymbolELF &>(Symbol).setOther(ELF::STO_RISCV_VARIANT_CC);
180}
181
182void RISCVELFStreamer::reset() {
183 MCELFStreamer::reset();
184 LastMappingSymbols.clear();
185 LastEMS = EMS_None;
186 MappingSymbolArch.clear();
187 LastEmittedArch.clear();
188 LastEmittedArchInSection.clear();
189 // Call target streamer reset last: it may call setMappingSymbolArch to
190 // re-seed the initial ISA after our state has been cleared.
191 static_cast<RISCVTargetStreamer *>(getTargetStreamer())->reset();
192}
193
194void RISCVELFStreamer::emitDataMappingSymbol() {
195 if (LastEMS == EMS_Data)
196 return;
197 emitMappingSymbol(Name: "$d");
198 LastEMS = EMS_Data;
199}
200
201void RISCVELFStreamer::emitInstructionsMappingSymbol() {
202 // Emit a mapping symbol at the start of each instruction run, and whenever
203 // the active ISA has changed since the last one emitted in this section.
204 // The symbol takes the form "$x<ISA>" when MappingSymbolArch is known, or
205 // plain "$x" as a fallback. The comparison with LastEmittedArch provides
206 // deduplication: repeating .option arch with the same ISA, or re-entering a
207 // section whose last mapping symbol already matches the active ISA, emits
208 // no redundant symbol.
209 bool NeedSymbol =
210 LastEMS != EMS_Instructions || LastEmittedArch != MappingSymbolArch;
211 if (NeedSymbol) {
212 if (MappingSymbolArch.empty())
213 emitMappingSymbol(Name: "$x");
214 else
215 emitMappingSymbol(Name: "$x" + MappingSymbolArch);
216 LastEmittedArch = MappingSymbolArch;
217 }
218 LastEMS = EMS_Instructions;
219}
220
221void RISCVELFStreamer::emitMappingSymbol(StringRef Name) {
222 auto *Symbol =
223 static_cast<MCSymbolELF *>(getContext().createLocalSymbol(Name));
224 emitLabel(Symbol);
225 Symbol->setType(ELF::STT_NOTYPE);
226 Symbol->setBinding(ELF::STB_LOCAL);
227}
228
229void RISCVELFStreamer::setMappingSymbolArch(StringRef Arch) {
230 MappingSymbolArch = std::string(Arch);
231}
232
233void RISCVELFStreamer::changeSection(MCSection *Section, uint32_t Subsection) {
234 // We have to keep track of the mapping symbol state of any sections we
235 // use. Each one should start off as EMS_None, which is provided as the
236 // default constructor by DenseMap::lookup. The last ISA suffix emitted in
237 // each section is also preserved so that re-entering a section only emits a
238 // new "$x<ISA>" symbol when the active ISA has actually changed.
239 const MCSection *Prev = getPreviousSection().first;
240 LastMappingSymbols[Prev] = LastEMS;
241 LastEmittedArchInSection[Prev] = LastEmittedArch;
242 LastEMS = LastMappingSymbols.lookup(Val: Section);
243 auto It = LastEmittedArchInSection.find(Val: Section);
244 LastEmittedArch = It != LastEmittedArchInSection.end() ? It->second : "";
245
246 MCELFStreamer::changeSection(Section, Subsection);
247}
248
249void RISCVELFStreamer::emitInstruction(const MCInst &Inst,
250 const MCSubtargetInfo &STI) {
251 emitInstructionsMappingSymbol();
252 MCELFStreamer::emitInstruction(Inst, STI);
253}
254
255void RISCVELFStreamer::emitBytes(StringRef Data) {
256 emitDataMappingSymbol();
257 MCELFStreamer::emitBytes(Data);
258}
259
260void RISCVELFStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue,
261 SMLoc Loc) {
262 emitDataMappingSymbol();
263 MCELFStreamer::emitFill(NumBytes, FillValue, Loc);
264}
265
266void RISCVELFStreamer::emitValueImpl(const MCExpr *Value, unsigned Size,
267 SMLoc Loc) {
268 emitDataMappingSymbol();
269 MCELFStreamer::emitValueImpl(Value, Size, Loc);
270}
271
272MCStreamer *llvm::createRISCVELFStreamer(const Triple &, MCContext &C,
273 std::unique_ptr<MCAsmBackend> &&MAB,
274 std::unique_ptr<MCObjectWriter> &&MOW,
275 std::unique_ptr<MCCodeEmitter> &&MCE) {
276 return new RISCVELFStreamer(C, std::move(MAB), std::move(MOW),
277 std::move(MCE));
278}
279
280void RISCVTargetELFStreamer::emitNoteGnuPropertySection(
281 const uint32_t Feature1And) {
282 MCStreamer &OutStreamer = getStreamer();
283 MCContext &Ctx = OutStreamer.getContext();
284
285 const Triple &Triple = Ctx.getTargetTriple();
286 Align NoteAlign;
287 uint64_t DescSize;
288 if (Triple.isArch64Bit()) {
289 NoteAlign = Align(8);
290 DescSize = 16;
291 } else {
292 assert(Triple.isArch32Bit());
293 NoteAlign = Align(4);
294 DescSize = 12;
295 }
296
297 assert(Ctx.getObjectFileType() == MCContext::Environment::IsELF);
298 MCSection *const NoteSection =
299 Ctx.getELFSection(Section: ".note.gnu.property", Type: ELF::SHT_NOTE, Flags: ELF::SHF_ALLOC);
300 OutStreamer.pushSection();
301 OutStreamer.switchSection(Section: NoteSection);
302
303 // Emit the note header
304 OutStreamer.emitValueToAlignment(Alignment: NoteAlign);
305 OutStreamer.emitIntValue(Value: 4, Size: 4); // n_namsz
306 OutStreamer.emitIntValue(Value: DescSize, Size: 4); // n_descsz
307 OutStreamer.emitIntValue(Value: ELF::NT_GNU_PROPERTY_TYPE_0, Size: 4); // n_type
308 OutStreamer.emitBytes(Data: StringRef("GNU", 4)); // n_name
309
310 // Emit n_desc field
311
312 // Emit the feature_1_and property
313 OutStreamer.emitIntValue(Value: ELF::GNU_PROPERTY_RISCV_FEATURE_1_AND, Size: 4); // pr_type
314 OutStreamer.emitIntValue(Value: 4, Size: 4); // pr_datasz
315 OutStreamer.emitIntValue(Value: Feature1And, Size: 4); // pr_data
316 OutStreamer.emitValueToAlignment(Alignment: NoteAlign); // pr_padding
317
318 OutStreamer.popSection();
319}
320