xref: /freebsd/contrib/llvm-project/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp (revision 9f23cbd6cae82fd77edfad7173432fa8dccd0a95)
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.
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 
42 RISCVELFStreamer &RISCVTargetELFStreamer::getStreamer() {
43   return static_cast<RISCVELFStreamer &>(Streamer);
44 }
45 
46 void RISCVTargetELFStreamer::emitDirectiveOptionPush() {}
47 void RISCVTargetELFStreamer::emitDirectiveOptionPop() {}
48 void RISCVTargetELFStreamer::emitDirectiveOptionPIC() {}
49 void RISCVTargetELFStreamer::emitDirectiveOptionNoPIC() {}
50 void RISCVTargetELFStreamer::emitDirectiveOptionRVC() {}
51 void RISCVTargetELFStreamer::emitDirectiveOptionNoRVC() {}
52 void RISCVTargetELFStreamer::emitDirectiveOptionRelax() {}
53 void RISCVTargetELFStreamer::emitDirectiveOptionNoRelax() {}
54 
55 void RISCVTargetELFStreamer::emitAttribute(unsigned Attribute, unsigned Value) {
56   setAttributeItem(Attribute, Value, /*OverwriteExisting=*/true);
57 }
58 
59 void RISCVTargetELFStreamer::emitTextAttribute(unsigned Attribute,
60                                                StringRef String) {
61   setAttributeItem(Attribute, String, /*OverwriteExisting=*/true);
62 }
63 
64 void RISCVTargetELFStreamer::emitIntTextAttribute(unsigned Attribute,
65                                                   unsigned IntValue,
66                                                   StringRef StringValue) {
67   setAttributeItems(Attribute, IntValue, StringValue,
68                     /*OverwriteExisting=*/true);
69 }
70 
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 
126 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 
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 
185 void RISCVTargetELFStreamer::reset() {
186   AttributeSection = nullptr;
187   Contents.clear();
188 }
189 
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>
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 
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 
257 void RISCVELFStreamer::reset() {
258   static_cast<RISCVTargetStreamer *>(getTargetStreamer())->reset();
259   MCELFStreamer::reset();
260 }
261 
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 {
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