xref: /llvm-project/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp (revision 82d5dd28b4de7245088f7ed40da37f8cf80461e4)
1 //===-- RISCVELFStreamer.cpp - RISC-V 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 RISC-V 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/MCELFObjectWriter.h"
23 #include "llvm/MC/MCSubtargetInfo.h"
24 
25 using namespace llvm;
26 
27 // This part is for ELF object output.
28 RISCVTargetELFStreamer::RISCVTargetELFStreamer(MCStreamer &S,
29                                                const MCSubtargetInfo &STI)
30     : RISCVTargetStreamer(S), CurrentVendor("riscv") {
31   MCAssembler &MCA = getStreamer().getAssembler();
32   const FeatureBitset &Features = STI.getFeatureBits();
33   auto &MAB = static_cast<RISCVAsmBackend &>(MCA.getBackend());
34   setTargetABI(RISCVABI::computeTargetABI(STI.getTargetTriple(), Features,
35                                           MAB.getTargetOptions().getABIName()));
36   setFlagsFromFeatures(STI);
37   // `j label` in `.option norelax; j label; .option relax; ...; label:` needs a
38   // relocation to ensure the jump target is correct after linking. This is due
39   // to a limitation that shouldForceRelocation has to make the decision upfront
40   // without knowing a possibly future .option relax. When RISCVAsmParser is used,
41   // its ParseInstruction may call setForceRelocs as well.
42   if (STI.hasFeature(RISCV::FeatureRelax))
43     static_cast<RISCVAsmBackend &>(MAB).setForceRelocs();
44 }
45 
46 RISCVELFStreamer &RISCVTargetELFStreamer::getStreamer() {
47   return static_cast<RISCVELFStreamer &>(Streamer);
48 }
49 
50 void RISCVTargetELFStreamer::emitDirectiveOptionPush() {}
51 void RISCVTargetELFStreamer::emitDirectiveOptionPop() {}
52 void RISCVTargetELFStreamer::emitDirectiveOptionPIC() {}
53 void RISCVTargetELFStreamer::emitDirectiveOptionNoPIC() {}
54 void RISCVTargetELFStreamer::emitDirectiveOptionRVC() {}
55 void RISCVTargetELFStreamer::emitDirectiveOptionNoRVC() {}
56 void RISCVTargetELFStreamer::emitDirectiveOptionRelax() {}
57 void RISCVTargetELFStreamer::emitDirectiveOptionNoRelax() {}
58 
59 void RISCVTargetELFStreamer::emitAttribute(unsigned Attribute, unsigned Value) {
60   getStreamer().setAttributeItem(Attribute, Value, /*OverwriteExisting=*/true);
61 }
62 
63 void RISCVTargetELFStreamer::emitTextAttribute(unsigned Attribute,
64                                                StringRef String) {
65   getStreamer().setAttributeItem(Attribute, String, /*OverwriteExisting=*/true);
66 }
67 
68 void RISCVTargetELFStreamer::emitIntTextAttribute(unsigned Attribute,
69                                                   unsigned IntValue,
70                                                   StringRef StringValue) {
71   getStreamer().setAttributeItems(Attribute, IntValue, StringValue,
72                                   /*OverwriteExisting=*/true);
73 }
74 
75 void RISCVTargetELFStreamer::finishAttributeSection() {
76   RISCVELFStreamer &S = getStreamer();
77   if (S.Contents.empty())
78     return;
79 
80   S.emitAttributesSection(CurrentVendor, ".riscv.attributes",
81                           ELF::SHT_RISCV_ATTRIBUTES, AttributeSection);
82 }
83 
84 void RISCVTargetELFStreamer::finish() {
85   RISCVTargetStreamer::finish();
86   ELFObjectWriter &W = getStreamer().getWriter();
87   RISCVABI::ABI ABI = getTargetABI();
88 
89   unsigned EFlags = W.getELFHeaderEFlags();
90 
91   if (hasRVC())
92     EFlags |= ELF::EF_RISCV_RVC;
93   if (hasTSO())
94     EFlags |= ELF::EF_RISCV_TSO;
95 
96   switch (ABI) {
97   case RISCVABI::ABI_ILP32:
98   case RISCVABI::ABI_LP64:
99     break;
100   case RISCVABI::ABI_ILP32F:
101   case RISCVABI::ABI_LP64F:
102     EFlags |= ELF::EF_RISCV_FLOAT_ABI_SINGLE;
103     break;
104   case RISCVABI::ABI_ILP32D:
105   case RISCVABI::ABI_LP64D:
106     EFlags |= ELF::EF_RISCV_FLOAT_ABI_DOUBLE;
107     break;
108   case RISCVABI::ABI_ILP32E:
109   case RISCVABI::ABI_LP64E:
110     EFlags |= ELF::EF_RISCV_RVE;
111     break;
112   case RISCVABI::ABI_Unknown:
113     llvm_unreachable("Improperly initialised target ABI");
114   }
115 
116   W.setELFHeaderEFlags(EFlags);
117 }
118 
119 void RISCVTargetELFStreamer::reset() {
120   AttributeSection = nullptr;
121 }
122 
123 void RISCVTargetELFStreamer::emitDirectiveVariantCC(MCSymbol &Symbol) {
124   getStreamer().getAssembler().registerSymbol(Symbol);
125   cast<MCSymbolELF>(Symbol).setOther(ELF::STO_RISCV_VARIANT_CC);
126 }
127 
128 void RISCVELFStreamer::reset() {
129   static_cast<RISCVTargetStreamer *>(getTargetStreamer())->reset();
130   MCELFStreamer::reset();
131   LastMappingSymbols.clear();
132   LastEMS = EMS_None;
133 }
134 
135 void RISCVELFStreamer::emitDataMappingSymbol() {
136   if (LastEMS == EMS_Data)
137     return;
138   emitMappingSymbol("$d");
139   LastEMS = EMS_Data;
140 }
141 
142 void RISCVELFStreamer::emitInstructionsMappingSymbol() {
143   if (LastEMS == EMS_Instructions)
144     return;
145   emitMappingSymbol("$x");
146   LastEMS = EMS_Instructions;
147 }
148 
149 void RISCVELFStreamer::emitMappingSymbol(StringRef Name) {
150   auto *Symbol = cast<MCSymbolELF>(getContext().createLocalSymbol(Name));
151   emitLabel(Symbol);
152   Symbol->setType(ELF::STT_NOTYPE);
153   Symbol->setBinding(ELF::STB_LOCAL);
154 }
155 
156 void RISCVELFStreamer::changeSection(MCSection *Section, uint32_t Subsection) {
157   // We have to keep track of the mapping symbol state of any sections we
158   // use. Each one should start off as EMS_None, which is provided as the
159   // default constructor by DenseMap::lookup.
160   LastMappingSymbols[getPreviousSection().first] = LastEMS;
161   LastEMS = LastMappingSymbols.lookup(Section);
162 
163   MCELFStreamer::changeSection(Section, Subsection);
164 }
165 
166 void RISCVELFStreamer::emitInstruction(const MCInst &Inst,
167                                        const MCSubtargetInfo &STI) {
168   emitInstructionsMappingSymbol();
169   MCELFStreamer::emitInstruction(Inst, STI);
170 }
171 
172 void RISCVELFStreamer::emitBytes(StringRef Data) {
173   emitDataMappingSymbol();
174   MCELFStreamer::emitBytes(Data);
175 }
176 
177 void RISCVELFStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue,
178                                 SMLoc Loc) {
179   emitDataMappingSymbol();
180   MCELFStreamer::emitFill(NumBytes, FillValue, Loc);
181 }
182 
183 void RISCVELFStreamer::emitValueImpl(const MCExpr *Value, unsigned Size,
184                                      SMLoc Loc) {
185   emitDataMappingSymbol();
186   MCELFStreamer::emitValueImpl(Value, Size, Loc);
187 }
188 
189 namespace llvm {
190 MCELFStreamer *createRISCVELFStreamer(MCContext &C,
191                                       std::unique_ptr<MCAsmBackend> MAB,
192                                       std::unique_ptr<MCObjectWriter> MOW,
193                                       std::unique_ptr<MCCodeEmitter> MCE) {
194   RISCVELFStreamer *S =
195       new RISCVELFStreamer(C, std::move(MAB), std::move(MOW), std::move(MCE));
196   return S;
197 }
198 } // namespace llvm
199