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(TT: STI.getTargetTriple(), FeatureBits: Features, |
35 | ABIName: MAB.getTargetOptions().getABIName())); |
36 | setFlagsFromFeatures(STI); |
37 | } |
38 | |
39 | RISCVELFStreamer &RISCVTargetELFStreamer::getStreamer() { |
40 | return static_cast<RISCVELFStreamer &>(Streamer); |
41 | } |
42 | |
43 | void RISCVTargetELFStreamer::emitDirectiveOptionExact() {} |
44 | void RISCVTargetELFStreamer::emitDirectiveOptionNoExact() {} |
45 | void RISCVTargetELFStreamer::emitDirectiveOptionPIC() {} |
46 | void RISCVTargetELFStreamer::emitDirectiveOptionNoPIC() {} |
47 | void RISCVTargetELFStreamer::emitDirectiveOptionPop() {} |
48 | void RISCVTargetELFStreamer::emitDirectiveOptionPush() {} |
49 | void RISCVTargetELFStreamer::emitDirectiveOptionRelax() {} |
50 | void RISCVTargetELFStreamer::emitDirectiveOptionNoRelax() {} |
51 | void RISCVTargetELFStreamer::emitDirectiveOptionRVC() {} |
52 | void RISCVTargetELFStreamer::emitDirectiveOptionNoRVC() {} |
53 | |
54 | void RISCVTargetELFStreamer::emitAttribute(unsigned Attribute, unsigned Value) { |
55 | getStreamer().setAttributeItem(Attribute, Value, /*OverwriteExisting=*/true); |
56 | } |
57 | |
58 | void RISCVTargetELFStreamer::emitTextAttribute(unsigned Attribute, |
59 | StringRef String) { |
60 | getStreamer().setAttributeItem(Attribute, Value: String, /*OverwriteExisting=*/true); |
61 | } |
62 | |
63 | void RISCVTargetELFStreamer::emitIntTextAttribute(unsigned Attribute, |
64 | unsigned IntValue, |
65 | StringRef StringValue) { |
66 | getStreamer().setAttributeItems(Attribute, IntValue, StringValue, |
67 | /*OverwriteExisting=*/true); |
68 | } |
69 | |
70 | void RISCVTargetELFStreamer::finishAttributeSection() { |
71 | RISCVELFStreamer &S = getStreamer(); |
72 | if (S.Contents.empty()) |
73 | return; |
74 | |
75 | S.emitAttributesSection(Vendor: CurrentVendor, Section: ".riscv.attributes" , |
76 | Type: ELF::SHT_RISCV_ATTRIBUTES, AttributeSection); |
77 | } |
78 | |
79 | void RISCVTargetELFStreamer::finish() { |
80 | RISCVTargetStreamer::finish(); |
81 | ELFObjectWriter &W = getStreamer().getWriter(); |
82 | RISCVABI::ABI ABI = getTargetABI(); |
83 | |
84 | unsigned EFlags = W.getELFHeaderEFlags(); |
85 | |
86 | if (hasRVC()) |
87 | EFlags |= ELF::EF_RISCV_RVC; |
88 | if (hasTSO()) |
89 | EFlags |= ELF::EF_RISCV_TSO; |
90 | |
91 | switch (ABI) { |
92 | case RISCVABI::ABI_ILP32: |
93 | case RISCVABI::ABI_LP64: |
94 | break; |
95 | case RISCVABI::ABI_ILP32F: |
96 | case RISCVABI::ABI_LP64F: |
97 | EFlags |= ELF::EF_RISCV_FLOAT_ABI_SINGLE; |
98 | break; |
99 | case RISCVABI::ABI_ILP32D: |
100 | case RISCVABI::ABI_LP64D: |
101 | EFlags |= ELF::EF_RISCV_FLOAT_ABI_DOUBLE; |
102 | break; |
103 | case RISCVABI::ABI_ILP32E: |
104 | case RISCVABI::ABI_LP64E: |
105 | EFlags |= ELF::EF_RISCV_RVE; |
106 | break; |
107 | case RISCVABI::ABI_Unknown: |
108 | llvm_unreachable("Improperly initialised target ABI" ); |
109 | } |
110 | |
111 | W.setELFHeaderEFlags(EFlags); |
112 | } |
113 | |
114 | void RISCVTargetELFStreamer::reset() { |
115 | AttributeSection = nullptr; |
116 | } |
117 | |
118 | void RISCVTargetELFStreamer::emitDirectiveVariantCC(MCSymbol &Symbol) { |
119 | getStreamer().getAssembler().registerSymbol(Symbol); |
120 | cast<MCSymbolELF>(Val&: Symbol).setOther(ELF::STO_RISCV_VARIANT_CC); |
121 | } |
122 | |
123 | void RISCVELFStreamer::reset() { |
124 | static_cast<RISCVTargetStreamer *>(getTargetStreamer())->reset(); |
125 | MCELFStreamer::reset(); |
126 | LastMappingSymbols.clear(); |
127 | LastEMS = EMS_None; |
128 | } |
129 | |
130 | void RISCVELFStreamer::emitDataMappingSymbol() { |
131 | if (LastEMS == EMS_Data) |
132 | return; |
133 | emitMappingSymbol(Name: "$d" ); |
134 | LastEMS = EMS_Data; |
135 | } |
136 | |
137 | void RISCVELFStreamer::emitInstructionsMappingSymbol() { |
138 | if (LastEMS == EMS_Instructions) |
139 | return; |
140 | emitMappingSymbol(Name: "$x" ); |
141 | LastEMS = EMS_Instructions; |
142 | } |
143 | |
144 | void RISCVELFStreamer::emitMappingSymbol(StringRef Name) { |
145 | auto *Symbol = cast<MCSymbolELF>(Val: getContext().createLocalSymbol(Name)); |
146 | emitLabel(Symbol); |
147 | Symbol->setType(ELF::STT_NOTYPE); |
148 | Symbol->setBinding(ELF::STB_LOCAL); |
149 | } |
150 | |
151 | void RISCVELFStreamer::changeSection(MCSection *Section, uint32_t Subsection) { |
152 | // We have to keep track of the mapping symbol state of any sections we |
153 | // use. Each one should start off as EMS_None, which is provided as the |
154 | // default constructor by DenseMap::lookup. |
155 | LastMappingSymbols[getPreviousSection().first] = LastEMS; |
156 | LastEMS = LastMappingSymbols.lookup(Val: Section); |
157 | |
158 | MCELFStreamer::changeSection(Section, Subsection); |
159 | } |
160 | |
161 | void RISCVELFStreamer::emitInstruction(const MCInst &Inst, |
162 | const MCSubtargetInfo &STI) { |
163 | emitInstructionsMappingSymbol(); |
164 | MCELFStreamer::emitInstruction(Inst, STI); |
165 | } |
166 | |
167 | void RISCVELFStreamer::emitBytes(StringRef Data) { |
168 | emitDataMappingSymbol(); |
169 | MCELFStreamer::emitBytes(Data); |
170 | } |
171 | |
172 | void RISCVELFStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue, |
173 | SMLoc Loc) { |
174 | emitDataMappingSymbol(); |
175 | MCELFStreamer::emitFill(NumBytes, FillValue, Loc); |
176 | } |
177 | |
178 | void RISCVELFStreamer::emitValueImpl(const MCExpr *Value, unsigned Size, |
179 | SMLoc Loc) { |
180 | emitDataMappingSymbol(); |
181 | MCELFStreamer::emitValueImpl(Value, Size, Loc); |
182 | } |
183 | |
184 | MCStreamer *llvm::createRISCVELFStreamer(const Triple &, MCContext &C, |
185 | std::unique_ptr<MCAsmBackend> &&MAB, |
186 | std::unique_ptr<MCObjectWriter> &&MOW, |
187 | std::unique_ptr<MCCodeEmitter> &&MCE) { |
188 | return new RISCVELFStreamer(C, std::move(MAB), std::move(MOW), |
189 | std::move(MCE)); |
190 | } |
191 | |