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
29using namespace llvm;
30
31// This part is for ELF object output.
32RISCVTargetELFStreamer::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(TT: STI.getTargetTriple(), FeatureBits: Features,
39 ABIName: 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::Feature: FeatureRelax))
47 static_cast<RISCVAsmBackend &>(MAB).setForceRelocs();
48}
49
50RISCVELFStreamer &RISCVTargetELFStreamer::getStreamer() {
51 return static_cast<RISCVELFStreamer &>(Streamer);
52}
53
54void RISCVTargetELFStreamer::emitDirectiveOptionPush() {}
55void RISCVTargetELFStreamer::emitDirectiveOptionPop() {}
56void RISCVTargetELFStreamer::emitDirectiveOptionPIC() {}
57void RISCVTargetELFStreamer::emitDirectiveOptionNoPIC() {}
58void RISCVTargetELFStreamer::emitDirectiveOptionRVC() {}
59void RISCVTargetELFStreamer::emitDirectiveOptionNoRVC() {}
60void RISCVTargetELFStreamer::emitDirectiveOptionRelax() {}
61void RISCVTargetELFStreamer::emitDirectiveOptionNoRelax() {}
62
63void RISCVTargetELFStreamer::emitAttribute(unsigned Attribute, unsigned Value) {
64 getStreamer().setAttributeItem(Attribute, Value, /*OverwriteExisting=*/true);
65}
66
67void RISCVTargetELFStreamer::emitTextAttribute(unsigned Attribute,
68 StringRef String) {
69 getStreamer().setAttributeItem(Attribute, Value: String, /*OverwriteExisting=*/true);
70}
71
72void RISCVTargetELFStreamer::emitIntTextAttribute(unsigned Attribute,
73 unsigned IntValue,
74 StringRef StringValue) {
75 getStreamer().setAttributeItems(Attribute, IntValue, StringValue,
76 /*OverwriteExisting=*/true);
77}
78
79void RISCVTargetELFStreamer::finishAttributeSection() {
80 RISCVELFStreamer &S = getStreamer();
81 if (S.Contents.empty())
82 return;
83
84 S.emitAttributesSection(Vendor: CurrentVendor, Section: ".riscv.attributes",
85 Type: ELF::SHT_RISCV_ATTRIBUTES, AttributeSection);
86}
87
88void 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
123void RISCVTargetELFStreamer::reset() {
124 AttributeSection = nullptr;
125}
126
127void RISCVTargetELFStreamer::emitDirectiveVariantCC(MCSymbol &Symbol) {
128 getStreamer().getAssembler().registerSymbol(Symbol);
129 cast<MCSymbolELF>(Val&: Symbol).setOther(ELF::STO_RISCV_VARIANT_CC);
130}
131
132void RISCVELFStreamer::reset() {
133 static_cast<RISCVTargetStreamer *>(getTargetStreamer())->reset();
134 MCELFStreamer::reset();
135 MappingSymbolCounter = 0;
136 LastMappingSymbols.clear();
137 LastEMS = EMS_None;
138}
139
140void RISCVELFStreamer::emitDataMappingSymbol() {
141 if (LastEMS == EMS_Data)
142 return;
143 emitMappingSymbol(Name: "$d");
144 LastEMS = EMS_Data;
145}
146
147void RISCVELFStreamer::emitInstructionsMappingSymbol() {
148 if (LastEMS == EMS_Instructions)
149 return;
150 emitMappingSymbol(Name: "$x");
151 LastEMS = EMS_Instructions;
152}
153
154void RISCVELFStreamer::emitMappingSymbol(StringRef Name) {
155 auto *Symbol = cast<MCSymbolELF>(Val: getContext().getOrCreateSymbol(
156 Name: Name + "." + Twine(MappingSymbolCounter++)));
157 emitLabel(Symbol);
158 Symbol->setType(ELF::STT_NOTYPE);
159 Symbol->setBinding(ELF::STB_LOCAL);
160}
161
162void 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(Val: Section);
169
170 MCELFStreamer::changeSection(Section, Subsection);
171}
172
173void RISCVELFStreamer::emitInstruction(const MCInst &Inst,
174 const MCSubtargetInfo &STI) {
175 emitInstructionsMappingSymbol();
176 MCELFStreamer::emitInstruction(Inst, STI);
177}
178
179void RISCVELFStreamer::emitBytes(StringRef Data) {
180 emitDataMappingSymbol();
181 MCELFStreamer::emitBytes(Data);
182}
183
184void RISCVELFStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue,
185 SMLoc Loc) {
186 emitDataMappingSymbol();
187 MCELFStreamer::emitFill(NumBytes, FillValue, Loc);
188}
189
190void RISCVELFStreamer::emitValueImpl(const MCExpr *Value, unsigned Size,
191 SMLoc Loc) {
192 emitDataMappingSymbol();
193 MCELFStreamer::emitValueImpl(Value, Size, Loc);
194}
195
196namespace llvm {
197MCELFStreamer *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

source code of llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp