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.
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 
67 MCELFStreamer &RISCVTargetELFStreamer::getStreamer() {
68   return static_cast<MCELFStreamer &>(Streamer);
69 }
70 
71 void RISCVTargetELFStreamer::emitDirectiveOptionPush() {}
72 void RISCVTargetELFStreamer::emitDirectiveOptionPop() {}
73 void RISCVTargetELFStreamer::emitDirectiveOptionPIC() {}
74 void RISCVTargetELFStreamer::emitDirectiveOptionNoPIC() {}
75 void RISCVTargetELFStreamer::emitDirectiveOptionRVC() {}
76 void RISCVTargetELFStreamer::emitDirectiveOptionNoRVC() {}
77 void RISCVTargetELFStreamer::emitDirectiveOptionRelax() {}
78 void RISCVTargetELFStreamer::emitDirectiveOptionNoRelax() {}
79 
80 void RISCVTargetELFStreamer::emitAttribute(unsigned Attribute, unsigned Value) {
81   setAttributeItem(Attribute, Value, /*OverwriteExisting=*/true);
82 }
83 
84 void RISCVTargetELFStreamer::emitTextAttribute(unsigned Attribute,
85                                                StringRef String) {
86   setAttributeItem(Attribute, String, /*OverwriteExisting=*/true);
87 }
88 
89 void RISCVTargetELFStreamer::emitIntTextAttribute(unsigned Attribute,
90                                                   unsigned IntValue,
91                                                   StringRef StringValue) {
92   setAttributeItems(Attribute, IntValue, StringValue,
93                     /*OverwriteExisting=*/true);
94 }
95 
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 
151 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 {
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 
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:
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 
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 {
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