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