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(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 | |
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, Value: 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(Vendor: CurrentVendor, Section: ".riscv.attributes" , |
85 | Type: 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>(Val&: 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(Name: "$d" ); |
144 | LastEMS = EMS_Data; |
145 | } |
146 | |
147 | void RISCVELFStreamer::emitInstructionsMappingSymbol() { |
148 | if (LastEMS == EMS_Instructions) |
149 | return; |
150 | emitMappingSymbol(Name: "$x" ); |
151 | LastEMS = EMS_Instructions; |
152 | } |
153 | |
154 | void 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 | |
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(Val: 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 | |