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/MCCodeEmitter.h"
20 #include "llvm/MC/MCContext.h"
21 #include "llvm/MC/MCObjectWriter.h"
22 #include "llvm/MC/MCSectionELF.h"
23 #include "llvm/MC/MCSubtargetInfo.h"
24 #include "llvm/MC/MCValue.h"
25 #include "llvm/Support/LEB128.h"
26 #include "llvm/Support/RISCVAttributes.h"
27
28 using namespace llvm;
29
30 // This part is for ELF object output.
RISCVTargetELFStreamer(MCStreamer & S,const MCSubtargetInfo & STI)31 RISCVTargetELFStreamer::RISCVTargetELFStreamer(MCStreamer &S,
32 const MCSubtargetInfo &STI)
33 : RISCVTargetStreamer(S), CurrentVendor("riscv") {
34 MCAssembler &MCA = getStreamer().getAssembler();
35 const FeatureBitset &Features = STI.getFeatureBits();
36 auto &MAB = static_cast<RISCVAsmBackend &>(MCA.getBackend());
37 RISCVABI::ABI ABI = MAB.getTargetABI();
38 assert(ABI != RISCVABI::ABI_Unknown && "Improperly initialised target ABI");
39
40 unsigned EFlags = MCA.getELFHeaderEFlags();
41
42 if (Features[RISCV::FeatureStdExtC])
43 EFlags |= ELF::EF_RISCV_RVC;
44
45 switch (ABI) {
46 case RISCVABI::ABI_ILP32:
47 case RISCVABI::ABI_LP64:
48 break;
49 case RISCVABI::ABI_ILP32F:
50 case RISCVABI::ABI_LP64F:
51 EFlags |= ELF::EF_RISCV_FLOAT_ABI_SINGLE;
52 break;
53 case RISCVABI::ABI_ILP32D:
54 case RISCVABI::ABI_LP64D:
55 EFlags |= ELF::EF_RISCV_FLOAT_ABI_DOUBLE;
56 break;
57 case RISCVABI::ABI_ILP32E:
58 EFlags |= ELF::EF_RISCV_RVE;
59 break;
60 case RISCVABI::ABI_Unknown:
61 llvm_unreachable("Improperly initialised target ABI");
62 }
63
64 MCA.setELFHeaderEFlags(EFlags);
65 }
66
getStreamer()67 MCELFStreamer &RISCVTargetELFStreamer::getStreamer() {
68 return static_cast<MCELFStreamer &>(Streamer);
69 }
70
emitDirectiveOptionPush()71 void RISCVTargetELFStreamer::emitDirectiveOptionPush() {}
emitDirectiveOptionPop()72 void RISCVTargetELFStreamer::emitDirectiveOptionPop() {}
emitDirectiveOptionPIC()73 void RISCVTargetELFStreamer::emitDirectiveOptionPIC() {}
emitDirectiveOptionNoPIC()74 void RISCVTargetELFStreamer::emitDirectiveOptionNoPIC() {}
emitDirectiveOptionRVC()75 void RISCVTargetELFStreamer::emitDirectiveOptionRVC() {}
emitDirectiveOptionNoRVC()76 void RISCVTargetELFStreamer::emitDirectiveOptionNoRVC() {}
emitDirectiveOptionRelax()77 void RISCVTargetELFStreamer::emitDirectiveOptionRelax() {}
emitDirectiveOptionNoRelax()78 void RISCVTargetELFStreamer::emitDirectiveOptionNoRelax() {}
79
emitAttribute(unsigned Attribute,unsigned Value)80 void RISCVTargetELFStreamer::emitAttribute(unsigned Attribute, unsigned Value) {
81 setAttributeItem(Attribute, Value, /*OverwriteExisting=*/true);
82 }
83
emitTextAttribute(unsigned Attribute,StringRef String)84 void RISCVTargetELFStreamer::emitTextAttribute(unsigned Attribute,
85 StringRef String) {
86 setAttributeItem(Attribute, String, /*OverwriteExisting=*/true);
87 }
88
emitIntTextAttribute(unsigned Attribute,unsigned IntValue,StringRef StringValue)89 void RISCVTargetELFStreamer::emitIntTextAttribute(unsigned Attribute,
90 unsigned IntValue,
91 StringRef StringValue) {
92 setAttributeItems(Attribute, IntValue, StringValue,
93 /*OverwriteExisting=*/true);
94 }
95
finishAttributeSection()96 void RISCVTargetELFStreamer::finishAttributeSection() {
97 if (Contents.empty())
98 return;
99
100 if (AttributeSection) {
101 Streamer.SwitchSection(AttributeSection);
102 } else {
103 MCAssembler &MCA = getStreamer().getAssembler();
104 AttributeSection = MCA.getContext().getELFSection(
105 ".riscv.attributes", ELF::SHT_RISCV_ATTRIBUTES, 0);
106 Streamer.SwitchSection(AttributeSection);
107
108 Streamer.emitInt8(ELFAttrs::Format_Version);
109 }
110
111 // Vendor size + Vendor name + '\0'
112 const size_t VendorHeaderSize = 4 + CurrentVendor.size() + 1;
113
114 // Tag + Tag Size
115 const size_t TagHeaderSize = 1 + 4;
116
117 const size_t ContentsSize = calculateContentSize();
118
119 Streamer.emitInt32(VendorHeaderSize + TagHeaderSize + ContentsSize);
120 Streamer.emitBytes(CurrentVendor);
121 Streamer.emitInt8(0); // '\0'
122
123 Streamer.emitInt8(ELFAttrs::File);
124 Streamer.emitInt32(TagHeaderSize + ContentsSize);
125
126 // Size should have been accounted for already, now
127 // emit each field as its type (ULEB or String).
128 for (AttributeItem item : Contents) {
129 Streamer.emitULEB128IntValue(item.Tag);
130 switch (item.Type) {
131 default:
132 llvm_unreachable("Invalid attribute type");
133 case AttributeType::Numeric:
134 Streamer.emitULEB128IntValue(item.IntValue);
135 break;
136 case AttributeType::Text:
137 Streamer.emitBytes(item.StringValue);
138 Streamer.emitInt8(0); // '\0'
139 break;
140 case AttributeType::NumericAndText:
141 Streamer.emitULEB128IntValue(item.IntValue);
142 Streamer.emitBytes(item.StringValue);
143 Streamer.emitInt8(0); // '\0'
144 break;
145 }
146 }
147
148 Contents.clear();
149 }
150
calculateContentSize() const151 size_t RISCVTargetELFStreamer::calculateContentSize() const {
152 size_t Result = 0;
153 for (AttributeItem item : Contents) {
154 switch (item.Type) {
155 case AttributeType::Hidden:
156 break;
157 case AttributeType::Numeric:
158 Result += getULEB128Size(item.Tag);
159 Result += getULEB128Size(item.IntValue);
160 break;
161 case AttributeType::Text:
162 Result += getULEB128Size(item.Tag);
163 Result += item.StringValue.size() + 1; // string + '\0'
164 break;
165 case AttributeType::NumericAndText:
166 Result += getULEB128Size(item.Tag);
167 Result += getULEB128Size(item.IntValue);
168 Result += item.StringValue.size() + 1; // string + '\0';
169 break;
170 }
171 }
172 return Result;
173 }
174
175 namespace {
176 class RISCVELFStreamer : public MCELFStreamer {
getRelocPairForSize(unsigned Size)177 static std::pair<unsigned, unsigned> getRelocPairForSize(unsigned Size) {
178 switch (Size) {
179 default:
180 llvm_unreachable("unsupported fixup size");
181 case 1:
182 return std::make_pair(RISCV::fixup_riscv_add_8, RISCV::fixup_riscv_sub_8);
183 case 2:
184 return std::make_pair(RISCV::fixup_riscv_add_16,
185 RISCV::fixup_riscv_sub_16);
186 case 4:
187 return std::make_pair(RISCV::fixup_riscv_add_32,
188 RISCV::fixup_riscv_sub_32);
189 case 8:
190 return std::make_pair(RISCV::fixup_riscv_add_64,
191 RISCV::fixup_riscv_sub_64);
192 }
193 }
194
requiresFixups(MCContext & C,const MCExpr * Value,const MCExpr * & LHS,const MCExpr * & RHS)195 static bool 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
210 LHS =
211 MCBinaryExpr::create(MCBinaryExpr::Add, MCSymbolRefExpr::create(&A, C),
212 MCConstantExpr::create(E.getConstant(), C), C);
213 RHS = E.getSymB();
214
215 return (A.isInSection() ? A.getSection().hasInstructions()
216 : !A.getName().empty()) ||
217 (B.isInSection() ? B.getSection().hasInstructions()
218 : !B.getName().empty());
219 }
220
221 public:
RISCVELFStreamer(MCContext & C,std::unique_ptr<MCAsmBackend> MAB,std::unique_ptr<MCObjectWriter> MOW,std::unique_ptr<MCCodeEmitter> MCE)222 RISCVELFStreamer(MCContext &C, std::unique_ptr<MCAsmBackend> MAB,
223 std::unique_ptr<MCObjectWriter> MOW,
224 std::unique_ptr<MCCodeEmitter> MCE)
225 : MCELFStreamer(C, std::move(MAB), std::move(MOW), std::move(MCE)) {}
226
emitValueImpl(const MCExpr * Value,unsigned Size,SMLoc Loc)227 void emitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) override {
228 const MCExpr *A, *B;
229 if (!requiresFixups(getContext(), Value, A, B))
230 return MCELFStreamer::emitValueImpl(Value, Size, Loc);
231
232 MCStreamer::emitValueImpl(Value, Size, Loc);
233
234 MCDataFragment *DF = getOrCreateDataFragment();
235 flushPendingLabels(DF, DF->getContents().size());
236 MCDwarfLineEntry::make(this, getCurrentSectionOnly());
237
238 unsigned Add, Sub;
239 std::tie(Add, Sub) = getRelocPairForSize(Size);
240
241 DF->getFixups().push_back(MCFixup::create(
242 DF->getContents().size(), A, static_cast<MCFixupKind>(Add), Loc));
243 DF->getFixups().push_back(MCFixup::create(
244 DF->getContents().size(), B, static_cast<MCFixupKind>(Sub), Loc));
245
246 DF->getContents().resize(DF->getContents().size() + Size, 0);
247 }
248 };
249 } // namespace
250
251 namespace llvm {
createRISCVELFStreamer(MCContext & C,std::unique_ptr<MCAsmBackend> MAB,std::unique_ptr<MCObjectWriter> MOW,std::unique_ptr<MCCodeEmitter> MCE,bool RelaxAll)252 MCELFStreamer *createRISCVELFStreamer(MCContext &C,
253 std::unique_ptr<MCAsmBackend> MAB,
254 std::unique_ptr<MCObjectWriter> MOW,
255 std::unique_ptr<MCCodeEmitter> MCE,
256 bool RelaxAll) {
257 RISCVELFStreamer *S =
258 new RISCVELFStreamer(C, std::move(MAB), std::move(MOW), std::move(MCE));
259 S->getAssembler().setRelaxAll(RelaxAll);
260 return S;
261 }
262 } // namespace llvm
263