1056d835fSShiva Chen //===-- RISCVELFStreamer.cpp - RISCV ELF Target Streamer Methods ----------===//
2056d835fSShiva Chen //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6056d835fSShiva Chen //
7056d835fSShiva Chen //===----------------------------------------------------------------------===//
8056d835fSShiva Chen //
9056d835fSShiva Chen // This file provides RISCV specific target streamer methods.
10056d835fSShiva Chen //
11056d835fSShiva Chen //===----------------------------------------------------------------------===//
12056d835fSShiva Chen
13056d835fSShiva Chen #include "RISCVELFStreamer.h"
14387d3c24SCraig Topper #include "RISCVAsmBackend.h"
15387d3c24SCraig Topper #include "RISCVBaseInfo.h"
16056d835fSShiva Chen #include "RISCVMCTargetDesc.h"
17056d835fSShiva Chen #include "llvm/BinaryFormat/ELF.h"
18bbea6425SSaleem Abdulrasool #include "llvm/MC/MCAsmBackend.h"
19ef736a1cSserge-sans-paille #include "llvm/MC/MCAssembler.h"
20bbea6425SSaleem Abdulrasool #include "llvm/MC/MCCodeEmitter.h"
21581ba352SKai Wang #include "llvm/MC/MCContext.h"
22bbea6425SSaleem Abdulrasool #include "llvm/MC/MCObjectWriter.h"
23581ba352SKai Wang #include "llvm/MC/MCSectionELF.h"
24056d835fSShiva Chen #include "llvm/MC/MCSubtargetInfo.h"
25bbea6425SSaleem Abdulrasool #include "llvm/MC/MCValue.h"
26581ba352SKai Wang #include "llvm/Support/LEB128.h"
27581ba352SKai Wang #include "llvm/Support/RISCVAttributes.h"
28056d835fSShiva Chen
29056d835fSShiva Chen using namespace llvm;
30056d835fSShiva Chen
31056d835fSShiva Chen // This part is for ELF object output.
RISCVTargetELFStreamer(MCStreamer & S,const MCSubtargetInfo & STI)32056d835fSShiva Chen RISCVTargetELFStreamer::RISCVTargetELFStreamer(MCStreamer &S,
33056d835fSShiva Chen const MCSubtargetInfo &STI)
34227496dcSluxufan : RISCVTargetStreamer(S), CurrentVendor("riscv"), STI(STI) {
35056d835fSShiva Chen MCAssembler &MCA = getStreamer().getAssembler();
36056d835fSShiva Chen const FeatureBitset &Features = STI.getFeatureBits();
37fea49571SAlex Bradbury auto &MAB = static_cast<RISCVAsmBackend &>(MCA.getBackend());
38227496dcSluxufan setTargetABI(RISCVABI::computeTargetABI(STI.getTargetTriple(), Features,
39227496dcSluxufan MAB.getTargetOptions().getABIName()));
40056d835fSShiva Chen }
41056d835fSShiva Chen
getStreamer()42056d835fSShiva Chen MCELFStreamer &RISCVTargetELFStreamer::getStreamer() {
43056d835fSShiva Chen return static_cast<MCELFStreamer &>(Streamer);
44056d835fSShiva Chen }
45bca0c3cdSAlex Bradbury
emitDirectiveOptionPush()46893e5bc7SAlex Bradbury void RISCVTargetELFStreamer::emitDirectiveOptionPush() {}
emitDirectiveOptionPop()47893e5bc7SAlex Bradbury void RISCVTargetELFStreamer::emitDirectiveOptionPop() {}
emitDirectiveOptionPIC()485f236864SRoger Ferrer Ibanez void RISCVTargetELFStreamer::emitDirectiveOptionPIC() {}
emitDirectiveOptionNoPIC()495f236864SRoger Ferrer Ibanez void RISCVTargetELFStreamer::emitDirectiveOptionNoPIC() {}
emitDirectiveOptionRVC()50bca0c3cdSAlex Bradbury void RISCVTargetELFStreamer::emitDirectiveOptionRVC() {}
emitDirectiveOptionNoRVC()51bca0c3cdSAlex Bradbury void RISCVTargetELFStreamer::emitDirectiveOptionNoRVC() {}
emitDirectiveOptionRelax()529c03e4caSAlex Bradbury void RISCVTargetELFStreamer::emitDirectiveOptionRelax() {}
emitDirectiveOptionNoRelax()539c03e4caSAlex Bradbury void RISCVTargetELFStreamer::emitDirectiveOptionNoRelax() {}
54581ba352SKai Wang
emitAttribute(unsigned Attribute,unsigned Value)55581ba352SKai Wang void RISCVTargetELFStreamer::emitAttribute(unsigned Attribute, unsigned Value) {
56581ba352SKai Wang setAttributeItem(Attribute, Value, /*OverwriteExisting=*/true);
57581ba352SKai Wang }
58581ba352SKai Wang
emitTextAttribute(unsigned Attribute,StringRef String)59581ba352SKai Wang void RISCVTargetELFStreamer::emitTextAttribute(unsigned Attribute,
60581ba352SKai Wang StringRef String) {
61581ba352SKai Wang setAttributeItem(Attribute, String, /*OverwriteExisting=*/true);
62581ba352SKai Wang }
63581ba352SKai Wang
emitIntTextAttribute(unsigned Attribute,unsigned IntValue,StringRef StringValue)64581ba352SKai Wang void RISCVTargetELFStreamer::emitIntTextAttribute(unsigned Attribute,
65581ba352SKai Wang unsigned IntValue,
66581ba352SKai Wang StringRef StringValue) {
67581ba352SKai Wang setAttributeItems(Attribute, IntValue, StringValue,
68581ba352SKai Wang /*OverwriteExisting=*/true);
69581ba352SKai Wang }
70581ba352SKai Wang
finishAttributeSection()71581ba352SKai Wang void RISCVTargetELFStreamer::finishAttributeSection() {
72581ba352SKai Wang if (Contents.empty())
73581ba352SKai Wang return;
74581ba352SKai Wang
75581ba352SKai Wang if (AttributeSection) {
76adf4142fSFangrui Song Streamer.switchSection(AttributeSection);
77581ba352SKai Wang } else {
78581ba352SKai Wang MCAssembler &MCA = getStreamer().getAssembler();
79581ba352SKai Wang AttributeSection = MCA.getContext().getELFSection(
80581ba352SKai Wang ".riscv.attributes", ELF::SHT_RISCV_ATTRIBUTES, 0);
81adf4142fSFangrui Song Streamer.switchSection(AttributeSection);
82581ba352SKai Wang
83581ba352SKai Wang Streamer.emitInt8(ELFAttrs::Format_Version);
84581ba352SKai Wang }
85581ba352SKai Wang
86581ba352SKai Wang // Vendor size + Vendor name + '\0'
87581ba352SKai Wang const size_t VendorHeaderSize = 4 + CurrentVendor.size() + 1;
88581ba352SKai Wang
89581ba352SKai Wang // Tag + Tag Size
90581ba352SKai Wang const size_t TagHeaderSize = 1 + 4;
91581ba352SKai Wang
92581ba352SKai Wang const size_t ContentsSize = calculateContentSize();
93581ba352SKai Wang
94581ba352SKai Wang Streamer.emitInt32(VendorHeaderSize + TagHeaderSize + ContentsSize);
95581ba352SKai Wang Streamer.emitBytes(CurrentVendor);
96581ba352SKai Wang Streamer.emitInt8(0); // '\0'
97581ba352SKai Wang
98581ba352SKai Wang Streamer.emitInt8(ELFAttrs::File);
99581ba352SKai Wang Streamer.emitInt32(TagHeaderSize + ContentsSize);
100581ba352SKai Wang
101581ba352SKai Wang // Size should have been accounted for already, now
102581ba352SKai Wang // emit each field as its type (ULEB or String).
103581ba352SKai Wang for (AttributeItem item : Contents) {
104581ba352SKai Wang Streamer.emitULEB128IntValue(item.Tag);
105581ba352SKai Wang switch (item.Type) {
106581ba352SKai Wang default:
107581ba352SKai Wang llvm_unreachable("Invalid attribute type");
108581ba352SKai Wang case AttributeType::Numeric:
109581ba352SKai Wang Streamer.emitULEB128IntValue(item.IntValue);
110581ba352SKai Wang break;
111581ba352SKai Wang case AttributeType::Text:
112581ba352SKai Wang Streamer.emitBytes(item.StringValue);
113581ba352SKai Wang Streamer.emitInt8(0); // '\0'
114581ba352SKai Wang break;
115581ba352SKai Wang case AttributeType::NumericAndText:
116581ba352SKai Wang Streamer.emitULEB128IntValue(item.IntValue);
117581ba352SKai Wang Streamer.emitBytes(item.StringValue);
118581ba352SKai Wang Streamer.emitInt8(0); // '\0'
119581ba352SKai Wang break;
120581ba352SKai Wang }
121581ba352SKai Wang }
122581ba352SKai Wang
123581ba352SKai Wang Contents.clear();
124581ba352SKai Wang }
125581ba352SKai Wang
calculateContentSize() const126581ba352SKai Wang size_t RISCVTargetELFStreamer::calculateContentSize() const {
127581ba352SKai Wang size_t Result = 0;
128581ba352SKai Wang for (AttributeItem item : Contents) {
129581ba352SKai Wang switch (item.Type) {
130581ba352SKai Wang case AttributeType::Hidden:
131581ba352SKai Wang break;
132581ba352SKai Wang case AttributeType::Numeric:
133581ba352SKai Wang Result += getULEB128Size(item.Tag);
134581ba352SKai Wang Result += getULEB128Size(item.IntValue);
135581ba352SKai Wang break;
136581ba352SKai Wang case AttributeType::Text:
137581ba352SKai Wang Result += getULEB128Size(item.Tag);
138581ba352SKai Wang Result += item.StringValue.size() + 1; // string + '\0'
139581ba352SKai Wang break;
140581ba352SKai Wang case AttributeType::NumericAndText:
141581ba352SKai Wang Result += getULEB128Size(item.Tag);
142581ba352SKai Wang Result += getULEB128Size(item.IntValue);
143581ba352SKai Wang Result += item.StringValue.size() + 1; // string + '\0';
144581ba352SKai Wang break;
145581ba352SKai Wang }
146581ba352SKai Wang }
147581ba352SKai Wang return Result;
148581ba352SKai Wang }
149bbea6425SSaleem Abdulrasool
finish()150227496dcSluxufan void RISCVTargetELFStreamer::finish() {
151227496dcSluxufan RISCVTargetStreamer::finish();
152227496dcSluxufan MCAssembler &MCA = getStreamer().getAssembler();
153227496dcSluxufan const FeatureBitset &Features = STI.getFeatureBits();
154227496dcSluxufan RISCVABI::ABI ABI = getTargetABI();
155227496dcSluxufan
156227496dcSluxufan unsigned EFlags = MCA.getELFHeaderEFlags();
157227496dcSluxufan
158227496dcSluxufan if (Features[RISCV::FeatureStdExtC])
159227496dcSluxufan EFlags |= ELF::EF_RISCV_RVC;
160227496dcSluxufan
161227496dcSluxufan switch (ABI) {
162227496dcSluxufan case RISCVABI::ABI_ILP32:
163227496dcSluxufan case RISCVABI::ABI_LP64:
164227496dcSluxufan break;
165227496dcSluxufan case RISCVABI::ABI_ILP32F:
166227496dcSluxufan case RISCVABI::ABI_LP64F:
167227496dcSluxufan EFlags |= ELF::EF_RISCV_FLOAT_ABI_SINGLE;
168227496dcSluxufan break;
169227496dcSluxufan case RISCVABI::ABI_ILP32D:
170227496dcSluxufan case RISCVABI::ABI_LP64D:
171227496dcSluxufan EFlags |= ELF::EF_RISCV_FLOAT_ABI_DOUBLE;
172227496dcSluxufan break;
173227496dcSluxufan case RISCVABI::ABI_ILP32E:
174227496dcSluxufan EFlags |= ELF::EF_RISCV_RVE;
175227496dcSluxufan break;
176227496dcSluxufan case RISCVABI::ABI_Unknown:
177227496dcSluxufan llvm_unreachable("Improperly initialised target ABI");
178227496dcSluxufan }
179227496dcSluxufan
180227496dcSluxufan MCA.setELFHeaderEFlags(EFlags);
181227496dcSluxufan }
182227496dcSluxufan
reset()183e45087fdSKito Cheng void RISCVTargetELFStreamer::reset() {
184e45087fdSKito Cheng AttributeSection = nullptr;
185e45087fdSKito Cheng Contents.clear();
186e45087fdSKito Cheng }
187e45087fdSKito Cheng
188bbea6425SSaleem Abdulrasool namespace {
189bbea6425SSaleem Abdulrasool class RISCVELFStreamer : public MCELFStreamer {
getRelocPairForSize(unsigned Size)190bbea6425SSaleem Abdulrasool static std::pair<unsigned, unsigned> getRelocPairForSize(unsigned Size) {
191bbea6425SSaleem Abdulrasool switch (Size) {
192bbea6425SSaleem Abdulrasool default:
193bbea6425SSaleem Abdulrasool llvm_unreachable("unsupported fixup size");
194bbea6425SSaleem Abdulrasool case 1:
195bbea6425SSaleem Abdulrasool return std::make_pair(RISCV::fixup_riscv_add_8, RISCV::fixup_riscv_sub_8);
196bbea6425SSaleem Abdulrasool case 2:
197bbea6425SSaleem Abdulrasool return std::make_pair(RISCV::fixup_riscv_add_16,
198bbea6425SSaleem Abdulrasool RISCV::fixup_riscv_sub_16);
199bbea6425SSaleem Abdulrasool case 4:
200bbea6425SSaleem Abdulrasool return std::make_pair(RISCV::fixup_riscv_add_32,
201bbea6425SSaleem Abdulrasool RISCV::fixup_riscv_sub_32);
202bbea6425SSaleem Abdulrasool case 8:
203bbea6425SSaleem Abdulrasool return std::make_pair(RISCV::fixup_riscv_add_64,
204bbea6425SSaleem Abdulrasool RISCV::fixup_riscv_sub_64);
205bbea6425SSaleem Abdulrasool }
206bbea6425SSaleem Abdulrasool }
207bbea6425SSaleem Abdulrasool
requiresFixups(MCContext & C,const MCExpr * Value,const MCExpr * & LHS,const MCExpr * & RHS)208bbea6425SSaleem Abdulrasool static bool requiresFixups(MCContext &C, const MCExpr *Value,
209bbea6425SSaleem Abdulrasool const MCExpr *&LHS, const MCExpr *&RHS) {
2101582bcd0SSaleem Abdulrasool auto IsMetadataOrEHFrameSection = [](const MCSection &S) -> bool {
211*6e8ec13dSFangrui Song // Additionally check .apple_names/.apple_types. They are fixed-size and
212*6e8ec13dSFangrui Song // do not need fixups. llvm-dwarfdump --apple-names does not process
213*6e8ec13dSFangrui Song // R_RISCV_{ADD,SUB}32 in them.
214*6e8ec13dSFangrui Song return S.getKind().isMetadata() || S.getName() == ".eh_frame" ||
215*6e8ec13dSFangrui Song S.getName() == ".apple_names" || S.getName() == ".apple_types";
2161582bcd0SSaleem Abdulrasool };
2171582bcd0SSaleem Abdulrasool
218bbea6425SSaleem Abdulrasool const auto *MBE = dyn_cast<MCBinaryExpr>(Value);
219bbea6425SSaleem Abdulrasool if (MBE == nullptr)
220bbea6425SSaleem Abdulrasool return false;
221bbea6425SSaleem Abdulrasool
222bbea6425SSaleem Abdulrasool MCValue E;
223bbea6425SSaleem Abdulrasool if (!Value->evaluateAsRelocatable(E, nullptr, nullptr))
224bbea6425SSaleem Abdulrasool return false;
225bbea6425SSaleem Abdulrasool if (E.getSymA() == nullptr || E.getSymB() == nullptr)
226bbea6425SSaleem Abdulrasool return false;
227bbea6425SSaleem Abdulrasool
228bbea6425SSaleem Abdulrasool const auto &A = E.getSymA()->getSymbol();
229bbea6425SSaleem Abdulrasool const auto &B = E.getSymB()->getSymbol();
230bbea6425SSaleem Abdulrasool
231bbea6425SSaleem Abdulrasool LHS =
232bbea6425SSaleem Abdulrasool MCBinaryExpr::create(MCBinaryExpr::Add, MCSymbolRefExpr::create(&A, C),
233bbea6425SSaleem Abdulrasool MCConstantExpr::create(E.getConstant(), C), C);
234bbea6425SSaleem Abdulrasool RHS = E.getSymB();
235bbea6425SSaleem Abdulrasool
2361582bcd0SSaleem Abdulrasool // TODO: when available, R_RISCV_n_PCREL should be preferred.
2371582bcd0SSaleem Abdulrasool
2381582bcd0SSaleem Abdulrasool // Avoid pairwise relocations for symbolic difference in debug and .eh_frame
2391582bcd0SSaleem Abdulrasool if (A.isInSection())
2401582bcd0SSaleem Abdulrasool return !IsMetadataOrEHFrameSection(A.getSection());
2411582bcd0SSaleem Abdulrasool if (B.isInSection())
2421582bcd0SSaleem Abdulrasool return !IsMetadataOrEHFrameSection(B.getSection());
2431582bcd0SSaleem Abdulrasool // as well as for absolute symbols.
2441582bcd0SSaleem Abdulrasool return !A.getName().empty() || !B.getName().empty();
245bbea6425SSaleem Abdulrasool }
246bbea6425SSaleem Abdulrasool
reset()247e45087fdSKito Cheng void reset() override {
248cef377d7SFangrui Song static_cast<RISCVTargetStreamer *>(getTargetStreamer())->reset();
249e45087fdSKito Cheng MCELFStreamer::reset();
250e45087fdSKito Cheng }
251e45087fdSKito Cheng
252bbea6425SSaleem Abdulrasool public:
RISCVELFStreamer(MCContext & C,std::unique_ptr<MCAsmBackend> MAB,std::unique_ptr<MCObjectWriter> MOW,std::unique_ptr<MCCodeEmitter> MCE)253bbea6425SSaleem Abdulrasool RISCVELFStreamer(MCContext &C, std::unique_ptr<MCAsmBackend> MAB,
254bbea6425SSaleem Abdulrasool std::unique_ptr<MCObjectWriter> MOW,
255bbea6425SSaleem Abdulrasool std::unique_ptr<MCCodeEmitter> MCE)
256bbea6425SSaleem Abdulrasool : MCELFStreamer(C, std::move(MAB), std::move(MOW), std::move(MCE)) {}
257bbea6425SSaleem Abdulrasool
emitValueImpl(const MCExpr * Value,unsigned Size,SMLoc Loc)258bbea6425SSaleem Abdulrasool void emitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) override {
259bbea6425SSaleem Abdulrasool const MCExpr *A, *B;
260bbea6425SSaleem Abdulrasool if (!requiresFixups(getContext(), Value, A, B))
261bbea6425SSaleem Abdulrasool return MCELFStreamer::emitValueImpl(Value, Size, Loc);
262bbea6425SSaleem Abdulrasool
263bbea6425SSaleem Abdulrasool MCStreamer::emitValueImpl(Value, Size, Loc);
264bbea6425SSaleem Abdulrasool
265bbea6425SSaleem Abdulrasool MCDataFragment *DF = getOrCreateDataFragment();
266bbea6425SSaleem Abdulrasool flushPendingLabels(DF, DF->getContents().size());
267bbea6425SSaleem Abdulrasool MCDwarfLineEntry::make(this, getCurrentSectionOnly());
268bbea6425SSaleem Abdulrasool
269bbea6425SSaleem Abdulrasool unsigned Add, Sub;
270bbea6425SSaleem Abdulrasool std::tie(Add, Sub) = getRelocPairForSize(Size);
271bbea6425SSaleem Abdulrasool
272bbea6425SSaleem Abdulrasool DF->getFixups().push_back(MCFixup::create(
273bbea6425SSaleem Abdulrasool DF->getContents().size(), A, static_cast<MCFixupKind>(Add), Loc));
274bbea6425SSaleem Abdulrasool DF->getFixups().push_back(MCFixup::create(
275bbea6425SSaleem Abdulrasool DF->getContents().size(), B, static_cast<MCFixupKind>(Sub), Loc));
276bbea6425SSaleem Abdulrasool
277bbea6425SSaleem Abdulrasool DF->getContents().resize(DF->getContents().size() + Size, 0);
278bbea6425SSaleem Abdulrasool }
279bbea6425SSaleem Abdulrasool };
280bbea6425SSaleem Abdulrasool } // namespace
281bbea6425SSaleem Abdulrasool
282bbea6425SSaleem Abdulrasool namespace llvm {
createRISCVELFStreamer(MCContext & C,std::unique_ptr<MCAsmBackend> MAB,std::unique_ptr<MCObjectWriter> MOW,std::unique_ptr<MCCodeEmitter> MCE,bool RelaxAll)283bbea6425SSaleem Abdulrasool MCELFStreamer *createRISCVELFStreamer(MCContext &C,
284bbea6425SSaleem Abdulrasool std::unique_ptr<MCAsmBackend> MAB,
285bbea6425SSaleem Abdulrasool std::unique_ptr<MCObjectWriter> MOW,
286bbea6425SSaleem Abdulrasool std::unique_ptr<MCCodeEmitter> MCE,
287bbea6425SSaleem Abdulrasool bool RelaxAll) {
288bbea6425SSaleem Abdulrasool RISCVELFStreamer *S =
289bbea6425SSaleem Abdulrasool new RISCVELFStreamer(C, std::move(MAB), std::move(MOW), std::move(MCE));
290bbea6425SSaleem Abdulrasool S->getAssembler().setRelaxAll(RelaxAll);
291bbea6425SSaleem Abdulrasool return S;
292bbea6425SSaleem Abdulrasool }
293bbea6425SSaleem Abdulrasool } // namespace llvm
294