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 MCELFStreamer &RISCVTargetELFStreamer::getStreamer() {
43 return static_cast<MCELFStreamer &>(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
161 switch (ABI) {
162 case RISCVABI::ABI_ILP32:
163 case RISCVABI::ABI_LP64:
164 break;
165 case RISCVABI::ABI_ILP32F:
166 case RISCVABI::ABI_LP64F:
167 EFlags |= ELF::EF_RISCV_FLOAT_ABI_SINGLE;
168 break;
169 case RISCVABI::ABI_ILP32D:
170 case RISCVABI::ABI_LP64D:
171 EFlags |= ELF::EF_RISCV_FLOAT_ABI_DOUBLE;
172 break;
173 case RISCVABI::ABI_ILP32E:
174 EFlags |= ELF::EF_RISCV_RVE;
175 break;
176 case RISCVABI::ABI_Unknown:
177 llvm_unreachable("Improperly initialised target ABI");
178 }
179
180 MCA.setELFHeaderEFlags(EFlags);
181 }
182
reset()183 void RISCVTargetELFStreamer::reset() {
184 AttributeSection = nullptr;
185 Contents.clear();
186 }
187
188 namespace {
189 class RISCVELFStreamer : public MCELFStreamer {
getRelocPairForSize(unsigned Size)190 static std::pair<unsigned, unsigned> getRelocPairForSize(unsigned Size) {
191 switch (Size) {
192 default:
193 llvm_unreachable("unsupported fixup size");
194 case 1:
195 return std::make_pair(RISCV::fixup_riscv_add_8, RISCV::fixup_riscv_sub_8);
196 case 2:
197 return std::make_pair(RISCV::fixup_riscv_add_16,
198 RISCV::fixup_riscv_sub_16);
199 case 4:
200 return std::make_pair(RISCV::fixup_riscv_add_32,
201 RISCV::fixup_riscv_sub_32);
202 case 8:
203 return std::make_pair(RISCV::fixup_riscv_add_64,
204 RISCV::fixup_riscv_sub_64);
205 }
206 }
207
requiresFixups(MCContext & C,const MCExpr * Value,const MCExpr * & LHS,const MCExpr * & RHS)208 static bool requiresFixups(MCContext &C, const MCExpr *Value,
209 const MCExpr *&LHS, const MCExpr *&RHS) {
210 auto IsMetadataOrEHFrameSection = [](const MCSection &S) -> bool {
211 // Additionally check .apple_names/.apple_types. They are fixed-size and
212 // do not need fixups. llvm-dwarfdump --apple-names does not process
213 // R_RISCV_{ADD,SUB}32 in them.
214 return S.getKind().isMetadata() || S.getName() == ".eh_frame" ||
215 S.getName() == ".apple_names" || S.getName() == ".apple_types";
216 };
217
218 const auto *MBE = dyn_cast<MCBinaryExpr>(Value);
219 if (MBE == nullptr)
220 return false;
221
222 MCValue E;
223 if (!Value->evaluateAsRelocatable(E, nullptr, nullptr))
224 return false;
225 if (E.getSymA() == nullptr || E.getSymB() == nullptr)
226 return false;
227
228 const auto &A = E.getSymA()->getSymbol();
229 const auto &B = E.getSymB()->getSymbol();
230
231 LHS =
232 MCBinaryExpr::create(MCBinaryExpr::Add, MCSymbolRefExpr::create(&A, C),
233 MCConstantExpr::create(E.getConstant(), C), C);
234 RHS = E.getSymB();
235
236 // TODO: when available, R_RISCV_n_PCREL should be preferred.
237
238 // Avoid pairwise relocations for symbolic difference in debug and .eh_frame
239 if (A.isInSection())
240 return !IsMetadataOrEHFrameSection(A.getSection());
241 if (B.isInSection())
242 return !IsMetadataOrEHFrameSection(B.getSection());
243 // as well as for absolute symbols.
244 return !A.getName().empty() || !B.getName().empty();
245 }
246
reset()247 void reset() override {
248 static_cast<RISCVTargetStreamer *>(getTargetStreamer())->reset();
249 MCELFStreamer::reset();
250 }
251
252 public:
RISCVELFStreamer(MCContext & C,std::unique_ptr<MCAsmBackend> MAB,std::unique_ptr<MCObjectWriter> MOW,std::unique_ptr<MCCodeEmitter> MCE)253 RISCVELFStreamer(MCContext &C, std::unique_ptr<MCAsmBackend> MAB,
254 std::unique_ptr<MCObjectWriter> MOW,
255 std::unique_ptr<MCCodeEmitter> MCE)
256 : MCELFStreamer(C, std::move(MAB), std::move(MOW), std::move(MCE)) {}
257
emitValueImpl(const MCExpr * Value,unsigned Size,SMLoc Loc)258 void emitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) override {
259 const MCExpr *A, *B;
260 if (!requiresFixups(getContext(), Value, A, B))
261 return MCELFStreamer::emitValueImpl(Value, Size, Loc);
262
263 MCStreamer::emitValueImpl(Value, Size, Loc);
264
265 MCDataFragment *DF = getOrCreateDataFragment();
266 flushPendingLabels(DF, DF->getContents().size());
267 MCDwarfLineEntry::make(this, getCurrentSectionOnly());
268
269 unsigned Add, Sub;
270 std::tie(Add, Sub) = getRelocPairForSize(Size);
271
272 DF->getFixups().push_back(MCFixup::create(
273 DF->getContents().size(), A, static_cast<MCFixupKind>(Add), Loc));
274 DF->getFixups().push_back(MCFixup::create(
275 DF->getContents().size(), B, static_cast<MCFixupKind>(Sub), Loc));
276
277 DF->getContents().resize(DF->getContents().size() + Size, 0);
278 }
279 };
280 } // namespace
281
282 namespace llvm {
createRISCVELFStreamer(MCContext & C,std::unique_ptr<MCAsmBackend> MAB,std::unique_ptr<MCObjectWriter> MOW,std::unique_ptr<MCCodeEmitter> MCE,bool RelaxAll)283 MCELFStreamer *createRISCVELFStreamer(MCContext &C,
284 std::unique_ptr<MCAsmBackend> MAB,
285 std::unique_ptr<MCObjectWriter> MOW,
286 std::unique_ptr<MCCodeEmitter> MCE,
287 bool RelaxAll) {
288 RISCVELFStreamer *S =
289 new RISCVELFStreamer(C, std::move(MAB), std::move(MOW), std::move(MCE));
290 S->getAssembler().setRelaxAll(RelaxAll);
291 return S;
292 }
293 } // namespace llvm
294