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(Feature: 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, 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 | ELFObjectWriter &W = getStreamer().getWriter(); |
91 | RISCVABI::ABI ABI = getTargetABI(); |
92 | |
93 | unsigned EFlags = W.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 | W.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 | LastMappingSymbols.clear(); |
136 | LastEMS = EMS_None; |
137 | } |
138 | |
139 | void RISCVELFStreamer::emitDataMappingSymbol() { |
140 | if (LastEMS == EMS_Data) |
141 | return; |
142 | emitMappingSymbol(Name: "$d" ); |
143 | LastEMS = EMS_Data; |
144 | } |
145 | |
146 | void RISCVELFStreamer::emitInstructionsMappingSymbol() { |
147 | if (LastEMS == EMS_Instructions) |
148 | return; |
149 | emitMappingSymbol(Name: "$x" ); |
150 | LastEMS = EMS_Instructions; |
151 | } |
152 | |
153 | void RISCVELFStreamer::emitMappingSymbol(StringRef Name) { |
154 | auto *Symbol = cast<MCSymbolELF>(Val: getContext().createLocalSymbol(Name)); |
155 | emitLabel(Symbol); |
156 | Symbol->setType(ELF::STT_NOTYPE); |
157 | Symbol->setBinding(ELF::STB_LOCAL); |
158 | } |
159 | |
160 | void RISCVELFStreamer::changeSection(MCSection *Section, uint32_t Subsection) { |
161 | // We have to keep track of the mapping symbol state of any sections we |
162 | // use. Each one should start off as EMS_None, which is provided as the |
163 | // default constructor by DenseMap::lookup. |
164 | LastMappingSymbols[getPreviousSection().first] = LastEMS; |
165 | LastEMS = LastMappingSymbols.lookup(Val: Section); |
166 | |
167 | MCELFStreamer::changeSection(Section, Subsection); |
168 | } |
169 | |
170 | void RISCVELFStreamer::emitInstruction(const MCInst &Inst, |
171 | const MCSubtargetInfo &STI) { |
172 | emitInstructionsMappingSymbol(); |
173 | MCELFStreamer::emitInstruction(Inst, STI); |
174 | } |
175 | |
176 | void RISCVELFStreamer::emitBytes(StringRef Data) { |
177 | emitDataMappingSymbol(); |
178 | MCELFStreamer::emitBytes(Data); |
179 | } |
180 | |
181 | void RISCVELFStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue, |
182 | SMLoc Loc) { |
183 | emitDataMappingSymbol(); |
184 | MCELFStreamer::emitFill(NumBytes, FillValue, Loc); |
185 | } |
186 | |
187 | void RISCVELFStreamer::emitValueImpl(const MCExpr *Value, unsigned Size, |
188 | SMLoc Loc) { |
189 | emitDataMappingSymbol(); |
190 | MCELFStreamer::emitValueImpl(Value, Size, Loc); |
191 | } |
192 | |
193 | namespace llvm { |
194 | MCELFStreamer *createRISCVELFStreamer(MCContext &C, |
195 | std::unique_ptr<MCAsmBackend> MAB, |
196 | std::unique_ptr<MCObjectWriter> MOW, |
197 | std::unique_ptr<MCCodeEmitter> MCE) { |
198 | RISCVELFStreamer *S = |
199 | new RISCVELFStreamer(C, std::move(MAB), std::move(MOW), std::move(MCE)); |
200 | return S; |
201 | } |
202 | } // namespace llvm |
203 | |