LLVM 17.0.0git
RISCVELFStreamer.cpp
Go to the documentation of this file.
1//===-- RISCVELFStreamer.cpp - RISCV 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 RISCV specific target streamer methods.
10//
11//===----------------------------------------------------------------------===//
12
13#include "RISCVELFStreamer.h"
14#include "RISCVAsmBackend.h"
15#include "RISCVBaseInfo.h"
16#include "RISCVMCTargetDesc.h"
19#include "llvm/MC/MCAssembler.h"
21#include "llvm/MC/MCContext.h"
25#include "llvm/MC/MCValue.h"
26#include "llvm/Support/LEB128.h"
28
29using namespace llvm;
30
31// This part is for ELF object output.
33 const MCSubtargetInfo &STI)
34 : RISCVTargetStreamer(S), CurrentVendor("riscv"), STI(STI) {
36 const FeatureBitset &Features = STI.getFeatureBits();
37 auto &MAB = static_cast<RISCVAsmBackend &>(MCA.getBackend());
39 MAB.getTargetOptions().getABIName()));
40}
41
43 return static_cast<RISCVELFStreamer &>(Streamer);
44}
45
54
55void RISCVTargetELFStreamer::emitAttribute(unsigned Attribute, unsigned Value) {
56 setAttributeItem(Attribute, Value, /*OverwriteExisting=*/true);
57}
58
59void RISCVTargetELFStreamer::emitTextAttribute(unsigned Attribute,
61 setAttributeItem(Attribute, String, /*OverwriteExisting=*/true);
62}
63
64void RISCVTargetELFStreamer::emitIntTextAttribute(unsigned Attribute,
65 unsigned IntValue,
66 StringRef StringValue) {
67 setAttributeItems(Attribute, IntValue, StringValue,
68 /*OverwriteExisting=*/true);
69}
70
71void RISCVTargetELFStreamer::finishAttributeSection() {
72 if (Contents.empty())
73 return;
74
75 if (AttributeSection) {
76 Streamer.switchSection(AttributeSection);
77 } else {
79 AttributeSection = MCA.getContext().getELFSection(
80 ".riscv.attributes", ELF::SHT_RISCV_ATTRIBUTES, 0);
81 Streamer.switchSection(AttributeSection);
82
84 }
85
86 // Vendor size + Vendor name + '\0'
87 const size_t VendorHeaderSize = 4 + CurrentVendor.size() + 1;
88
89 // Tag + Tag Size
90 const size_t TagHeaderSize = 1 + 4;
91
92 const size_t ContentsSize = calculateContentSize();
93
94 Streamer.emitInt32(VendorHeaderSize + TagHeaderSize + ContentsSize);
95 Streamer.emitBytes(CurrentVendor);
96 Streamer.emitInt8(0); // '\0'
97
99 Streamer.emitInt32(TagHeaderSize + ContentsSize);
100
101 // Size should have been accounted for already, now
102 // emit each field as its type (ULEB or String).
103 for (AttributeItem item : Contents) {
105 switch (item.Type) {
106 default:
107 llvm_unreachable("Invalid attribute type");
108 case AttributeType::Numeric:
109 Streamer.emitULEB128IntValue(item.IntValue);
110 break;
111 case AttributeType::Text:
112 Streamer.emitBytes(item.StringValue);
113 Streamer.emitInt8(0); // '\0'
114 break;
115 case AttributeType::NumericAndText:
116 Streamer.emitULEB128IntValue(item.IntValue);
117 Streamer.emitBytes(item.StringValue);
118 Streamer.emitInt8(0); // '\0'
119 break;
120 }
121 }
122
123 Contents.clear();
124}
125
126size_t RISCVTargetELFStreamer::calculateContentSize() const {
127 size_t Result = 0;
128 for (AttributeItem item : Contents) {
129 switch (item.Type) {
130 case AttributeType::Hidden:
131 break;
132 case AttributeType::Numeric:
133 Result += getULEB128Size(item.Tag);
134 Result += getULEB128Size(item.IntValue);
135 break;
136 case AttributeType::Text:
137 Result += getULEB128Size(item.Tag);
138 Result += item.StringValue.size() + 1; // string + '\0'
139 break;
140 case AttributeType::NumericAndText:
141 Result += getULEB128Size(item.Tag);
142 Result += getULEB128Size(item.IntValue);
143 Result += item.StringValue.size() + 1; // string + '\0';
144 break;
145 }
146 }
147 return Result;
148}
149
153 const FeatureBitset &Features = STI.getFeatureBits();
155
156 unsigned EFlags = MCA.getELFHeaderEFlags();
157
158 if (Features[RISCV::FeatureStdExtC])
159 EFlags |= ELF::EF_RISCV_RVC;
160 if (Features[RISCV::FeatureStdExtZtso])
161 EFlags |= ELF::EF_RISCV_TSO;
162
163 switch (ABI) {
166 break;
170 break;
174 break;
176 EFlags |= ELF::EF_RISCV_RVE;
177 break;
179 llvm_unreachable("Improperly initialised target ABI");
180 }
181
182 MCA.setELFHeaderEFlags(EFlags);
183}
184
185void RISCVTargetELFStreamer::reset() {
186 AttributeSection = nullptr;
187 Contents.clear();
188}
189
192 cast<MCSymbolELF>(Symbol).setOther(ELF::STO_RISCV_VARIANT_CC);
193}
194
195bool RISCVELFStreamer::requiresFixups(MCContext &C, const MCExpr *Value,
196 const MCExpr *&LHS, const MCExpr *&RHS) {
197 const auto *MBE = dyn_cast<MCBinaryExpr>(Value);
198 if (MBE == nullptr)
199 return false;
200
201 MCValue E;
202 if (!Value->evaluateAsRelocatable(E, nullptr, nullptr))
203 return false;
204 if (E.getSymA() == nullptr || E.getSymB() == nullptr)
205 return false;
206
207 const auto &A = E.getSymA()->getSymbol();
208 const auto &B = E.getSymB()->getSymbol();
209
211 MCConstantExpr::create(E.getConstant(), C), C);
212 RHS = E.getSymB();
213
214 // If either symbol is in a text section, we need to delay the relocation
215 // evaluation as relaxation may alter the size of the symbol.
216 //
217 // Unfortunately, we cannot identify if the symbol was built with relaxation
218 // as we do not track the state per symbol or section. However, BFD will
219 // always emit the relocation and so we follow suit which avoids the need to
220 // track that information.
221 if (A.isInSection() && A.getSection().getKind().isText())
222 return true;
223 if (B.isInSection() && B.getSection().getKind().isText())
224 return true;
225
226 // Support cross-section symbolic differences ...
227 return A.isInSection() && B.isInSection() &&
228 A.getSection().getName() != B.getSection().getName();
229}
230
231void RISCVELFStreamer::reset() {
232 static_cast<RISCVTargetStreamer *>(getTargetStreamer())->reset();
234}
235
237 SMLoc Loc) {
238 const MCExpr *A, *B;
239 if (!requiresFixups(getContext(), Value, A, B))
241
243
244 MCDataFragment *DF = getOrCreateDataFragment();
245 flushPendingLabels(DF, DF->getContents().size());
246 MCDwarfLineEntry::make(this, getCurrentSectionOnly());
247
248 MCFixupKind Add, Sub;
249 std::tie(Add, Sub) = RISCV::getRelocPairForSize(Size);
250
251 DF->getFixups().push_back(
252 MCFixup::create(DF->getContents().size(), A, Add, Loc));
253 DF->getFixups().push_back(
254 MCFixup::create(DF->getContents().size(), B, Sub, Loc));
255
256 DF->getContents().resize(DF->getContents().size() + Size, 0);
257}
258
259namespace llvm {
261 std::unique_ptr<MCAsmBackend> MAB,
262 std::unique_ptr<MCObjectWriter> MOW,
263 std::unique_ptr<MCCodeEmitter> MCE,
264 bool RelaxAll) {
266 new RISCVELFStreamer(C, std::move(MAB), std::move(MOW), std::move(MCE));
267 S->getAssembler().setRelaxAll(RelaxAll);
268 return S;
269}
270} // namespace llvm
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static RegisterPass< DebugifyFunctionPass > DF("debugify-function", "Attach debug info to a function")
uint64_t Size
Value * RHS
Value * LHS
void emitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) override
Emit the expression Value into the output as a native integer of the given Size bytes.
Container class for subtarget features.
MCContext & getContext() const
Definition: MCAssembler.h:321
void registerSymbol(const MCSymbol &Symbol, bool *Created=nullptr)
unsigned getELFHeaderEFlags() const
ELF e_header flags.
Definition: MCAssembler.h:276
MCAsmBackend & getBackend() const
Definition: MCAssembler.h:329
void setELFHeaderEFlags(unsigned Flags)
Definition: MCAssembler.h:277
void setRelaxAll(bool Value)
Definition: MCAssembler.h:358
static const MCBinaryExpr * create(Opcode Op, const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition: MCExpr.cpp:183
@ Add
Addition.
Definition: MCExpr.h:484
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition: MCExpr.cpp:194
Context object for machine code objects.
Definition: MCContext.h:76
MCSectionELF * getELFSection(const Twine &Section, unsigned Type, unsigned Flags)
Definition: MCContext.h:563
Fragment for data and encoded instructions.
Definition: MCFragment.h:241
static void make(MCStreamer *MCOS, MCSection *Section)
Definition: MCDwarf.cpp:91
void emitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc=SMLoc()) override
Emit the expression Value into the output as a native integer of the given Size bytes.
void reset() override
state management
Definition: MCELFStreamer.h:40
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:35
static MCFixup create(uint32_t Offset, const MCExpr *Value, MCFixupKind Kind, SMLoc Loc=SMLoc())
Definition: MCFixup.h:87
MCAssembler & getAssembler()
Streaming machine code generation interface.
Definition: MCStreamer.h:212
unsigned emitULEB128IntValue(uint64_t Value, unsigned PadTo=0)
Special case of EmitULEB128Value that avoids the client having to pass in a MCExpr for constant integ...
Definition: MCStreamer.cpp:162
virtual void switchSection(MCSection *Section, const MCExpr *Subsection=nullptr)
Set the current section where code is being emitted to Section.
void emitInt32(uint64_t Value)
Definition: MCStreamer.h:748
virtual void emitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc=SMLoc())
Emit the expression Value into the output as a native integer of the given Size bytes.
void emitInt8(uint64_t Value)
Definition: MCStreamer.h:746
virtual void emitBytes(StringRef Data)
Emit the bytes in Data into the output.
Generic base class for all target subtargets.
const Triple & getTargetTriple() const
const FeatureBitset & getFeatureBits() const
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
Definition: MCExpr.h:386
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
MCStreamer & Streamer
Definition: MCStreamer.h:95
This represents an "assembler immediate".
Definition: MCValue.h:36
void emitDirectiveOptionPop() override
void emitDirectiveOptionPush() override
void emitDirectiveOptionNoPIC() override
void emitDirectiveOptionNoRVC() override
RISCVTargetELFStreamer(MCStreamer &S, const MCSubtargetInfo &STI)
void emitDirectiveVariantCC(MCSymbol &Symbol) override
void emitDirectiveOptionRelax() override
RISCVELFStreamer & getStreamer()
void emitDirectiveOptionNoRelax() override
void emitDirectiveOptionPIC() override
void emitDirectiveOptionRVC() override
RISCVABI::ABI getTargetABI() const
void setTargetABI(RISCVABI::ABI ABI)
Represents a location in source code.
Definition: SMLoc.h:23
bool empty() const
Definition: SmallVector.h:94
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
constexpr size_t size() const
size - Get the string size.
Definition: StringRef.h:137
LLVM Value Representation.
Definition: Value.h:74
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
@ EF_RISCV_RVE
Definition: ELF.h:676
@ EF_RISCV_RVC
Definition: ELF.h:670
@ EF_RISCV_TSO
Definition: ELF.h:677
@ EF_RISCV_FLOAT_ABI_SINGLE
Definition: ELF.h:673
@ EF_RISCV_FLOAT_ABI_DOUBLE
Definition: ELF.h:674
@ SHT_RISCV_ATTRIBUTES
Definition: ELF.h:1068
@ STO_RISCV_VARIANT_CC
Definition: ELF.h:688
ABI computeTargetABI(const Triple &TT, FeatureBitset FeatureBits, StringRef ABIName)
static std::pair< MCFixupKind, MCFixupKind > getRelocPairForSize(unsigned Size)
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
MCFixupKind
Extensible enumeration to represent the type of a fixup.
Definition: MCFixup.h:21
unsigned getULEB128Size(uint64_t Value)
Utility function to get the size of the ULEB128-encoded value.
Definition: LEB128.cpp:19
@ Add
Sum of integers.
MCELFStreamer * createRISCVELFStreamer(MCContext &C, std::unique_ptr< MCAsmBackend > MAB, std::unique_ptr< MCObjectWriter > MOW, std::unique_ptr< MCCodeEmitter > MCE, bool RelaxAll)