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"
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/MCObjectWriter.h"
23 #include "llvm/MC/MCSectionELF.h"
24 #include "llvm/MC/MCSubtargetInfo.h"
25 #include "llvm/MC/MCValue.h"
26 #include "llvm/Support/LEB128.h"
27 #include "llvm/Support/RISCVAttributes.h"
28
29 using namespace llvm;
30
31 // This part is for ELF object output.
RISCVTargetELFStreamer(MCStreamer & S,const MCSubtargetInfo & STI)32 RISCVTargetELFStreamer::RISCVTargetELFStreamer(MCStreamer &S,
33 const MCSubtargetInfo &STI)
34 : RISCVTargetStreamer(S), CurrentVendor("riscv"), STI(STI) {
35 MCAssembler &MCA = getStreamer().getAssembler();
36 const FeatureBitset &Features = STI.getFeatureBits();
37 auto &MAB = static_cast<RISCVAsmBackend &>(MCA.getBackend());
38 setTargetABI(RISCVABI::computeTargetABI(STI.getTargetTriple(), Features,
39 MAB.getTargetOptions().getABIName()));
40 }
41
getStreamer()42 RISCVELFStreamer &RISCVTargetELFStreamer::getStreamer() {
43 return static_cast<RISCVELFStreamer &>(Streamer);
44 }
45
emitDirectiveOptionPush()46 void RISCVTargetELFStreamer::emitDirectiveOptionPush() {}
emitDirectiveOptionPop()47 void RISCVTargetELFStreamer::emitDirectiveOptionPop() {}
emitDirectiveOptionPIC()48 void RISCVTargetELFStreamer::emitDirectiveOptionPIC() {}
emitDirectiveOptionNoPIC()49 void RISCVTargetELFStreamer::emitDirectiveOptionNoPIC() {}
emitDirectiveOptionRVC()50 void RISCVTargetELFStreamer::emitDirectiveOptionRVC() {}
emitDirectiveOptionNoRVC()51 void RISCVTargetELFStreamer::emitDirectiveOptionNoRVC() {}
emitDirectiveOptionRelax()52 void RISCVTargetELFStreamer::emitDirectiveOptionRelax() {}
emitDirectiveOptionNoRelax()53 void RISCVTargetELFStreamer::emitDirectiveOptionNoRelax() {}
54
emitAttribute(unsigned Attribute,unsigned Value)55 void RISCVTargetELFStreamer::emitAttribute(unsigned Attribute, unsigned Value) {
56 setAttributeItem(Attribute, Value, /*OverwriteExisting=*/true);
57 }
58
emitTextAttribute(unsigned Attribute,StringRef String)59 void RISCVTargetELFStreamer::emitTextAttribute(unsigned Attribute,
60 StringRef String) {
61 setAttributeItem(Attribute, String, /*OverwriteExisting=*/true);
62 }
63
emitIntTextAttribute(unsigned Attribute,unsigned IntValue,StringRef StringValue)64 void RISCVTargetELFStreamer::emitIntTextAttribute(unsigned Attribute,
65 unsigned IntValue,
66 StringRef StringValue) {
67 setAttributeItems(Attribute, IntValue, StringValue,
68 /*OverwriteExisting=*/true);
69 }
70
finishAttributeSection()71 void RISCVTargetELFStreamer::finishAttributeSection() {
72 if (Contents.empty())
73 return;
74
75 if (AttributeSection) {
76 Streamer.switchSection(AttributeSection);
77 } else {
78 MCAssembler &MCA = getStreamer().getAssembler();
79 AttributeSection = MCA.getContext().getELFSection(
80 ".riscv.attributes", ELF::SHT_RISCV_ATTRIBUTES, 0);
81 Streamer.switchSection(AttributeSection);
82
83 Streamer.emitInt8(ELFAttrs::Format_Version);
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
98 Streamer.emitInt8(ELFAttrs::File);
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) {
104 Streamer.emitULEB128IntValue(item.Tag);
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
calculateContentSize() const126 size_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
finish()150 void RISCVTargetELFStreamer::finish() {
151 RISCVTargetStreamer::finish();
152 MCAssembler &MCA = getStreamer().getAssembler();
153 const FeatureBitset &Features = STI.getFeatureBits();
154 RISCVABI::ABI ABI = getTargetABI();
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) {
164 case RISCVABI::ABI_ILP32:
165 case RISCVABI::ABI_LP64:
166 break;
167 case RISCVABI::ABI_ILP32F:
168 case RISCVABI::ABI_LP64F:
169 EFlags |= ELF::EF_RISCV_FLOAT_ABI_SINGLE;
170 break;
171 case RISCVABI::ABI_ILP32D:
172 case RISCVABI::ABI_LP64D:
173 EFlags |= ELF::EF_RISCV_FLOAT_ABI_DOUBLE;
174 break;
175 case RISCVABI::ABI_ILP32E:
176 EFlags |= ELF::EF_RISCV_RVE;
177 break;
178 case RISCVABI::ABI_Unknown:
179 llvm_unreachable("Improperly initialised target ABI");
180 }
181
182 MCA.setELFHeaderEFlags(EFlags);
183 }
184
reset()185 void RISCVTargetELFStreamer::reset() {
186 AttributeSection = nullptr;
187 Contents.clear();
188 }
189
emitDirectiveVariantCC(MCSymbol & Symbol)190 void RISCVTargetELFStreamer::emitDirectiveVariantCC(MCSymbol &Symbol) {
191 getStreamer().getAssembler().registerSymbol(Symbol);
192 cast<MCSymbolELF>(Symbol).setOther(ELF::STO_RISCV_VARIANT_CC);
193 }
194
195 std::pair<unsigned, unsigned>
getRelocPairForSize(unsigned Size)196 RISCVELFStreamer::getRelocPairForSize(unsigned Size) {
197 switch (Size) {
198 default:
199 llvm_unreachable("unsupported fixup size");
200 case 1:
201 return std::make_pair(RISCV::fixup_riscv_add_8, RISCV::fixup_riscv_sub_8);
202 case 2:
203 return std::make_pair(RISCV::fixup_riscv_add_16, RISCV::fixup_riscv_sub_16);
204 case 4:
205 return std::make_pair(RISCV::fixup_riscv_add_32, RISCV::fixup_riscv_sub_32);
206 case 8:
207 return std::make_pair(RISCV::fixup_riscv_add_64, RISCV::fixup_riscv_sub_64);
208 }
209 }
210
requiresFixups(MCContext & C,const MCExpr * Value,const MCExpr * & LHS,const MCExpr * & RHS)211 bool RISCVELFStreamer::requiresFixups(MCContext &C, const MCExpr *Value,
212 const MCExpr *&LHS, const MCExpr *&RHS) {
213 const auto *MBE = dyn_cast<MCBinaryExpr>(Value);
214 if (MBE == nullptr)
215 return false;
216
217 MCValue E;
218 if (!Value->evaluateAsRelocatable(E, nullptr, nullptr))
219 return false;
220 if (E.getSymA() == nullptr || E.getSymB() == nullptr)
221 return false;
222
223 const auto &A = E.getSymA()->getSymbol();
224 const auto &B = E.getSymB()->getSymbol();
225
226 LHS = MCBinaryExpr::create(MCBinaryExpr::Add, MCSymbolRefExpr::create(&A, C),
227 MCConstantExpr::create(E.getConstant(), C), C);
228 RHS = E.getSymB();
229
230 // If either symbol is in a text section, we need to delay the relocation
231 // evaluation as relaxation may alter the size of the symbol.
232 //
233 // Unfortunately, we cannot identify if the symbol was built with relaxation
234 // as we do not track the state per symbol or section. However, BFD will
235 // always emit the relocation and so we follow suit which avoids the need to
236 // track that information.
237 if (A.isInSection() && A.getSection().getKind().isText())
238 return true;
239 if (B.isInSection() && B.getSection().getKind().isText())
240 return true;
241
242 // Support cross-section symbolic differences ...
243 return A.isInSection() && B.isInSection() &&
244 A.getSection().getName() != B.getSection().getName();
245 }
246
reset()247 void RISCVELFStreamer::reset() {
248 static_cast<RISCVTargetStreamer *>(getTargetStreamer())->reset();
249 MCELFStreamer::reset();
250 }
251
emitValueImpl(const MCExpr * Value,unsigned Size,SMLoc Loc)252 void RISCVELFStreamer::emitValueImpl(const MCExpr *Value, unsigned Size,
253 SMLoc Loc) {
254 const MCExpr *A, *B;
255 if (!requiresFixups(getContext(), Value, A, B))
256 return MCELFStreamer::emitValueImpl(Value, Size, Loc);
257
258 MCStreamer::emitValueImpl(Value, Size, Loc);
259
260 MCDataFragment *DF = getOrCreateDataFragment();
261 flushPendingLabels(DF, DF->getContents().size());
262 MCDwarfLineEntry::make(this, getCurrentSectionOnly());
263
264 unsigned Add, Sub;
265 std::tie(Add, Sub) = getRelocPairForSize(Size);
266
267 DF->getFixups().push_back(MCFixup::create(
268 DF->getContents().size(), A, static_cast<MCFixupKind>(Add), Loc));
269 DF->getFixups().push_back(MCFixup::create(
270 DF->getContents().size(), B, static_cast<MCFixupKind>(Sub), Loc));
271
272 DF->getContents().resize(DF->getContents().size() + Size, 0);
273 }
274
275 namespace llvm {
createRISCVELFStreamer(MCContext & C,std::unique_ptr<MCAsmBackend> MAB,std::unique_ptr<MCObjectWriter> MOW,std::unique_ptr<MCCodeEmitter> MCE,bool RelaxAll)276 MCELFStreamer *createRISCVELFStreamer(MCContext &C,
277 std::unique_ptr<MCAsmBackend> MAB,
278 std::unique_ptr<MCObjectWriter> MOW,
279 std::unique_ptr<MCCodeEmitter> MCE,
280 bool RelaxAll) {
281 RISCVELFStreamer *S =
282 new RISCVELFStreamer(C, std::move(MAB), std::move(MOW), std::move(MCE));
283 S->getAssembler().setRelaxAll(RelaxAll);
284 return S;
285 }
286 } // namespace llvm
287