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