1 | //=== HexagonMCELFStreamer.cpp - Hexagon subclass of MCELFStreamer -------===// |
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 is a stub that parses a MCInst bundle and passes the |
10 | // instructions on to the real streamer. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #include "MCTargetDesc/HexagonMCELFStreamer.h" |
15 | #include "HexagonTargetStreamer.h" |
16 | #include "MCTargetDesc/HexagonMCChecker.h" |
17 | #include "MCTargetDesc/HexagonMCInstrInfo.h" |
18 | #include "MCTargetDesc/HexagonMCShuffler.h" |
19 | #include "llvm/ADT/StringRef.h" |
20 | #include "llvm/BinaryFormat/ELF.h" |
21 | #include "llvm/MC/MCAsmBackend.h" |
22 | #include "llvm/MC/MCAssembler.h" |
23 | #include "llvm/MC/MCCodeEmitter.h" |
24 | #include "llvm/MC/MCContext.h" |
25 | #include "llvm/MC/MCExpr.h" |
26 | #include "llvm/MC/MCInst.h" |
27 | #include "llvm/MC/MCObjectStreamer.h" |
28 | #include "llvm/MC/MCObjectWriter.h" |
29 | #include "llvm/MC/MCSection.h" |
30 | #include "llvm/MC/MCSectionELF.h" |
31 | #include "llvm/MC/MCStreamer.h" |
32 | #include "llvm/MC/MCSubtargetInfo.h" |
33 | #include "llvm/MC/MCSymbol.h" |
34 | #include "llvm/MC/MCSymbolELF.h" |
35 | #include "llvm/Support/Casting.h" |
36 | #include "llvm/Support/CommandLine.h" |
37 | #include "llvm/Support/ErrorHandling.h" |
38 | #include "llvm/Support/HexagonAttributes.h" |
39 | #include "llvm/Support/MathExtras.h" |
40 | #include <cassert> |
41 | #include <cstdint> |
42 | |
43 | #define DEBUG_TYPE "hexagonmcelfstreamer" |
44 | |
45 | using namespace llvm; |
46 | |
47 | static cl::opt<unsigned> GPSize |
48 | ("gpsize" , cl::NotHidden, |
49 | cl::desc("Global Pointer Addressing Size. The default size is 8." ), |
50 | cl::Prefix, |
51 | cl::init(Val: 8)); |
52 | |
53 | HexagonMCELFStreamer::HexagonMCELFStreamer( |
54 | MCContext &Context, std::unique_ptr<MCAsmBackend> TAB, |
55 | std::unique_ptr<MCObjectWriter> OW, std::unique_ptr<MCCodeEmitter> Emitter) |
56 | : MCELFStreamer(Context, std::move(TAB), std::move(OW), std::move(Emitter)), |
57 | MCII(createHexagonMCInstrInfo()) {} |
58 | |
59 | HexagonMCELFStreamer::HexagonMCELFStreamer( |
60 | MCContext &Context, std::unique_ptr<MCAsmBackend> TAB, |
61 | std::unique_ptr<MCObjectWriter> OW, std::unique_ptr<MCCodeEmitter> Emitter, |
62 | MCAssembler *Assembler) |
63 | : MCELFStreamer(Context, std::move(TAB), std::move(OW), std::move(Emitter)), |
64 | MCII(createHexagonMCInstrInfo()) {} |
65 | |
66 | void HexagonMCELFStreamer::emitInstruction(const MCInst &MCB, |
67 | const MCSubtargetInfo &STI) { |
68 | assert(MCB.getOpcode() == Hexagon::BUNDLE); |
69 | assert(HexagonMCInstrInfo::bundleSize(MCB) <= HEXAGON_PACKET_SIZE); |
70 | assert(HexagonMCInstrInfo::bundleSize(MCB) > 0); |
71 | |
72 | // At this point, MCB is a bundle |
73 | // Iterate through the bundle and assign addends for the instructions |
74 | for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCI: MCB)) { |
75 | MCInst *MCI = const_cast<MCInst *>(I.getInst()); |
76 | EmitSymbol(Inst: *MCI); |
77 | } |
78 | |
79 | MCObjectStreamer::emitInstruction(Inst: MCB, STI); |
80 | } |
81 | |
82 | void HexagonMCELFStreamer::EmitSymbol(const MCInst &Inst) { |
83 | // Scan for values. |
84 | for (unsigned i = Inst.getNumOperands(); i--;) |
85 | if (Inst.getOperand(i).isExpr()) |
86 | visitUsedExpr(Expr: *Inst.getOperand(i).getExpr()); |
87 | } |
88 | |
89 | // EmitCommonSymbol and EmitLocalCommonSymbol are extended versions of the |
90 | // functions found in MCELFStreamer.cpp taking AccessSize as an additional |
91 | // parameter. |
92 | void HexagonMCELFStreamer::HexagonMCEmitCommonSymbol(MCSymbol *Symbol, |
93 | uint64_t Size, |
94 | Align ByteAlignment, |
95 | unsigned AccessSize) { |
96 | getAssembler().registerSymbol(Symbol: *Symbol); |
97 | StringRef sbss[4] = {".sbss.1" , ".sbss.2" , ".sbss.4" , ".sbss.8" }; |
98 | |
99 | auto ELFSymbol = cast<MCSymbolELF>(Val: Symbol); |
100 | if (!ELFSymbol->isBindingSet()) { |
101 | ELFSymbol->setBinding(ELF::STB_GLOBAL); |
102 | ELFSymbol->setExternal(true); |
103 | } |
104 | |
105 | ELFSymbol->setType(ELF::STT_OBJECT); |
106 | |
107 | if (ELFSymbol->getBinding() == ELF::STB_LOCAL) { |
108 | StringRef SectionName = |
109 | ((AccessSize == 0) || (Size == 0) || (Size > GPSize)) |
110 | ? ".bss" |
111 | : sbss[(Log2_64(Value: AccessSize))]; |
112 | MCSection &Section = *getAssembler().getContext().getELFSection( |
113 | Section: SectionName, Type: ELF::SHT_NOBITS, Flags: ELF::SHF_WRITE | ELF::SHF_ALLOC); |
114 | MCSectionSubPair P = getCurrentSection(); |
115 | switchSection(Section: &Section); |
116 | |
117 | if (ELFSymbol->isUndefined()) { |
118 | emitValueToAlignment(ByteAlignment, 0, 1, 0); |
119 | emitLabel(Symbol); |
120 | emitZeros(NumBytes: Size); |
121 | } |
122 | |
123 | // Update the maximum alignment of the section if necessary. |
124 | Section.ensureMinAlignment(MinAlignment: ByteAlignment); |
125 | |
126 | switchSection(Section: P.first, Subsection: P.second); |
127 | } else { |
128 | if (ELFSymbol->declareCommon(Size, Alignment: ByteAlignment)) |
129 | report_fatal_error(reason: "Symbol: " + Symbol->getName() + |
130 | " redeclared as different type" ); |
131 | if ((AccessSize) && (Size <= GPSize)) { |
132 | uint64_t SectionIndex = |
133 | (AccessSize <= GPSize) |
134 | ? ELF::SHN_HEXAGON_SCOMMON + llvm::bit_width(Value: AccessSize) |
135 | : (unsigned)ELF::SHN_HEXAGON_SCOMMON; |
136 | ELFSymbol->setIndex(SectionIndex); |
137 | } |
138 | } |
139 | |
140 | ELFSymbol->setSize(MCConstantExpr::create(Value: Size, Ctx&: getContext())); |
141 | } |
142 | |
143 | void HexagonMCELFStreamer::HexagonMCEmitLocalCommonSymbol(MCSymbol *Symbol, |
144 | uint64_t Size, |
145 | Align ByteAlignment, |
146 | unsigned AccessSize) { |
147 | getAssembler().registerSymbol(Symbol: *Symbol); |
148 | auto ELFSymbol = cast<MCSymbolELF>(Val: Symbol); |
149 | ELFSymbol->setBinding(ELF::STB_LOCAL); |
150 | ELFSymbol->setExternal(false); |
151 | HexagonMCEmitCommonSymbol(Symbol, Size, ByteAlignment, AccessSize); |
152 | } |
153 | |
154 | static unsigned featureToArchVersion(unsigned Feature) { |
155 | switch (Feature) { |
156 | case Hexagon::ArchV5: |
157 | return 5; |
158 | case Hexagon::ArchV55: |
159 | return 55; |
160 | case Hexagon::ArchV60: |
161 | case Hexagon::ExtensionHVXV60: |
162 | return 60; |
163 | case Hexagon::ArchV62: |
164 | case Hexagon::ExtensionHVXV62: |
165 | return 62; |
166 | case Hexagon::ArchV65: |
167 | case Hexagon::ExtensionHVXV65: |
168 | return 65; |
169 | case Hexagon::ArchV66: |
170 | case Hexagon::ExtensionHVXV66: |
171 | return 66; |
172 | case Hexagon::ArchV67: |
173 | case Hexagon::ExtensionHVXV67: |
174 | return 67; |
175 | case Hexagon::ArchV68: |
176 | case Hexagon::ExtensionHVXV68: |
177 | return 68; |
178 | case Hexagon::ArchV69: |
179 | case Hexagon::ExtensionHVXV69: |
180 | return 69; |
181 | case Hexagon::ArchV71: |
182 | case Hexagon::ExtensionHVXV71: |
183 | return 71; |
184 | case Hexagon::ArchV73: |
185 | case Hexagon::ExtensionHVXV73: |
186 | return 73; |
187 | } |
188 | llvm_unreachable("Expected valid arch feature" ); |
189 | return 0; |
190 | } |
191 | |
192 | void HexagonTargetStreamer::emitTargetAttributes(const MCSubtargetInfo &STI) { |
193 | auto Features = STI.getFeatureBits(); |
194 | unsigned Arch = featureToArchVersion(Feature: Hexagon_MC::getArchVersion(Features)); |
195 | std::optional<unsigned> HVXArch = Hexagon_MC::getHVXVersion(Features); |
196 | emitAttribute(Attribute: HexagonAttrs::ARCH, Value: Arch); |
197 | if (HVXArch) |
198 | emitAttribute(Attribute: HexagonAttrs::HVXARCH, Value: featureToArchVersion(Feature: *HVXArch)); |
199 | if (Features.test(Hexagon::I: ExtensionHVXIEEEFP)) |
200 | emitAttribute(Attribute: HexagonAttrs::HVXIEEEFP, Value: 1); |
201 | if (Features.test(Hexagon::I: ExtensionHVXQFloat)) |
202 | emitAttribute(Attribute: HexagonAttrs::HVXQFLOAT, Value: 1); |
203 | if (Features.test(Hexagon::I: ExtensionZReg)) |
204 | emitAttribute(Attribute: HexagonAttrs::ZREG, Value: 1); |
205 | if (Features.test(Hexagon::I: ExtensionAudio)) |
206 | emitAttribute(Attribute: HexagonAttrs::AUDIO, Value: 1); |
207 | if (Features.test(Hexagon::I: FeatureCabac)) |
208 | emitAttribute(Attribute: HexagonAttrs::CABAC, Value: 1); |
209 | } |
210 | |
211 | namespace llvm { |
212 | MCStreamer *createHexagonELFStreamer(Triple const &TT, MCContext &Context, |
213 | std::unique_ptr<MCAsmBackend> MAB, |
214 | std::unique_ptr<MCObjectWriter> OW, |
215 | std::unique_ptr<MCCodeEmitter> CE) { |
216 | return new HexagonMCELFStreamer(Context, std::move(MAB), std::move(OW), |
217 | std::move(CE)); |
218 | } |
219 | |
220 | } // end namespace llvm |
221 | |