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 // If A is undefined and B is defined, we should emit ADD/SUB for A-B.
243 // Unfortunately, A may be defined later, but this requiresFixups call has to
244 // eagerly make a decision. For now, emit ADD/SUB unless A is .L*. This
245 // heuristic handles many temporary label differences for .debug_* and
246 // .apple_types sections.
247 //
248 // TODO Implement delayed relocation decision.
249 if (!A.isInSection() && !A.isTemporary() && B.isInSection())
250 return true;
251
252 // Support cross-section symbolic differences ...
253 return A.isInSection() && B.isInSection() &&
254 A.getSection().getName() != B.getSection().getName();
255 }
256
reset()257 void RISCVELFStreamer::reset() {
258 static_cast<RISCVTargetStreamer *>(getTargetStreamer())->reset();
259 MCELFStreamer::reset();
260 }
261
emitValueImpl(const MCExpr * Value,unsigned Size,SMLoc Loc)262 void RISCVELFStreamer::emitValueImpl(const MCExpr *Value, unsigned Size,
263 SMLoc Loc) {
264 const MCExpr *A, *B;
265 if (!requiresFixups(getContext(), Value, A, B))
266 return MCELFStreamer::emitValueImpl(Value, Size, Loc);
267
268 MCStreamer::emitValueImpl(Value, Size, Loc);
269
270 MCDataFragment *DF = getOrCreateDataFragment();
271 flushPendingLabels(DF, DF->getContents().size());
272 MCDwarfLineEntry::make(this, getCurrentSectionOnly());
273
274 unsigned Add, Sub;
275 std::tie(Add, Sub) = getRelocPairForSize(Size);
276
277 DF->getFixups().push_back(MCFixup::create(
278 DF->getContents().size(), A, static_cast<MCFixupKind>(Add), Loc));
279 DF->getFixups().push_back(MCFixup::create(
280 DF->getContents().size(), B, static_cast<MCFixupKind>(Sub), Loc));
281
282 DF->getContents().resize(DF->getContents().size() + Size, 0);
283 }
284
285 namespace llvm {
createRISCVELFStreamer(MCContext & C,std::unique_ptr<MCAsmBackend> MAB,std::unique_ptr<MCObjectWriter> MOW,std::unique_ptr<MCCodeEmitter> MCE,bool RelaxAll)286 MCELFStreamer *createRISCVELFStreamer(MCContext &C,
287 std::unique_ptr<MCAsmBackend> MAB,
288 std::unique_ptr<MCObjectWriter> MOW,
289 std::unique_ptr<MCCodeEmitter> MCE,
290 bool RelaxAll) {
291 RISCVELFStreamer *S =
292 new RISCVELFStreamer(C, std::move(MAB), std::move(MOW), std::move(MCE));
293 S->getAssembler().setRelaxAll(RelaxAll);
294 return S;
295 }
296 } // namespace llvm
297