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 | |
103 | ELFSymbol->setType(ELF::STT_OBJECT); |
104 | |
105 | if (ELFSymbol->getBinding() == ELF::STB_LOCAL) { |
106 | StringRef SectionName = |
107 | ((AccessSize == 0) || (Size == 0) || (Size > GPSize)) |
108 | ? ".bss" |
109 | : sbss[(Log2_64(Value: AccessSize))]; |
110 | MCSection &Section = *getAssembler().getContext().getELFSection( |
111 | Section: SectionName, Type: ELF::SHT_NOBITS, Flags: ELF::SHF_WRITE | ELF::SHF_ALLOC); |
112 | MCSectionSubPair P = getCurrentSection(); |
113 | switchSection(Section: &Section); |
114 | |
115 | if (ELFSymbol->isUndefined()) { |
116 | emitValueToAlignment(ByteAlignment, 0, 1, 0); |
117 | emitLabel(Symbol); |
118 | emitZeros(NumBytes: Size); |
119 | } |
120 | |
121 | // Update the maximum alignment of the section if necessary. |
122 | Section.ensureMinAlignment(MinAlignment: ByteAlignment); |
123 | |
124 | switchSection(Section: P.first, Subsec: P.second); |
125 | } else { |
126 | if (ELFSymbol->declareCommon(Size, Alignment: ByteAlignment)) |
127 | report_fatal_error(reason: "Symbol: " + Symbol->getName() + |
128 | " redeclared as different type" ); |
129 | if ((AccessSize) && (Size <= GPSize)) { |
130 | uint64_t SectionIndex = |
131 | (AccessSize <= GPSize) |
132 | ? ELF::SHN_HEXAGON_SCOMMON + llvm::bit_width(Value: AccessSize) |
133 | : (unsigned)ELF::SHN_HEXAGON_SCOMMON; |
134 | ELFSymbol->setIndex(SectionIndex); |
135 | } |
136 | } |
137 | |
138 | ELFSymbol->setSize(MCConstantExpr::create(Value: Size, Ctx&: getContext())); |
139 | } |
140 | |
141 | void HexagonMCELFStreamer::HexagonMCEmitLocalCommonSymbol(MCSymbol *Symbol, |
142 | uint64_t Size, |
143 | Align ByteAlignment, |
144 | unsigned AccessSize) { |
145 | getAssembler().registerSymbol(Symbol: *Symbol); |
146 | auto ELFSymbol = cast<MCSymbolELF>(Val: Symbol); |
147 | ELFSymbol->setBinding(ELF::STB_LOCAL); |
148 | ELFSymbol->setExternal(false); |
149 | HexagonMCEmitCommonSymbol(Symbol, Size, ByteAlignment, AccessSize); |
150 | } |
151 | |
152 | static unsigned featureToArchVersion(unsigned Feature) { |
153 | switch (Feature) { |
154 | case Hexagon::ArchV5: |
155 | return 5; |
156 | case Hexagon::ArchV55: |
157 | return 55; |
158 | case Hexagon::ArchV60: |
159 | case Hexagon::ExtensionHVXV60: |
160 | return 60; |
161 | case Hexagon::ArchV62: |
162 | case Hexagon::ExtensionHVXV62: |
163 | return 62; |
164 | case Hexagon::ArchV65: |
165 | case Hexagon::ExtensionHVXV65: |
166 | return 65; |
167 | case Hexagon::ArchV66: |
168 | case Hexagon::ExtensionHVXV66: |
169 | return 66; |
170 | case Hexagon::ArchV67: |
171 | case Hexagon::ExtensionHVXV67: |
172 | return 67; |
173 | case Hexagon::ArchV68: |
174 | case Hexagon::ExtensionHVXV68: |
175 | return 68; |
176 | case Hexagon::ArchV69: |
177 | case Hexagon::ExtensionHVXV69: |
178 | return 69; |
179 | case Hexagon::ArchV71: |
180 | case Hexagon::ExtensionHVXV71: |
181 | return 71; |
182 | case Hexagon::ArchV73: |
183 | case Hexagon::ExtensionHVXV73: |
184 | return 73; |
185 | } |
186 | llvm_unreachable("Expected valid arch feature" ); |
187 | return 0; |
188 | } |
189 | |
190 | void HexagonTargetStreamer::emitTargetAttributes(const MCSubtargetInfo &STI) { |
191 | auto Features = STI.getFeatureBits(); |
192 | unsigned Arch = featureToArchVersion(Feature: Hexagon_MC::getArchVersion(Features)); |
193 | std::optional<unsigned> HVXArch = Hexagon_MC::getHVXVersion(Features); |
194 | emitAttribute(Attribute: HexagonAttrs::ARCH, Value: Arch); |
195 | if (HVXArch) |
196 | emitAttribute(Attribute: HexagonAttrs::HVXARCH, Value: featureToArchVersion(Feature: *HVXArch)); |
197 | if (Features.test(I: Hexagon::ExtensionHVXIEEEFP)) |
198 | emitAttribute(Attribute: HexagonAttrs::HVXIEEEFP, Value: 1); |
199 | if (Features.test(I: Hexagon::ExtensionHVXQFloat)) |
200 | emitAttribute(Attribute: HexagonAttrs::HVXQFLOAT, Value: 1); |
201 | if (Features.test(I: Hexagon::ExtensionZReg)) |
202 | emitAttribute(Attribute: HexagonAttrs::ZREG, Value: 1); |
203 | if (Features.test(I: Hexagon::ExtensionAudio)) |
204 | emitAttribute(Attribute: HexagonAttrs::AUDIO, Value: 1); |
205 | if (Features.test(I: Hexagon::FeatureCabac)) |
206 | emitAttribute(Attribute: HexagonAttrs::CABAC, Value: 1); |
207 | } |
208 | |
209 | namespace llvm { |
210 | MCStreamer *createHexagonELFStreamer(Triple const &TT, MCContext &Context, |
211 | std::unique_ptr<MCAsmBackend> MAB, |
212 | std::unique_ptr<MCObjectWriter> OW, |
213 | std::unique_ptr<MCCodeEmitter> CE) { |
214 | return new HexagonMCELFStreamer(Context, std::move(MAB), std::move(OW), |
215 | std::move(CE)); |
216 | } |
217 | |
218 | } // end namespace llvm |
219 | |