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 | MCInst const &MCI) const { |
342 | bool Duplex = HexagonMCInstrInfo::isDuplex(MCII, MCI); |
343 | if (State.Index == 0) { |
344 | if (HexagonMCInstrInfo::isInnerLoop(MCI: MCB)) { |
345 | assert(!Duplex); |
346 | assert(State.Index != Last); |
347 | return HexagonII::INST_PARSE_LOOP_END; |
348 | } |
349 | } |
350 | if (State.Index == 1) { |
351 | if (HexagonMCInstrInfo::isOuterLoop(MCI: MCB)) { |
352 | assert(!Duplex); |
353 | assert(State.Index != Last); |
354 | return HexagonII::INST_PARSE_LOOP_END; |
355 | } |
356 | } |
357 | if (Duplex) { |
358 | assert(State.Index == Last); |
359 | return HexagonII::INST_PARSE_DUPLEX; |
360 | } |
361 | if (State.Index == Last) |
362 | return HexagonII::INST_PARSE_PACKET_END; |
363 | return HexagonII::INST_PARSE_NOT_END; |
364 | } |
365 | |
366 | /// Emit the bundle. |
367 | void HexagonMCCodeEmitter::encodeInstruction(const MCInst &MI, |
368 | SmallVectorImpl<char> &CB, |
369 | SmallVectorImpl<MCFixup> &Fixups, |
370 | const MCSubtargetInfo &STI) const { |
371 | MCInst &HMB = const_cast<MCInst &>(MI); |
372 | |
373 | assert(HexagonMCInstrInfo::isBundle(HMB)); |
374 | LLVM_DEBUG(dbgs() << "Encoding bundle\n" ;); |
375 | State.Addend = 0; |
376 | State.Extended = false; |
377 | State.Bundle = &MI; |
378 | State.Index = 0; |
379 | size_t Last = HexagonMCInstrInfo::bundleSize(MCI: HMB) - 1; |
380 | |
381 | for (auto &I : HexagonMCInstrInfo::bundleInstructions(MCI: HMB)) { |
382 | MCInst &HMI = const_cast<MCInst &>(*I.getInst()); |
383 | |
384 | encodeSingleInstruction(MI: HMI, CB, Fixups, STI, Parse: parseBits(Last, MCB: HMB, MCI: HMI)); |
385 | State.Extended = HexagonMCInstrInfo::isImmext(MCI: HMI); |
386 | State.Addend += HEXAGON_INSTR_SIZE; |
387 | ++State.Index; |
388 | } |
389 | } |
390 | |
391 | static bool RegisterMatches(unsigned Consumer, unsigned Producer, |
392 | unsigned Producer2) { |
393 | return (Consumer == Producer) || (Consumer == Producer2) || |
394 | HexagonMCInstrInfo::IsSingleConsumerRefPairProducer(Producer, |
395 | Consumer); |
396 | } |
397 | |
398 | void HexagonMCCodeEmitter::encodeSingleInstruction( |
399 | const MCInst &MI, SmallVectorImpl<char> &CB, |
400 | SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI, |
401 | uint32_t Parse) const { |
402 | assert(!HexagonMCInstrInfo::isBundle(MI)); |
403 | uint64_t Binary; |
404 | |
405 | // Pseudo instructions don't get encoded and shouldn't be here |
406 | // in the first place! |
407 | assert(!HexagonMCInstrInfo::getDesc(MCII, MI).isPseudo() && |
408 | "pseudo-instruction found" ); |
409 | LLVM_DEBUG(dbgs() << "Encoding insn `" |
410 | << HexagonMCInstrInfo::getName(MCII, MI) << "'\n" ); |
411 | |
412 | Binary = getBinaryCodeForInstr(MI, Fixups, STI); |
413 | 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 | if (!Binary && Opc != DuplexIClass0 && Opc != A4_ext) { |
418 | LLVM_DEBUG(dbgs() << "Unimplemented inst `" |
419 | << HexagonMCInstrInfo::getName(MCII, MI) << "'\n" ); |
420 | llvm_unreachable("Unimplemented Instruction" ); |
421 | } |
422 | Binary |= Parse; |
423 | |
424 | // if we need to emit a duplexed instruction |
425 | if (Opc >= Hexagon::DuplexIClass0 && Opc <= Hexagon::DuplexIClassF) { |
426 | assert(Parse == HexagonII::INST_PARSE_DUPLEX && |
427 | "Emitting duplex without duplex parse bits" ); |
428 | 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 | Binary = ((DupIClass & 0xE) << (29 - 1)) | ((DupIClass & 0x1) << 13); |
433 | |
434 | const MCInst *Sub0 = MI.getOperand(i: 0).getInst(); |
435 | const MCInst *Sub1 = MI.getOperand(i: 1).getInst(); |
436 | |
437 | // Get subinstruction slot 0. |
438 | unsigned SubBits0 = getBinaryCodeForInstr(MI: *Sub0, Fixups, STI); |
439 | // Get subinstruction slot 1. |
440 | State.SubInst1 = true; |
441 | unsigned SubBits1 = getBinaryCodeForInstr(MI: *Sub1, Fixups, STI); |
442 | State.SubInst1 = false; |
443 | |
444 | Binary |= SubBits0 | (SubBits1 << 16); |
445 | } |
446 | support::endian::write<uint32_t>(Out&: CB, V: Binary, E: llvm::endianness::little); |
447 | ++MCNumEmitted; |
448 | } |
449 | |
450 | [[noreturn]] static void raise_relocation_error(unsigned Width, unsigned Kind) { |
451 | std::string Text; |
452 | raw_string_ostream Stream(Text); |
453 | Stream << "Unrecognized relocation combination: width=" << Width |
454 | << " kind=" << Kind; |
455 | report_fatal_error(reason: Twine(Stream.str())); |
456 | } |
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 | const MCSymbolRefExpr::VariantKind VarKind) const { |
463 | const MCInstrDesc &MCID = HexagonMCInstrInfo::getDesc(MCII, MCI: MI); |
464 | unsigned InsnType = HexagonMCInstrInfo::getType(MCII, MCI: MI); |
465 | using namespace Hexagon; |
466 | |
467 | if (InsnType == HexagonII::TypeEXTENDER) { |
468 | if (VarKind == MCSymbolRefExpr::VK_None) { |
469 | auto Instrs = HexagonMCInstrInfo::bundleInstructions(MCI: *State.Bundle); |
470 | for (auto I = Instrs.begin(), N = Instrs.end(); I != N; ++I) { |
471 | if (I->getInst() != &MI) |
472 | continue; |
473 | assert(I+1 != N && "Extender cannot be last in packet" ); |
474 | const MCInst &NextI = *(I+1)->getInst(); |
475 | const MCInstrDesc &NextD = HexagonMCInstrInfo::getDesc(MCII, MCI: NextI); |
476 | if (NextD.isBranch() || NextD.isCall() || |
477 | HexagonMCInstrInfo::getType(MCII, MCI: NextI) == HexagonII::TypeCR) |
478 | return fixup_Hexagon_B32_PCREL_X; |
479 | return fixup_Hexagon_32_6_X; |
480 | } |
481 | } |
482 | |
483 | static const std::map<unsigned,unsigned> Relocs = { |
484 | { MCSymbolRefExpr::VK_GOTREL, fixup_Hexagon_GOTREL_32_6_X }, |
485 | { MCSymbolRefExpr::VK_GOT, fixup_Hexagon_GOT_32_6_X }, |
486 | { MCSymbolRefExpr::VK_TPREL, fixup_Hexagon_TPREL_32_6_X }, |
487 | { MCSymbolRefExpr::VK_DTPREL, fixup_Hexagon_DTPREL_32_6_X }, |
488 | { MCSymbolRefExpr::VK_Hexagon_GD_GOT, fixup_Hexagon_GD_GOT_32_6_X }, |
489 | { MCSymbolRefExpr::VK_Hexagon_LD_GOT, fixup_Hexagon_LD_GOT_32_6_X }, |
490 | { MCSymbolRefExpr::VK_Hexagon_IE, fixup_Hexagon_IE_32_6_X }, |
491 | { MCSymbolRefExpr::VK_Hexagon_IE_GOT, fixup_Hexagon_IE_GOT_32_6_X }, |
492 | { MCSymbolRefExpr::VK_PCREL, fixup_Hexagon_B32_PCREL_X }, |
493 | { MCSymbolRefExpr::VK_Hexagon_GD_PLT, fixup_Hexagon_GD_PLT_B32_PCREL_X }, |
494 | { MCSymbolRefExpr::VK_Hexagon_LD_PLT, fixup_Hexagon_LD_PLT_B32_PCREL_X }, |
495 | }; |
496 | |
497 | auto F = Relocs.find(x: VarKind); |
498 | if (F != Relocs.end()) |
499 | return Hexagon::Fixups(F->second); |
500 | raise_relocation_error(Width: 0, Kind: VarKind); |
501 | } |
502 | |
503 | if (MCID.isBranch()) |
504 | return fixup_Hexagon_B13_PCREL; |
505 | |
506 | static const std::map<unsigned,unsigned> RelocsLo = { |
507 | { MCSymbolRefExpr::VK_GOT, fixup_Hexagon_GOT_LO16 }, |
508 | { MCSymbolRefExpr::VK_GOTREL, fixup_Hexagon_GOTREL_LO16 }, |
509 | { MCSymbolRefExpr::VK_Hexagon_GD_GOT, fixup_Hexagon_GD_GOT_LO16 }, |
510 | { MCSymbolRefExpr::VK_Hexagon_LD_GOT, fixup_Hexagon_LD_GOT_LO16 }, |
511 | { MCSymbolRefExpr::VK_Hexagon_IE, fixup_Hexagon_IE_LO16 }, |
512 | { MCSymbolRefExpr::VK_Hexagon_IE_GOT, fixup_Hexagon_IE_GOT_LO16 }, |
513 | { MCSymbolRefExpr::VK_TPREL, fixup_Hexagon_TPREL_LO16 }, |
514 | { MCSymbolRefExpr::VK_DTPREL, fixup_Hexagon_DTPREL_LO16 }, |
515 | { MCSymbolRefExpr::VK_None, fixup_Hexagon_LO16 }, |
516 | }; |
517 | |
518 | static const std::map<unsigned,unsigned> RelocsHi = { |
519 | { MCSymbolRefExpr::VK_GOT, fixup_Hexagon_GOT_HI16 }, |
520 | { MCSymbolRefExpr::VK_GOTREL, fixup_Hexagon_GOTREL_HI16 }, |
521 | { MCSymbolRefExpr::VK_Hexagon_GD_GOT, fixup_Hexagon_GD_GOT_HI16 }, |
522 | { MCSymbolRefExpr::VK_Hexagon_LD_GOT, fixup_Hexagon_LD_GOT_HI16 }, |
523 | { MCSymbolRefExpr::VK_Hexagon_IE, fixup_Hexagon_IE_HI16 }, |
524 | { MCSymbolRefExpr::VK_Hexagon_IE_GOT, fixup_Hexagon_IE_GOT_HI16 }, |
525 | { MCSymbolRefExpr::VK_TPREL, fixup_Hexagon_TPREL_HI16 }, |
526 | { MCSymbolRefExpr::VK_DTPREL, fixup_Hexagon_DTPREL_HI16 }, |
527 | { MCSymbolRefExpr::VK_None, fixup_Hexagon_HI16 }, |
528 | }; |
529 | |
530 | switch (MCID.getOpcode()) { |
531 | case Hexagon::LO: |
532 | case Hexagon::A2_tfril: { |
533 | auto F = RelocsLo.find(x: VarKind); |
534 | if (F != RelocsLo.end()) |
535 | return Hexagon::Fixups(F->second); |
536 | break; |
537 | } |
538 | case Hexagon::HI: |
539 | case Hexagon::A2_tfrih: { |
540 | auto F = RelocsHi.find(x: VarKind); |
541 | if (F != RelocsHi.end()) |
542 | return Hexagon::Fixups(F->second); |
543 | break; |
544 | } |
545 | } |
546 | |
547 | raise_relocation_error(Width: 0, Kind: VarKind); |
548 | } |
549 | |
550 | static bool isPCRel(unsigned Kind) { |
551 | switch (Kind){ |
552 | case fixup_Hexagon_B22_PCREL: |
553 | case fixup_Hexagon_B15_PCREL: |
554 | case fixup_Hexagon_B7_PCREL: |
555 | case fixup_Hexagon_B13_PCREL: |
556 | case fixup_Hexagon_B9_PCREL: |
557 | case fixup_Hexagon_B32_PCREL_X: |
558 | case fixup_Hexagon_B22_PCREL_X: |
559 | case fixup_Hexagon_B15_PCREL_X: |
560 | case fixup_Hexagon_B13_PCREL_X: |
561 | case fixup_Hexagon_B9_PCREL_X: |
562 | case fixup_Hexagon_B7_PCREL_X: |
563 | case fixup_Hexagon_32_PCREL: |
564 | case fixup_Hexagon_PLT_B22_PCREL: |
565 | case fixup_Hexagon_GD_PLT_B22_PCREL: |
566 | case fixup_Hexagon_LD_PLT_B22_PCREL: |
567 | case fixup_Hexagon_GD_PLT_B22_PCREL_X: |
568 | case fixup_Hexagon_LD_PLT_B22_PCREL_X: |
569 | case fixup_Hexagon_6_PCREL_X: |
570 | return true; |
571 | default: |
572 | return false; |
573 | } |
574 | } |
575 | |
576 | unsigned HexagonMCCodeEmitter::getExprOpValue(const MCInst &MI, |
577 | const MCOperand &MO, const MCExpr *ME, SmallVectorImpl<MCFixup> &Fixups, |
578 | const MCSubtargetInfo &STI) const { |
579 | if (isa<HexagonMCExpr>(Val: ME)) |
580 | ME = &HexagonMCInstrInfo::getExpr(Expr: *ME); |
581 | int64_t Value; |
582 | if (ME->evaluateAsAbsolute(Res&: Value)) { |
583 | bool InstExtendable = HexagonMCInstrInfo::isExtendable(MCII, MCI: MI) || |
584 | HexagonMCInstrInfo::isExtended(MCII, MCI: 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 | bool IsSub0 = HexagonMCInstrInfo::isSubInstruction(MCI: MI) && !State.SubInst1; |
589 | if (State.Extended && InstExtendable && !IsSub0) { |
590 | unsigned OpIdx = ~0u; |
591 | for (unsigned I = 0, E = MI.getNumOperands(); I != E; ++I) { |
592 | if (&MO != &MI.getOperand(i: I)) |
593 | continue; |
594 | OpIdx = I; |
595 | break; |
596 | } |
597 | assert(OpIdx != ~0u); |
598 | if (OpIdx == HexagonMCInstrInfo::getExtendableOp(MCII, MCI: MI)) { |
599 | unsigned Shift = HexagonMCInstrInfo::getExtentAlignment(MCII, MCI: MI); |
600 | Value = (Value & 0x3f) << Shift; |
601 | } |
602 | } |
603 | return Value; |
604 | } |
605 | assert(ME->getKind() == MCExpr::SymbolRef || |
606 | ME->getKind() == MCExpr::Binary); |
607 | if (ME->getKind() == MCExpr::Binary) { |
608 | MCBinaryExpr const *Binary = cast<MCBinaryExpr>(Val: ME); |
609 | getExprOpValue(MI, MO, ME: Binary->getLHS(), Fixups, STI); |
610 | getExprOpValue(MI, MO, ME: Binary->getRHS(), Fixups, STI); |
611 | return 0; |
612 | } |
613 | |
614 | unsigned FixupKind = fixup_Invalid; |
615 | const MCSymbolRefExpr *MCSRE = static_cast<const MCSymbolRefExpr *>(ME); |
616 | const MCInstrDesc &MCID = HexagonMCInstrInfo::getDesc(MCII, MCI: MI); |
617 | unsigned FixupWidth = HexagonMCInstrInfo::getExtentBits(MCII, MCI: MI) - |
618 | HexagonMCInstrInfo::getExtentAlignment(MCII, MCI: MI); |
619 | MCSymbolRefExpr::VariantKind VarKind = MCSRE->getKind(); |
620 | unsigned Opc = MCID.getOpcode(); |
621 | unsigned IType = HexagonMCInstrInfo::getType(MCII, MCI: MI); |
622 | |
623 | LLVM_DEBUG(dbgs() << "----------------------------------------\n" |
624 | << "Opcode Name: " << HexagonMCInstrInfo::getName(MCII, MI) |
625 | << "\nOpcode: " << Opc << "\nRelocation bits: " |
626 | << FixupWidth << "\nAddend: " << State.Addend |
627 | << "\nVariant: " << unsigned(VarKind) |
628 | << "\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 | if (FixupWidth == 16 && !State.Extended) { |
634 | if (VarKind == MCSymbolRefExpr::VK_None) { |
635 | if (HexagonMCInstrInfo::s27_2_reloc(Expr: *MO.getExpr())) { |
636 | // A2_iconst. |
637 | FixupKind = Hexagon::fixup_Hexagon_27_REG; |
638 | } else { |
639 | // Look for GP-relative fixups. |
640 | unsigned Shift = HexagonMCInstrInfo::getExtentAlignment(MCII, MCI: MI); |
641 | static const Hexagon::Fixups GPRelFixups[] = { |
642 | Hexagon::fixup_Hexagon_GPREL16_0, Hexagon::fixup_Hexagon_GPREL16_1, |
643 | Hexagon::fixup_Hexagon_GPREL16_2, Hexagon::fixup_Hexagon_GPREL16_3 |
644 | }; |
645 | assert(Shift < std::size(GPRelFixups)); |
646 | auto UsesGP = [](const MCInstrDesc &D) { |
647 | return is_contained(Range: D.implicit_uses(), Element: Hexagon::GP); |
648 | }; |
649 | if (UsesGP(MCID)) |
650 | FixupKind = GPRelFixups[Shift]; |
651 | } |
652 | } else if (VarKind == MCSymbolRefExpr::VK_GOTREL) { |
653 | // Select between LO/HI. |
654 | if (Opc == Hexagon::LO) |
655 | FixupKind = Hexagon::fixup_Hexagon_GOTREL_LO16; |
656 | else if (Opc == Hexagon::HI) |
657 | FixupKind = Hexagon::fixup_Hexagon_GOTREL_HI16; |
658 | } |
659 | } else { |
660 | bool BranchOrCR = MCID.isBranch() || IType == HexagonII::TypeCR; |
661 | switch (FixupWidth) { |
662 | case 9: |
663 | if (BranchOrCR) |
664 | FixupKind = State.Extended ? Hexagon::fixup_Hexagon_B9_PCREL_X |
665 | : Hexagon::fixup_Hexagon_B9_PCREL; |
666 | break; |
667 | case 8: |
668 | case 7: |
669 | if (State.Extended && VarKind == MCSymbolRefExpr::VK_GOT) |
670 | FixupKind = HexagonMCInstrInfo::isExtentSigned(MCII, MCI: MI) |
671 | ? Hexagon::fixup_Hexagon_GOT_16_X |
672 | : Hexagon::fixup_Hexagon_GOT_11_X; |
673 | else if (FixupWidth == 7 && BranchOrCR) |
674 | FixupKind = State.Extended ? Hexagon::fixup_Hexagon_B7_PCREL_X |
675 | : Hexagon::fixup_Hexagon_B7_PCREL; |
676 | break; |
677 | case 0: |
678 | FixupKind = getFixupNoBits(MCII, MI, MO, VarKind); |
679 | break; |
680 | } |
681 | } |
682 | |
683 | if (FixupKind == fixup_Invalid) { |
684 | const auto &FixupTable = State.Extended ? ExtFixups : StdFixups; |
685 | |
686 | auto FindVK = FixupTable.find(x: VarKind); |
687 | if (FindVK != FixupTable.end()) |
688 | FixupKind = FindVK->second[FixupWidth]; |
689 | } |
690 | |
691 | if (FixupKind == fixup_Invalid) |
692 | raise_relocation_error(Width: FixupWidth, Kind: VarKind); |
693 | |
694 | const MCExpr *FixupExpr = MO.getExpr(); |
695 | if (State.Addend != 0 && isPCRel(Kind: FixupKind)) { |
696 | const MCExpr *C = MCConstantExpr::create(Value: State.Addend, Ctx&: MCT); |
697 | FixupExpr = MCBinaryExpr::createAdd(LHS: FixupExpr, RHS: C, Ctx&: MCT); |
698 | } |
699 | |
700 | MCFixup Fixup = MCFixup::create(Offset: State.Addend, Value: FixupExpr, |
701 | Kind: MCFixupKind(FixupKind), Loc: MI.getLoc()); |
702 | Fixups.push_back(Elt: Fixup); |
703 | // All of the information is in the fixup. |
704 | return 0; |
705 | } |
706 | |
707 | unsigned |
708 | HexagonMCCodeEmitter::getMachineOpValue(MCInst const &MI, MCOperand const &MO, |
709 | SmallVectorImpl<MCFixup> &Fixups, |
710 | MCSubtargetInfo const &STI) const { |
711 | size_t OperandNumber = ~0U; |
712 | for (unsigned i = 0, n = MI.getNumOperands(); i < n; ++i) |
713 | if (&MI.getOperand(i) == &MO) { |
714 | OperandNumber = i; |
715 | break; |
716 | } |
717 | assert((OperandNumber != ~0U) && "Operand not found" ); |
718 | |
719 | if (HexagonMCInstrInfo::isNewValue(MCII, MCI: MI) && |
720 | &MO == &HexagonMCInstrInfo::getNewValueOperand(MCII, MCI: MI)) { |
721 | // Calculate the new value distance to the associated producer |
722 | unsigned SOffset = 0; |
723 | unsigned VOffset = 0; |
724 | unsigned UseReg = MO.getReg(); |
725 | unsigned DefReg1 = Hexagon::NoRegister; |
726 | unsigned DefReg2 = Hexagon::NoRegister; |
727 | |
728 | auto Instrs = HexagonMCInstrInfo::bundleInstructions(MCI: *State.Bundle); |
729 | const MCOperand *I = Instrs.begin() + State.Index - 1; |
730 | |
731 | for (;; --I) { |
732 | assert(I != Instrs.begin() - 1 && "Couldn't find producer" ); |
733 | MCInst const &Inst = *I->getInst(); |
734 | if (HexagonMCInstrInfo::isImmext(MCI: Inst)) |
735 | continue; |
736 | |
737 | DefReg1 = Hexagon::NoRegister; |
738 | DefReg2 = Hexagon::NoRegister; |
739 | ++SOffset; |
740 | if (HexagonMCInstrInfo::isVector(MCII, MCI: Inst)) { |
741 | // Vector instructions don't count scalars. |
742 | ++VOffset; |
743 | } |
744 | if (HexagonMCInstrInfo::hasNewValue(MCII, MCI: Inst)) |
745 | DefReg1 = HexagonMCInstrInfo::getNewValueOperand(MCII, MCI: Inst).getReg(); |
746 | if (HexagonMCInstrInfo::hasNewValue2(MCII, MCI: Inst)) |
747 | DefReg2 = HexagonMCInstrInfo::getNewValueOperand2(MCII, MCI: Inst).getReg(); |
748 | if (!RegisterMatches(Consumer: UseReg, Producer: DefReg1, Producer2: DefReg2)) { |
749 | // This isn't the register we're looking for |
750 | continue; |
751 | } |
752 | if (!HexagonMCInstrInfo::isPredicated(MCII, MCI: Inst)) { |
753 | // Producer is unpredicated |
754 | break; |
755 | } |
756 | assert(HexagonMCInstrInfo::isPredicated(MCII, MI) && |
757 | "Unpredicated consumer depending on predicated producer" ); |
758 | if (HexagonMCInstrInfo::isPredicatedTrue(MCII, MCI: Inst) == |
759 | HexagonMCInstrInfo::isPredicatedTrue(MCII, MCI: MI)) |
760 | // Producer predicate sense matched ours. |
761 | break; |
762 | } |
763 | // Hexagon PRM 10.11 Construct Nt from distance |
764 | unsigned Offset = HexagonMCInstrInfo::isVector(MCII, MCI: MI) ? VOffset |
765 | : SOffset; |
766 | Offset <<= 1; |
767 | Offset |= HexagonMCInstrInfo::SubregisterBit(Consumer: UseReg, Producer: DefReg1, Producer2: DefReg2); |
768 | return Offset; |
769 | } |
770 | |
771 | assert(!MO.isImm()); |
772 | if (MO.isReg()) { |
773 | unsigned Reg = MO.getReg(); |
774 | switch (HexagonMCInstrInfo::getDesc(MCII, MCI: MI) |
775 | .operands()[OperandNumber] |
776 | .RegClass) { |
777 | case GeneralSubRegsRegClassID: |
778 | case GeneralDoubleLow8RegsRegClassID: |
779 | return HexagonMCInstrInfo::getDuplexRegisterNumbering(Reg); |
780 | default: |
781 | break; |
782 | } |
783 | return MCT.getRegisterInfo()->getEncodingValue(RegNo: Reg); |
784 | } |
785 | |
786 | return getExprOpValue(MI, MO, ME: MO.getExpr(), Fixups, STI); |
787 | } |
788 | |
789 | MCCodeEmitter *llvm::createHexagonMCCodeEmitter(MCInstrInfo const &MII, |
790 | MCContext &MCT) { |
791 | return new HexagonMCCodeEmitter(MII, MCT); |
792 | } |
793 | |
794 | #include "HexagonGenMCCodeEmitter.inc" |
795 | |