/src/llvm-project/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- HexagonMCCodeEmitter.cpp - Hexagon Target Descriptions -------------===// |
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 | | #include "MCTargetDesc/HexagonMCCodeEmitter.h" |
10 | | #include "MCTargetDesc/HexagonBaseInfo.h" |
11 | | #include "MCTargetDesc/HexagonFixupKinds.h" |
12 | | #include "MCTargetDesc/HexagonMCExpr.h" |
13 | | #include "MCTargetDesc/HexagonMCInstrInfo.h" |
14 | | #include "MCTargetDesc/HexagonMCTargetDesc.h" |
15 | | #include "llvm/ADT/Statistic.h" |
16 | | #include "llvm/MC/MCContext.h" |
17 | | #include "llvm/MC/MCExpr.h" |
18 | | #include "llvm/MC/MCFixup.h" |
19 | | #include "llvm/MC/MCInst.h" |
20 | | #include "llvm/MC/MCInstrDesc.h" |
21 | | #include "llvm/MC/MCInstrInfo.h" |
22 | | #include "llvm/MC/MCRegisterInfo.h" |
23 | | #include "llvm/MC/MCSubtargetInfo.h" |
24 | | #include "llvm/Support/Casting.h" |
25 | | #include "llvm/Support/Compiler.h" |
26 | | #include "llvm/Support/Debug.h" |
27 | | #include "llvm/Support/Endian.h" |
28 | | #include "llvm/Support/EndianStream.h" |
29 | | #include "llvm/Support/ErrorHandling.h" |
30 | | #include "llvm/Support/raw_ostream.h" |
31 | | #include <cassert> |
32 | | #include <cstddef> |
33 | | #include <cstdint> |
34 | | #include <map> |
35 | | #include <string> |
36 | | #include <vector> |
37 | | |
38 | | #define DEBUG_TYPE "mccodeemitter" |
39 | | |
40 | | using namespace llvm; |
41 | | using namespace Hexagon; |
42 | | |
43 | | STATISTIC(MCNumEmitted, "Number of MC instructions emitted"); |
44 | | |
45 | | static const unsigned fixup_Invalid = ~0u; |
46 | | |
47 | | #define _ fixup_Invalid |
48 | | #define P(x) Hexagon::fixup_Hexagon##x |
49 | | static const std::map<unsigned, std::vector<unsigned>> ExtFixups = { |
50 | | { MCSymbolRefExpr::VK_DTPREL, |
51 | | { _, _, _, _, |
52 | | _, _, P(_DTPREL_16_X), P(_DTPREL_11_X), |
53 | | P(_DTPREL_11_X), P(_9_X), _, P(_DTPREL_11_X), |
54 | | P(_DTPREL_16_X), _, _, _, |
55 | | P(_DTPREL_16_X), _, _, _, |
56 | | _, _, _, _, |
57 | | _, _, _, _, |
58 | | _, _, _, _, |
59 | | P(_DTPREL_32_6_X) }}, |
60 | | { MCSymbolRefExpr::VK_GOT, |
61 | | { _, _, _, _, |
62 | | _, _, P(_GOT_11_X), _ /* [1] */, |
63 | | _ /* [1] */, P(_9_X), _, P(_GOT_11_X), |
64 | | P(_GOT_16_X), _, _, _, |
65 | | P(_GOT_16_X), _, _, _, |
66 | | _, _, _, _, |
67 | | _, _, _, _, |
68 | | _, _, _, _, |
69 | | P(_GOT_32_6_X) }}, |
70 | | { MCSymbolRefExpr::VK_GOTREL, |
71 | | { _, _, _, _, |
72 | | _, _, P(_GOTREL_11_X), P(_GOTREL_11_X), |
73 | | P(_GOTREL_11_X), P(_9_X), _, P(_GOTREL_11_X), |
74 | | P(_GOTREL_16_X), _, _, _, |
75 | | P(_GOTREL_16_X), _, _, _, |
76 | | _, _, _, _, |
77 | | _, _, _, _, |
78 | | _, _, _, _, |
79 | | P(_GOTREL_32_6_X) }}, |
80 | | { MCSymbolRefExpr::VK_TPREL, |
81 | | { _, _, _, _, |
82 | | _, _, P(_TPREL_16_X), P(_TPREL_11_X), |
83 | | P(_TPREL_11_X), P(_9_X), _, P(_TPREL_11_X), |
84 | | P(_TPREL_16_X), _, _, _, |
85 | | P(_TPREL_16_X), _, _, _, |
86 | | _, _, _, _, |
87 | | _, _, _, _, |
88 | | _, _, _, _, |
89 | | P(_TPREL_32_6_X) }}, |
90 | | { MCSymbolRefExpr::VK_Hexagon_GD_GOT, |
91 | | { _, _, _, _, |
92 | | _, _, P(_GD_GOT_16_X), P(_GD_GOT_11_X), |
93 | | P(_GD_GOT_11_X), P(_9_X), _, P(_GD_GOT_11_X), |
94 | | P(_GD_GOT_16_X), _, _, _, |
95 | | P(_GD_GOT_16_X), _, _, _, |
96 | | _, _, _, _, |
97 | | _, _, _, _, |
98 | | _, _, _, _, |
99 | | P(_GD_GOT_32_6_X) }}, |
100 | | { MCSymbolRefExpr::VK_Hexagon_GD_PLT, |
101 | | { _, _, _, _, |
102 | | _, _, _, _, |
103 | | _, P(_9_X), _, P(_GD_PLT_B22_PCREL_X), |
104 | | _, _, _, _, |
105 | | _, _, _, _, |
106 | | _, _, P(_GD_PLT_B22_PCREL_X), _, |
107 | | _, _, _, _, |
108 | | _, _, _, _, |
109 | | _ }}, |
110 | | { MCSymbolRefExpr::VK_Hexagon_IE, |
111 | | { _, _, _, _, |
112 | | _, _, P(_IE_16_X), _, |
113 | | _, P(_9_X), _, _, |
114 | | P(_IE_16_X), _, _, _, |
115 | | P(_IE_16_X), _, _, _, |
116 | | _, _, _, _, |
117 | | _, _, _, _, |
118 | | _, _, _, _, |
119 | | P(_IE_32_6_X) }}, |
120 | | { MCSymbolRefExpr::VK_Hexagon_IE_GOT, |
121 | | { _, _, _, _, |
122 | | _, _, P(_IE_GOT_11_X), P(_IE_GOT_11_X), |
123 | | P(_IE_GOT_11_X), P(_9_X), _, P(_IE_GOT_11_X), |
124 | | P(_IE_GOT_16_X), _, _, _, |
125 | | P(_IE_GOT_16_X), _, _, _, |
126 | | _, _, _, _, |
127 | | _, _, _, _, |
128 | | _, _, _, _, |
129 | | P(_IE_GOT_32_6_X) }}, |
130 | | { MCSymbolRefExpr::VK_Hexagon_LD_GOT, |
131 | | { _, _, _, _, |
132 | | _, _, P(_LD_GOT_11_X), P(_LD_GOT_11_X), |
133 | | P(_LD_GOT_11_X), P(_9_X), _, P(_LD_GOT_11_X), |
134 | | P(_LD_GOT_16_X), _, _, _, |
135 | | P(_LD_GOT_16_X), _, _, _, |
136 | | _, _, _, _, |
137 | | _, _, _, _, |
138 | | _, _, _, _, |
139 | | P(_LD_GOT_32_6_X) }}, |
140 | | { MCSymbolRefExpr::VK_Hexagon_LD_PLT, |
141 | | { _, _, _, _, |
142 | | _, _, _, _, |
143 | | _, P(_9_X), _, P(_LD_PLT_B22_PCREL_X), |
144 | | _, _, _, _, |
145 | | _, _, _, _, |
146 | | _, _, P(_LD_PLT_B22_PCREL_X), _, |
147 | | _, _, _, _, |
148 | | _, _, _, _, |
149 | | _ }}, |
150 | | { MCSymbolRefExpr::VK_PCREL, |
151 | | { _, _, _, _, |
152 | | _, _, P(_6_PCREL_X), _, |
153 | | _, P(_9_X), _, _, |
154 | | _, _, _, _, |
155 | | _, _, _, _, |
156 | | _, _, _, _, |
157 | | _, _, _, _, |
158 | | _, _, _, _, |
159 | | P(_32_PCREL) }}, |
160 | | { MCSymbolRefExpr::VK_None, |
161 | | { _, _, _, _, |
162 | | _, _, P(_6_X), P(_8_X), |
163 | | P(_8_X), P(_9_X), P(_10_X), P(_11_X), |
164 | | P(_12_X), P(_B13_PCREL), _, P(_B15_PCREL_X), |
165 | | P(_16_X), _, _, _, |
166 | | _, _, P(_B22_PCREL_X), _, |
167 | | _, _, _, _, |
168 | | _, _, _, _, |
169 | | P(_32_6_X) }}, |
170 | | }; |
171 | | // [1] The fixup is GOT_16_X for signed values and GOT_11_X for unsigned. |
172 | | |
173 | | static const std::map<unsigned, std::vector<unsigned>> StdFixups = { |
174 | | { MCSymbolRefExpr::VK_DTPREL, |
175 | | { _, _, _, _, |
176 | | _, _, _, _, |
177 | | _, _, _, _, |
178 | | _, _, _, _, |
179 | | P(_DTPREL_16), _, _, _, |
180 | | _, _, _, _, |
181 | | _, _, _, _, |
182 | | _, _, _, _, |
183 | | P(_DTPREL_32) }}, |
184 | | { MCSymbolRefExpr::VK_GOT, |
185 | | { _, _, _, _, |
186 | | _, _, _, _, |
187 | | _, _, _, _, |
188 | | _, _, _, _, |
189 | | _, _, _, _, |
190 | | _, _, _, _, |
191 | | _, _, _, _, |
192 | | _, _, _, _, |
193 | | P(_GOT_32) }}, |
194 | | { MCSymbolRefExpr::VK_GOTREL, |
195 | | { _, _, _, _, |
196 | | _, _, _, _, |
197 | | _, _, _, _, |
198 | | _, _, _, _, |
199 | | _ /* [2] */, _, _, _, |
200 | | _, _, _, _, |
201 | | _, _, _, _, |
202 | | _, _, _, _, |
203 | | P(_GOTREL_32) }}, |
204 | | { MCSymbolRefExpr::VK_PLT, |
205 | | { _, _, _, _, |
206 | | _, _, _, _, |
207 | | _, _, _, _, |
208 | | _, _, _, _, |
209 | | _, _, _, _, |
210 | | _, _, P(_PLT_B22_PCREL), _, |
211 | | _, _, _, _, |
212 | | _, _, _, _, |
213 | | _ }}, |
214 | | { MCSymbolRefExpr::VK_TPREL, |
215 | | { _, _, _, _, |
216 | | _, _, _, _, |
217 | | _, _, _, P(_TPREL_11_X), |
218 | | _, _, _, _, |
219 | | P(_TPREL_16), _, _, _, |
220 | | _, _, _, _, |
221 | | _, _, _, _, |
222 | | _, _, _, _, |
223 | | P(_TPREL_32) }}, |
224 | | { MCSymbolRefExpr::VK_Hexagon_GD_GOT, |
225 | | { _, _, _, _, |
226 | | _, _, _, _, |
227 | | _, _, _, _, |
228 | | _, _, _, _, |
229 | | P(_GD_GOT_16), _, _, _, |
230 | | _, _, _, _, |
231 | | _, _, _, _, |
232 | | _, _, _, _, |
233 | | P(_GD_GOT_32) }}, |
234 | | { MCSymbolRefExpr::VK_Hexagon_GD_PLT, |
235 | | { _, _, _, _, |
236 | | _, _, _, _, |
237 | | _, _, _, _, |
238 | | _, _, _, _, |
239 | | _, _, _, _, |
240 | | _, _, P(_GD_PLT_B22_PCREL), _, |
241 | | _, _, _, _, |
242 | | _, _, _, _, |
243 | | _ }}, |
244 | | { MCSymbolRefExpr::VK_Hexagon_GPREL, |
245 | | { _, _, _, _, |
246 | | _, _, _, _, |
247 | | _, _, _, _, |
248 | | _, _, _, _, |
249 | | P(_GPREL16_0), _, _, _, |
250 | | _, _, _, _, |
251 | | _, _, _, _, |
252 | | _, _, _, _, |
253 | | _ }}, |
254 | | { MCSymbolRefExpr::VK_Hexagon_HI16, |
255 | | { _, _, _, _, |
256 | | _, _, _, _, |
257 | | _, _, _, _, |
258 | | _, _, _, _, |
259 | | P(_HI16), _, _, _, |
260 | | _, _, _, _, |
261 | | _, _, _, _, |
262 | | _, _, _, _, |
263 | | _ }}, |
264 | | { MCSymbolRefExpr::VK_Hexagon_IE, |
265 | | { _, _, _, _, |
266 | | _, _, _, _, |
267 | | _, _, _, _, |
268 | | _, _, _, _, |
269 | | _, _, _, _, |
270 | | _, _, _, _, |
271 | | _, _, _, _, |
272 | | _, _, _, _, |
273 | | P(_IE_32) }}, |
274 | | { MCSymbolRefExpr::VK_Hexagon_IE_GOT, |
275 | | { _, _, _, _, |
276 | | _, _, _, _, |
277 | | _, _, _, _, |
278 | | _, _, _, _, |
279 | | P(_IE_GOT_16), _, _, _, |
280 | | _, _, _, _, |
281 | | _, _, _, _, |
282 | | _, _, _, _, |
283 | | P(_IE_GOT_32) }}, |
284 | | { MCSymbolRefExpr::VK_Hexagon_LD_GOT, |
285 | | { _, _, _, _, |
286 | | _, _, _, _, |
287 | | _, _, _, _, |
288 | | _, _, _, _, |
289 | | P(_LD_GOT_16), _, _, _, |
290 | | _, _, _, _, |
291 | | _, _, _, _, |
292 | | _, _, _, _, |
293 | | P(_LD_GOT_32) }}, |
294 | | { MCSymbolRefExpr::VK_Hexagon_LD_PLT, |
295 | | { _, _, _, _, |
296 | | _, _, _, _, |
297 | | _, _, _, _, |
298 | | _, _, _, _, |
299 | | _, _, _, _, |
300 | | _, _, P(_LD_PLT_B22_PCREL), _, |
301 | | _, _, _, _, |
302 | | _, _, _, _, |
303 | | _ }}, |
304 | | { MCSymbolRefExpr::VK_Hexagon_LO16, |
305 | | { _, _, _, _, |
306 | | _, _, _, _, |
307 | | _, _, _, _, |
308 | | _, _, _, _, |
309 | | P(_LO16), _, _, _, |
310 | | _, _, _, _, |
311 | | _, _, _, _, |
312 | | _, _, _, _, |
313 | | _ }}, |
314 | | { MCSymbolRefExpr::VK_PCREL, |
315 | | { _, _, _, _, |
316 | | _, _, _, _, |
317 | | _, _, _, _, |
318 | | _, _, _, _, |
319 | | _, _, _, _, |
320 | | _, _, _, _, |
321 | | _, _, _, _, |
322 | | _, _, _, _, |
323 | | P(_32_PCREL) }}, |
324 | | { MCSymbolRefExpr::VK_None, |
325 | | { _, _, _, _, |
326 | | _, _, _, _, |
327 | | _, _, _, _, |
328 | | _, P(_B13_PCREL), _, P(_B15_PCREL), |
329 | | _, _, _, _, |
330 | | _, _, P(_B22_PCREL), _, |
331 | | _, _, _, _, |
332 | | _, _, _, _, |
333 | | P(_32) }}, |
334 | | }; |
335 | | // |
336 | | // [2] The actual fixup is LO16 or HI16, depending on the instruction. |
337 | | #undef P |
338 | | #undef _ |
339 | | |
340 | | uint32_t HexagonMCCodeEmitter::parseBits(size_t Last, MCInst const &MCB, |
341 | 0 | MCInst const &MCI) const { |
342 | 0 | bool Duplex = HexagonMCInstrInfo::isDuplex(MCII, MCI); |
343 | 0 | if (State.Index == 0) { |
344 | 0 | if (HexagonMCInstrInfo::isInnerLoop(MCB)) { |
345 | 0 | assert(!Duplex); |
346 | 0 | assert(State.Index != Last); |
347 | 0 | return HexagonII::INST_PARSE_LOOP_END; |
348 | 0 | } |
349 | 0 | } |
350 | 0 | if (State.Index == 1) { |
351 | 0 | if (HexagonMCInstrInfo::isOuterLoop(MCB)) { |
352 | 0 | assert(!Duplex); |
353 | 0 | assert(State.Index != Last); |
354 | 0 | return HexagonII::INST_PARSE_LOOP_END; |
355 | 0 | } |
356 | 0 | } |
357 | 0 | if (Duplex) { |
358 | 0 | assert(State.Index == Last); |
359 | 0 | return HexagonII::INST_PARSE_DUPLEX; |
360 | 0 | } |
361 | 0 | if (State.Index == Last) |
362 | 0 | return HexagonII::INST_PARSE_PACKET_END; |
363 | 0 | return HexagonII::INST_PARSE_NOT_END; |
364 | 0 | } |
365 | | |
366 | | /// Emit the bundle. |
367 | | void HexagonMCCodeEmitter::encodeInstruction(const MCInst &MI, |
368 | | SmallVectorImpl<char> &CB, |
369 | | SmallVectorImpl<MCFixup> &Fixups, |
370 | 0 | const MCSubtargetInfo &STI) const { |
371 | 0 | MCInst &HMB = const_cast<MCInst &>(MI); |
372 | |
|
373 | 0 | assert(HexagonMCInstrInfo::isBundle(HMB)); |
374 | 0 | LLVM_DEBUG(dbgs() << "Encoding bundle\n";); |
375 | 0 | State.Addend = 0; |
376 | 0 | State.Extended = false; |
377 | 0 | State.Bundle = &MI; |
378 | 0 | State.Index = 0; |
379 | 0 | size_t Last = HexagonMCInstrInfo::bundleSize(HMB) - 1; |
380 | |
|
381 | 0 | for (auto &I : HexagonMCInstrInfo::bundleInstructions(HMB)) { |
382 | 0 | MCInst &HMI = const_cast<MCInst &>(*I.getInst()); |
383 | |
|
384 | 0 | encodeSingleInstruction(HMI, CB, Fixups, STI, parseBits(Last, HMB, HMI)); |
385 | 0 | State.Extended = HexagonMCInstrInfo::isImmext(HMI); |
386 | 0 | State.Addend += HEXAGON_INSTR_SIZE; |
387 | 0 | ++State.Index; |
388 | 0 | } |
389 | 0 | } |
390 | | |
391 | | static bool RegisterMatches(unsigned Consumer, unsigned Producer, |
392 | 0 | unsigned Producer2) { |
393 | 0 | return (Consumer == Producer) || (Consumer == Producer2) || |
394 | 0 | HexagonMCInstrInfo::IsSingleConsumerRefPairProducer(Producer, |
395 | 0 | Consumer); |
396 | 0 | } |
397 | | |
398 | | void HexagonMCCodeEmitter::encodeSingleInstruction( |
399 | | const MCInst &MI, SmallVectorImpl<char> &CB, |
400 | | SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI, |
401 | 0 | uint32_t Parse) const { |
402 | 0 | assert(!HexagonMCInstrInfo::isBundle(MI)); |
403 | 0 | uint64_t Binary; |
404 | | |
405 | | // Pseudo instructions don't get encoded and shouldn't be here |
406 | | // in the first place! |
407 | 0 | assert(!HexagonMCInstrInfo::getDesc(MCII, MI).isPseudo() && |
408 | 0 | "pseudo-instruction found"); |
409 | 0 | LLVM_DEBUG(dbgs() << "Encoding insn `" |
410 | 0 | << HexagonMCInstrInfo::getName(MCII, MI) << "'\n"); |
411 | |
|
412 | 0 | Binary = getBinaryCodeForInstr(MI, Fixups, STI); |
413 | 0 | unsigned Opc = MI.getOpcode(); |
414 | | |
415 | | // Check for unimplemented instructions. Immediate extenders |
416 | | // are encoded as zero, so they need to be accounted for. |
417 | 0 | if (!Binary && Opc != DuplexIClass0 && Opc != A4_ext) { |
418 | 0 | LLVM_DEBUG(dbgs() << "Unimplemented inst `" |
419 | 0 | << HexagonMCInstrInfo::getName(MCII, MI) << "'\n"); |
420 | 0 | llvm_unreachable("Unimplemented Instruction"); |
421 | 0 | } |
422 | 0 | Binary |= Parse; |
423 | | |
424 | | // if we need to emit a duplexed instruction |
425 | 0 | if (Opc >= Hexagon::DuplexIClass0 && Opc <= Hexagon::DuplexIClassF) { |
426 | 0 | assert(Parse == HexagonII::INST_PARSE_DUPLEX && |
427 | 0 | "Emitting duplex without duplex parse bits"); |
428 | 0 | unsigned DupIClass = MI.getOpcode() - Hexagon::DuplexIClass0; |
429 | | // 29 is the bit position. |
430 | | // 0b1110 =0xE bits are masked off and down shifted by 1 bit. |
431 | | // Last bit is moved to bit position 13 |
432 | 0 | Binary = ((DupIClass & 0xE) << (29 - 1)) | ((DupIClass & 0x1) << 13); |
433 | |
|
434 | 0 | const MCInst *Sub0 = MI.getOperand(0).getInst(); |
435 | 0 | const MCInst *Sub1 = MI.getOperand(1).getInst(); |
436 | | |
437 | | // Get subinstruction slot 0. |
438 | 0 | unsigned SubBits0 = getBinaryCodeForInstr(*Sub0, Fixups, STI); |
439 | | // Get subinstruction slot 1. |
440 | 0 | State.SubInst1 = true; |
441 | 0 | unsigned SubBits1 = getBinaryCodeForInstr(*Sub1, Fixups, STI); |
442 | 0 | State.SubInst1 = false; |
443 | |
|
444 | 0 | Binary |= SubBits0 | (SubBits1 << 16); |
445 | 0 | } |
446 | 0 | support::endian::write<uint32_t>(CB, Binary, llvm::endianness::little); |
447 | 0 | ++MCNumEmitted; |
448 | 0 | } |
449 | | |
450 | 0 | [[noreturn]] static void raise_relocation_error(unsigned Width, unsigned Kind) { |
451 | 0 | std::string Text; |
452 | 0 | raw_string_ostream Stream(Text); |
453 | 0 | Stream << "Unrecognized relocation combination: width=" << Width |
454 | 0 | << " kind=" << Kind; |
455 | 0 | report_fatal_error(Twine(Stream.str())); |
456 | 0 | } |
457 | | |
458 | | /// Some insns are not extended and thus have no bits. These cases require |
459 | | /// a more brute force method for determining the correct relocation. |
460 | | Hexagon::Fixups HexagonMCCodeEmitter::getFixupNoBits( |
461 | | MCInstrInfo const &MCII, const MCInst &MI, const MCOperand &MO, |
462 | 0 | const MCSymbolRefExpr::VariantKind VarKind) const { |
463 | 0 | const MCInstrDesc &MCID = HexagonMCInstrInfo::getDesc(MCII, MI); |
464 | 0 | unsigned InsnType = HexagonMCInstrInfo::getType(MCII, MI); |
465 | 0 | using namespace Hexagon; |
466 | |
|
467 | 0 | if (InsnType == HexagonII::TypeEXTENDER) { |
468 | 0 | if (VarKind == MCSymbolRefExpr::VK_None) { |
469 | 0 | auto Instrs = HexagonMCInstrInfo::bundleInstructions(*State.Bundle); |
470 | 0 | for (auto I = Instrs.begin(), N = Instrs.end(); I != N; ++I) { |
471 | 0 | if (I->getInst() != &MI) |
472 | 0 | continue; |
473 | 0 | assert(I+1 != N && "Extender cannot be last in packet"); |
474 | 0 | const MCInst &NextI = *(I+1)->getInst(); |
475 | 0 | const MCInstrDesc &NextD = HexagonMCInstrInfo::getDesc(MCII, NextI); |
476 | 0 | if (NextD.isBranch() || NextD.isCall() || |
477 | 0 | HexagonMCInstrInfo::getType(MCII, NextI) == HexagonII::TypeCR) |
478 | 0 | return fixup_Hexagon_B32_PCREL_X; |
479 | 0 | return fixup_Hexagon_32_6_X; |
480 | 0 | } |
481 | 0 | } |
482 | | |
483 | 0 | static const std::map<unsigned,unsigned> Relocs = { |
484 | 0 | { MCSymbolRefExpr::VK_GOTREL, fixup_Hexagon_GOTREL_32_6_X }, |
485 | 0 | { MCSymbolRefExpr::VK_GOT, fixup_Hexagon_GOT_32_6_X }, |
486 | 0 | { MCSymbolRefExpr::VK_TPREL, fixup_Hexagon_TPREL_32_6_X }, |
487 | 0 | { MCSymbolRefExpr::VK_DTPREL, fixup_Hexagon_DTPREL_32_6_X }, |
488 | 0 | { MCSymbolRefExpr::VK_Hexagon_GD_GOT, fixup_Hexagon_GD_GOT_32_6_X }, |
489 | 0 | { MCSymbolRefExpr::VK_Hexagon_LD_GOT, fixup_Hexagon_LD_GOT_32_6_X }, |
490 | 0 | { MCSymbolRefExpr::VK_Hexagon_IE, fixup_Hexagon_IE_32_6_X }, |
491 | 0 | { MCSymbolRefExpr::VK_Hexagon_IE_GOT, fixup_Hexagon_IE_GOT_32_6_X }, |
492 | 0 | { MCSymbolRefExpr::VK_PCREL, fixup_Hexagon_B32_PCREL_X }, |
493 | 0 | { MCSymbolRefExpr::VK_Hexagon_GD_PLT, fixup_Hexagon_GD_PLT_B32_PCREL_X }, |
494 | 0 | { MCSymbolRefExpr::VK_Hexagon_LD_PLT, fixup_Hexagon_LD_PLT_B32_PCREL_X }, |
495 | 0 | }; |
496 | |
|
497 | 0 | auto F = Relocs.find(VarKind); |
498 | 0 | if (F != Relocs.end()) |
499 | 0 | return Hexagon::Fixups(F->second); |
500 | 0 | raise_relocation_error(0, VarKind); |
501 | 0 | } |
502 | | |
503 | 0 | if (MCID.isBranch()) |
504 | 0 | return fixup_Hexagon_B13_PCREL; |
505 | | |
506 | 0 | static const std::map<unsigned,unsigned> RelocsLo = { |
507 | 0 | { MCSymbolRefExpr::VK_GOT, fixup_Hexagon_GOT_LO16 }, |
508 | 0 | { MCSymbolRefExpr::VK_GOTREL, fixup_Hexagon_GOTREL_LO16 }, |
509 | 0 | { MCSymbolRefExpr::VK_Hexagon_GD_GOT, fixup_Hexagon_GD_GOT_LO16 }, |
510 | 0 | { MCSymbolRefExpr::VK_Hexagon_LD_GOT, fixup_Hexagon_LD_GOT_LO16 }, |
511 | 0 | { MCSymbolRefExpr::VK_Hexagon_IE, fixup_Hexagon_IE_LO16 }, |
512 | 0 | { MCSymbolRefExpr::VK_Hexagon_IE_GOT, fixup_Hexagon_IE_GOT_LO16 }, |
513 | 0 | { MCSymbolRefExpr::VK_TPREL, fixup_Hexagon_TPREL_LO16 }, |
514 | 0 | { MCSymbolRefExpr::VK_DTPREL, fixup_Hexagon_DTPREL_LO16 }, |
515 | 0 | { MCSymbolRefExpr::VK_None, fixup_Hexagon_LO16 }, |
516 | 0 | }; |
517 | |
|
518 | 0 | static const std::map<unsigned,unsigned> RelocsHi = { |
519 | 0 | { MCSymbolRefExpr::VK_GOT, fixup_Hexagon_GOT_HI16 }, |
520 | 0 | { MCSymbolRefExpr::VK_GOTREL, fixup_Hexagon_GOTREL_HI16 }, |
521 | 0 | { MCSymbolRefExpr::VK_Hexagon_GD_GOT, fixup_Hexagon_GD_GOT_HI16 }, |
522 | 0 | { MCSymbolRefExpr::VK_Hexagon_LD_GOT, fixup_Hexagon_LD_GOT_HI16 }, |
523 | 0 | { MCSymbolRefExpr::VK_Hexagon_IE, fixup_Hexagon_IE_HI16 }, |
524 | 0 | { MCSymbolRefExpr::VK_Hexagon_IE_GOT, fixup_Hexagon_IE_GOT_HI16 }, |
525 | 0 | { MCSymbolRefExpr::VK_TPREL, fixup_Hexagon_TPREL_HI16 }, |
526 | 0 | { MCSymbolRefExpr::VK_DTPREL, fixup_Hexagon_DTPREL_HI16 }, |
527 | 0 | { MCSymbolRefExpr::VK_None, fixup_Hexagon_HI16 }, |
528 | 0 | }; |
529 | |
|
530 | 0 | switch (MCID.getOpcode()) { |
531 | 0 | case Hexagon::LO: |
532 | 0 | case Hexagon::A2_tfril: { |
533 | 0 | auto F = RelocsLo.find(VarKind); |
534 | 0 | if (F != RelocsLo.end()) |
535 | 0 | return Hexagon::Fixups(F->second); |
536 | 0 | break; |
537 | 0 | } |
538 | 0 | case Hexagon::HI: |
539 | 0 | case Hexagon::A2_tfrih: { |
540 | 0 | auto F = RelocsHi.find(VarKind); |
541 | 0 | if (F != RelocsHi.end()) |
542 | 0 | return Hexagon::Fixups(F->second); |
543 | 0 | break; |
544 | 0 | } |
545 | 0 | } |
546 | | |
547 | 0 | raise_relocation_error(0, VarKind); |
548 | 0 | } |
549 | | |
550 | 0 | static bool isPCRel(unsigned Kind) { |
551 | 0 | switch (Kind){ |
552 | 0 | case fixup_Hexagon_B22_PCREL: |
553 | 0 | case fixup_Hexagon_B15_PCREL: |
554 | 0 | case fixup_Hexagon_B7_PCREL: |
555 | 0 | case fixup_Hexagon_B13_PCREL: |
556 | 0 | case fixup_Hexagon_B9_PCREL: |
557 | 0 | case fixup_Hexagon_B32_PCREL_X: |
558 | 0 | case fixup_Hexagon_B22_PCREL_X: |
559 | 0 | case fixup_Hexagon_B15_PCREL_X: |
560 | 0 | case fixup_Hexagon_B13_PCREL_X: |
561 | 0 | case fixup_Hexagon_B9_PCREL_X: |
562 | 0 | case fixup_Hexagon_B7_PCREL_X: |
563 | 0 | case fixup_Hexagon_32_PCREL: |
564 | 0 | case fixup_Hexagon_PLT_B22_PCREL: |
565 | 0 | case fixup_Hexagon_GD_PLT_B22_PCREL: |
566 | 0 | case fixup_Hexagon_LD_PLT_B22_PCREL: |
567 | 0 | case fixup_Hexagon_GD_PLT_B22_PCREL_X: |
568 | 0 | case fixup_Hexagon_LD_PLT_B22_PCREL_X: |
569 | 0 | case fixup_Hexagon_6_PCREL_X: |
570 | 0 | return true; |
571 | 0 | default: |
572 | 0 | return false; |
573 | 0 | } |
574 | 0 | } |
575 | | |
576 | | unsigned HexagonMCCodeEmitter::getExprOpValue(const MCInst &MI, |
577 | | const MCOperand &MO, const MCExpr *ME, SmallVectorImpl<MCFixup> &Fixups, |
578 | 0 | const MCSubtargetInfo &STI) const { |
579 | 0 | if (isa<HexagonMCExpr>(ME)) |
580 | 0 | ME = &HexagonMCInstrInfo::getExpr(*ME); |
581 | 0 | int64_t Value; |
582 | 0 | if (ME->evaluateAsAbsolute(Value)) { |
583 | 0 | bool InstExtendable = HexagonMCInstrInfo::isExtendable(MCII, MI) || |
584 | 0 | HexagonMCInstrInfo::isExtended(MCII, MI); |
585 | | // Only sub-instruction #1 can be extended in a duplex. If MI is a |
586 | | // sub-instruction #0, it is not extended even if Extended is true |
587 | | // (it can be true for the duplex as a whole). |
588 | 0 | bool IsSub0 = HexagonMCInstrInfo::isSubInstruction(MI) && !State.SubInst1; |
589 | 0 | if (State.Extended && InstExtendable && !IsSub0) { |
590 | 0 | unsigned OpIdx = ~0u; |
591 | 0 | for (unsigned I = 0, E = MI.getNumOperands(); I != E; ++I) { |
592 | 0 | if (&MO != &MI.getOperand(I)) |
593 | 0 | continue; |
594 | 0 | OpIdx = I; |
595 | 0 | break; |
596 | 0 | } |
597 | 0 | assert(OpIdx != ~0u); |
598 | 0 | if (OpIdx == HexagonMCInstrInfo::getExtendableOp(MCII, MI)) { |
599 | 0 | unsigned Shift = HexagonMCInstrInfo::getExtentAlignment(MCII, MI); |
600 | 0 | Value = (Value & 0x3f) << Shift; |
601 | 0 | } |
602 | 0 | } |
603 | 0 | return Value; |
604 | 0 | } |
605 | 0 | assert(ME->getKind() == MCExpr::SymbolRef || |
606 | 0 | ME->getKind() == MCExpr::Binary); |
607 | 0 | if (ME->getKind() == MCExpr::Binary) { |
608 | 0 | MCBinaryExpr const *Binary = cast<MCBinaryExpr>(ME); |
609 | 0 | getExprOpValue(MI, MO, Binary->getLHS(), Fixups, STI); |
610 | 0 | getExprOpValue(MI, MO, Binary->getRHS(), Fixups, STI); |
611 | 0 | return 0; |
612 | 0 | } |
613 | | |
614 | 0 | unsigned FixupKind = fixup_Invalid; |
615 | 0 | const MCSymbolRefExpr *MCSRE = static_cast<const MCSymbolRefExpr *>(ME); |
616 | 0 | const MCInstrDesc &MCID = HexagonMCInstrInfo::getDesc(MCII, MI); |
617 | 0 | unsigned FixupWidth = HexagonMCInstrInfo::getExtentBits(MCII, MI) - |
618 | 0 | HexagonMCInstrInfo::getExtentAlignment(MCII, MI); |
619 | 0 | MCSymbolRefExpr::VariantKind VarKind = MCSRE->getKind(); |
620 | 0 | unsigned Opc = MCID.getOpcode(); |
621 | 0 | unsigned IType = HexagonMCInstrInfo::getType(MCII, MI); |
622 | |
|
623 | 0 | LLVM_DEBUG(dbgs() << "----------------------------------------\n" |
624 | 0 | << "Opcode Name: " << HexagonMCInstrInfo::getName(MCII, MI) |
625 | 0 | << "\nOpcode: " << Opc << "\nRelocation bits: " |
626 | 0 | << FixupWidth << "\nAddend: " << State.Addend |
627 | 0 | << "\nVariant: " << unsigned(VarKind) |
628 | 0 | << "\n----------------------------------------\n"); |
629 | | |
630 | | // Pick the applicable fixup kind for the symbol. |
631 | | // Handle special cases first, the rest will be looked up in the tables. |
632 | |
|
633 | 0 | if (FixupWidth == 16 && !State.Extended) { |
634 | 0 | if (VarKind == MCSymbolRefExpr::VK_None) { |
635 | 0 | if (HexagonMCInstrInfo::s27_2_reloc(*MO.getExpr())) { |
636 | | // A2_iconst. |
637 | 0 | FixupKind = Hexagon::fixup_Hexagon_27_REG; |
638 | 0 | } else { |
639 | | // Look for GP-relative fixups. |
640 | 0 | unsigned Shift = HexagonMCInstrInfo::getExtentAlignment(MCII, MI); |
641 | 0 | static const Hexagon::Fixups GPRelFixups[] = { |
642 | 0 | Hexagon::fixup_Hexagon_GPREL16_0, Hexagon::fixup_Hexagon_GPREL16_1, |
643 | 0 | Hexagon::fixup_Hexagon_GPREL16_2, Hexagon::fixup_Hexagon_GPREL16_3 |
644 | 0 | }; |
645 | 0 | assert(Shift < std::size(GPRelFixups)); |
646 | 0 | auto UsesGP = [](const MCInstrDesc &D) { |
647 | 0 | return is_contained(D.implicit_uses(), Hexagon::GP); |
648 | 0 | }; |
649 | 0 | if (UsesGP(MCID)) |
650 | 0 | FixupKind = GPRelFixups[Shift]; |
651 | 0 | } |
652 | 0 | } else if (VarKind == MCSymbolRefExpr::VK_GOTREL) { |
653 | | // Select between LO/HI. |
654 | 0 | if (Opc == Hexagon::LO) |
655 | 0 | FixupKind = Hexagon::fixup_Hexagon_GOTREL_LO16; |
656 | 0 | else if (Opc == Hexagon::HI) |
657 | 0 | FixupKind = Hexagon::fixup_Hexagon_GOTREL_HI16; |
658 | 0 | } |
659 | 0 | } else { |
660 | 0 | bool BranchOrCR = MCID.isBranch() || IType == HexagonII::TypeCR; |
661 | 0 | switch (FixupWidth) { |
662 | 0 | case 9: |
663 | 0 | if (BranchOrCR) |
664 | 0 | FixupKind = State.Extended ? Hexagon::fixup_Hexagon_B9_PCREL_X |
665 | 0 | : Hexagon::fixup_Hexagon_B9_PCREL; |
666 | 0 | break; |
667 | 0 | case 8: |
668 | 0 | case 7: |
669 | 0 | if (State.Extended && VarKind == MCSymbolRefExpr::VK_GOT) |
670 | 0 | FixupKind = HexagonMCInstrInfo::isExtentSigned(MCII, MI) |
671 | 0 | ? Hexagon::fixup_Hexagon_GOT_16_X |
672 | 0 | : Hexagon::fixup_Hexagon_GOT_11_X; |
673 | 0 | else if (FixupWidth == 7 && BranchOrCR) |
674 | 0 | FixupKind = State.Extended ? Hexagon::fixup_Hexagon_B7_PCREL_X |
675 | 0 | : Hexagon::fixup_Hexagon_B7_PCREL; |
676 | 0 | break; |
677 | 0 | case 0: |
678 | 0 | FixupKind = getFixupNoBits(MCII, MI, MO, VarKind); |
679 | 0 | break; |
680 | 0 | } |
681 | 0 | } |
682 | | |
683 | 0 | if (FixupKind == fixup_Invalid) { |
684 | 0 | const auto &FixupTable = State.Extended ? ExtFixups : StdFixups; |
685 | |
|
686 | 0 | auto FindVK = FixupTable.find(VarKind); |
687 | 0 | if (FindVK != FixupTable.end()) |
688 | 0 | FixupKind = FindVK->second[FixupWidth]; |
689 | 0 | } |
690 | |
|
691 | 0 | if (FixupKind == fixup_Invalid) |
692 | 0 | raise_relocation_error(FixupWidth, VarKind); |
693 | |
|
694 | 0 | const MCExpr *FixupExpr = MO.getExpr(); |
695 | 0 | if (State.Addend != 0 && isPCRel(FixupKind)) { |
696 | 0 | const MCExpr *C = MCConstantExpr::create(State.Addend, MCT); |
697 | 0 | FixupExpr = MCBinaryExpr::createAdd(FixupExpr, C, MCT); |
698 | 0 | } |
699 | |
|
700 | 0 | MCFixup Fixup = MCFixup::create(State.Addend, FixupExpr, |
701 | 0 | MCFixupKind(FixupKind), MI.getLoc()); |
702 | 0 | Fixups.push_back(Fixup); |
703 | | // All of the information is in the fixup. |
704 | 0 | return 0; |
705 | 0 | } |
706 | | |
707 | | unsigned |
708 | | HexagonMCCodeEmitter::getMachineOpValue(MCInst const &MI, MCOperand const &MO, |
709 | | SmallVectorImpl<MCFixup> &Fixups, |
710 | 0 | MCSubtargetInfo const &STI) const { |
711 | 0 | size_t OperandNumber = ~0U; |
712 | 0 | for (unsigned i = 0, n = MI.getNumOperands(); i < n; ++i) |
713 | 0 | if (&MI.getOperand(i) == &MO) { |
714 | 0 | OperandNumber = i; |
715 | 0 | break; |
716 | 0 | } |
717 | 0 | assert((OperandNumber != ~0U) && "Operand not found"); |
718 | | |
719 | 0 | if (HexagonMCInstrInfo::isNewValue(MCII, MI) && |
720 | 0 | &MO == &HexagonMCInstrInfo::getNewValueOperand(MCII, MI)) { |
721 | | // Calculate the new value distance to the associated producer |
722 | 0 | unsigned SOffset = 0; |
723 | 0 | unsigned VOffset = 0; |
724 | 0 | unsigned UseReg = MO.getReg(); |
725 | 0 | unsigned DefReg1 = Hexagon::NoRegister; |
726 | 0 | unsigned DefReg2 = Hexagon::NoRegister; |
727 | |
|
728 | 0 | auto Instrs = HexagonMCInstrInfo::bundleInstructions(*State.Bundle); |
729 | 0 | const MCOperand *I = Instrs.begin() + State.Index - 1; |
730 | |
|
731 | 0 | for (;; --I) { |
732 | 0 | assert(I != Instrs.begin() - 1 && "Couldn't find producer"); |
733 | 0 | MCInst const &Inst = *I->getInst(); |
734 | 0 | if (HexagonMCInstrInfo::isImmext(Inst)) |
735 | 0 | continue; |
736 | | |
737 | 0 | DefReg1 = Hexagon::NoRegister; |
738 | 0 | DefReg2 = Hexagon::NoRegister; |
739 | 0 | ++SOffset; |
740 | 0 | if (HexagonMCInstrInfo::isVector(MCII, Inst)) { |
741 | | // Vector instructions don't count scalars. |
742 | 0 | ++VOffset; |
743 | 0 | } |
744 | 0 | if (HexagonMCInstrInfo::hasNewValue(MCII, Inst)) |
745 | 0 | DefReg1 = HexagonMCInstrInfo::getNewValueOperand(MCII, Inst).getReg(); |
746 | 0 | if (HexagonMCInstrInfo::hasNewValue2(MCII, Inst)) |
747 | 0 | DefReg2 = HexagonMCInstrInfo::getNewValueOperand2(MCII, Inst).getReg(); |
748 | 0 | if (!RegisterMatches(UseReg, DefReg1, DefReg2)) { |
749 | | // This isn't the register we're looking for |
750 | 0 | continue; |
751 | 0 | } |
752 | 0 | if (!HexagonMCInstrInfo::isPredicated(MCII, Inst)) { |
753 | | // Producer is unpredicated |
754 | 0 | break; |
755 | 0 | } |
756 | 0 | assert(HexagonMCInstrInfo::isPredicated(MCII, MI) && |
757 | 0 | "Unpredicated consumer depending on predicated producer"); |
758 | 0 | if (HexagonMCInstrInfo::isPredicatedTrue(MCII, Inst) == |
759 | 0 | HexagonMCInstrInfo::isPredicatedTrue(MCII, MI)) |
760 | | // Producer predicate sense matched ours. |
761 | 0 | break; |
762 | 0 | } |
763 | | // Hexagon PRM 10.11 Construct Nt from distance |
764 | 0 | unsigned Offset = HexagonMCInstrInfo::isVector(MCII, MI) ? VOffset |
765 | 0 | : SOffset; |
766 | 0 | Offset <<= 1; |
767 | 0 | Offset |= HexagonMCInstrInfo::SubregisterBit(UseReg, DefReg1, DefReg2); |
768 | 0 | return Offset; |
769 | 0 | } |
770 | | |
771 | 0 | assert(!MO.isImm()); |
772 | 0 | if (MO.isReg()) { |
773 | 0 | unsigned Reg = MO.getReg(); |
774 | 0 | switch (HexagonMCInstrInfo::getDesc(MCII, MI) |
775 | 0 | .operands()[OperandNumber] |
776 | 0 | .RegClass) { |
777 | 0 | case GeneralSubRegsRegClassID: |
778 | 0 | case GeneralDoubleLow8RegsRegClassID: |
779 | 0 | return HexagonMCInstrInfo::getDuplexRegisterNumbering(Reg); |
780 | 0 | default: |
781 | 0 | break; |
782 | 0 | } |
783 | 0 | return MCT.getRegisterInfo()->getEncodingValue(Reg); |
784 | 0 | } |
785 | | |
786 | 0 | return getExprOpValue(MI, MO, MO.getExpr(), Fixups, STI); |
787 | 0 | } |
788 | | |
789 | | MCCodeEmitter *llvm::createHexagonMCCodeEmitter(MCInstrInfo const &MII, |
790 | 0 | MCContext &MCT) { |
791 | 0 | return new HexagonMCCodeEmitter(MII, MCT); |
792 | 0 | } |
793 | | |
794 | | #include "HexagonGenMCCodeEmitter.inc" |