xref: /llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp (revision 0288d065eecb1208971dc4cdcc71731e34c6fca0)
1 //=- LoongArchMCCodeEmitter.cpp - Convert LoongArch code to machine code --===//
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 implements the LoongArchMCCodeEmitter class.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "LoongArchFixupKinds.h"
14 #include "MCTargetDesc/LoongArchMCExpr.h"
15 #include "MCTargetDesc/LoongArchMCTargetDesc.h"
16 #include "llvm/MC/MCCodeEmitter.h"
17 #include "llvm/MC/MCContext.h"
18 #include "llvm/MC/MCInstBuilder.h"
19 #include "llvm/MC/MCInstrInfo.h"
20 #include "llvm/MC/MCRegisterInfo.h"
21 #include "llvm/MC/MCSubtargetInfo.h"
22 #include "llvm/Support/Casting.h"
23 #include "llvm/Support/EndianStream.h"
24 
25 using namespace llvm;
26 
27 #define DEBUG_TYPE "mccodeemitter"
28 
29 namespace {
30 class LoongArchMCCodeEmitter : public MCCodeEmitter {
31   LoongArchMCCodeEmitter(const LoongArchMCCodeEmitter &) = delete;
32   void operator=(const LoongArchMCCodeEmitter &) = delete;
33   MCContext &Ctx;
34   MCInstrInfo const &MCII;
35 
36 public:
37   LoongArchMCCodeEmitter(MCContext &ctx, MCInstrInfo const &MCII)
38       : Ctx(ctx), MCII(MCII) {}
39 
40   ~LoongArchMCCodeEmitter() override {}
41 
42   void encodeInstruction(const MCInst &MI, SmallVectorImpl<char> &CB,
43                          SmallVectorImpl<MCFixup> &Fixups,
44                          const MCSubtargetInfo &STI) const override;
45 
46   template <unsigned Opc>
47   void expandToVectorLDI(const MCInst &MI, SmallVectorImpl<char> &CB,
48                          SmallVectorImpl<MCFixup> &Fixups,
49                          const MCSubtargetInfo &STI) const;
50 
51   void expandAddTPRel(const MCInst &MI, SmallVectorImpl<char> &CB,
52                       SmallVectorImpl<MCFixup> &Fixups,
53                       const MCSubtargetInfo &STI) const;
54 
55   /// TableGen'erated function for getting the binary encoding for an
56   /// instruction.
57   uint64_t getBinaryCodeForInstr(const MCInst &MI,
58                                  SmallVectorImpl<MCFixup> &Fixups,
59                                  const MCSubtargetInfo &STI) const;
60 
61   /// Return binary encoding of operand. If the machine operand requires
62   /// relocation, record the relocation and return zero.
63   unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
64                              SmallVectorImpl<MCFixup> &Fixups,
65                              const MCSubtargetInfo &STI) const;
66 
67   /// Return binary encoding of an immediate operand specified by OpNo.
68   /// The value returned is the value of the immediate minus 1.
69   /// Note that this function is dedicated to specific immediate types,
70   /// e.g. uimm2_plus1.
71   unsigned getImmOpValueSub1(const MCInst &MI, unsigned OpNo,
72                              SmallVectorImpl<MCFixup> &Fixups,
73                              const MCSubtargetInfo &STI) const;
74 
75   /// Return binary encoding of an immediate operand specified by OpNo.
76   /// The value returned is the value of the immediate shifted right
77   //  arithmetically by N.
78   /// Note that this function is dedicated to specific immediate types,
79   /// e.g. simm14_lsl2, simm16_lsl2, simm21_lsl2 and simm26_lsl2.
80   template <unsigned N>
81   unsigned getImmOpValueAsr(const MCInst &MI, unsigned OpNo,
82                             SmallVectorImpl<MCFixup> &Fixups,
83                             const MCSubtargetInfo &STI) const {
84     const MCOperand &MO = MI.getOperand(OpNo);
85     if (MO.isImm()) {
86       unsigned Res = MI.getOperand(OpNo).getImm();
87       assert((Res & ((1U << N) - 1U)) == 0 && "lowest N bits are non-zero");
88       return Res >> N;
89     }
90     return getExprOpValue(MI, MO, Fixups, STI);
91   }
92 
93   unsigned getExprOpValue(const MCInst &MI, const MCOperand &MO,
94                           SmallVectorImpl<MCFixup> &Fixups,
95                           const MCSubtargetInfo &STI) const;
96 };
97 } // end namespace
98 
99 unsigned
100 LoongArchMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
101                                           SmallVectorImpl<MCFixup> &Fixups,
102                                           const MCSubtargetInfo &STI) const {
103 
104   if (MO.isReg())
105     return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
106 
107   if (MO.isImm())
108     return static_cast<unsigned>(MO.getImm());
109 
110   // MO must be an Expr.
111   assert(MO.isExpr());
112   return getExprOpValue(MI, MO, Fixups, STI);
113 }
114 
115 unsigned
116 LoongArchMCCodeEmitter::getImmOpValueSub1(const MCInst &MI, unsigned OpNo,
117                                           SmallVectorImpl<MCFixup> &Fixups,
118                                           const MCSubtargetInfo &STI) const {
119   return MI.getOperand(OpNo).getImm() - 1;
120 }
121 
122 unsigned
123 LoongArchMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCOperand &MO,
124                                        SmallVectorImpl<MCFixup> &Fixups,
125                                        const MCSubtargetInfo &STI) const {
126   assert(MO.isExpr() && "getExprOpValue expects only expressions");
127   bool RelaxCandidate = false;
128   bool EnableRelax = STI.hasFeature(LoongArch::FeatureRelax);
129   const MCExpr *Expr = MO.getExpr();
130   MCExpr::ExprKind Kind = Expr->getKind();
131   LoongArch::Fixups FixupKind = LoongArch::fixup_loongarch_invalid;
132   if (Kind == MCExpr::Target) {
133     const LoongArchMCExpr *LAExpr = cast<LoongArchMCExpr>(Expr);
134 
135     RelaxCandidate = LAExpr->getRelaxHint();
136     switch (LAExpr->getKind()) {
137     case LoongArchMCExpr::VK_LoongArch_None:
138     case LoongArchMCExpr::VK_LoongArch_Invalid:
139       llvm_unreachable("Unhandled fixup kind!");
140     case LoongArchMCExpr::VK_LoongArch_TLS_LE_ADD_R:
141       llvm_unreachable("VK_LoongArch_TLS_LE_ADD_R should not represent an "
142                        "instruction operand");
143     case LoongArchMCExpr::VK_LoongArch_B16:
144       FixupKind = LoongArch::fixup_loongarch_b16;
145       break;
146     case LoongArchMCExpr::VK_LoongArch_B21:
147       FixupKind = LoongArch::fixup_loongarch_b21;
148       break;
149     case LoongArchMCExpr::VK_LoongArch_B26:
150     case LoongArchMCExpr::VK_LoongArch_CALL:
151     case LoongArchMCExpr::VK_LoongArch_CALL_PLT:
152       FixupKind = LoongArch::fixup_loongarch_b26;
153       break;
154     case LoongArchMCExpr::VK_LoongArch_ABS_HI20:
155       FixupKind = LoongArch::fixup_loongarch_abs_hi20;
156       break;
157     case LoongArchMCExpr::VK_LoongArch_ABS_LO12:
158       FixupKind = LoongArch::fixup_loongarch_abs_lo12;
159       break;
160     case LoongArchMCExpr::VK_LoongArch_ABS64_LO20:
161       FixupKind = LoongArch::fixup_loongarch_abs64_lo20;
162       break;
163     case LoongArchMCExpr::VK_LoongArch_ABS64_HI12:
164       FixupKind = LoongArch::fixup_loongarch_abs64_hi12;
165       break;
166     case LoongArchMCExpr::VK_LoongArch_PCALA_HI20:
167       FixupKind = LoongArch::fixup_loongarch_pcala_hi20;
168       break;
169     case LoongArchMCExpr::VK_LoongArch_PCALA_LO12:
170       FixupKind = LoongArch::fixup_loongarch_pcala_lo12;
171       break;
172     case LoongArchMCExpr::VK_LoongArch_PCALA64_LO20:
173       FixupKind = LoongArch::fixup_loongarch_pcala64_lo20;
174       break;
175     case LoongArchMCExpr::VK_LoongArch_PCALA64_HI12:
176       FixupKind = LoongArch::fixup_loongarch_pcala64_hi12;
177       break;
178     case LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20:
179       FixupKind = LoongArch::fixup_loongarch_got_pc_hi20;
180       break;
181     case LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12:
182       FixupKind = LoongArch::fixup_loongarch_got_pc_lo12;
183       break;
184     case LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20:
185       FixupKind = LoongArch::fixup_loongarch_got64_pc_lo20;
186       break;
187     case LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12:
188       FixupKind = LoongArch::fixup_loongarch_got64_pc_hi12;
189       break;
190     case LoongArchMCExpr::VK_LoongArch_GOT_HI20:
191       FixupKind = LoongArch::fixup_loongarch_got_hi20;
192       break;
193     case LoongArchMCExpr::VK_LoongArch_GOT_LO12:
194       FixupKind = LoongArch::fixup_loongarch_got_lo12;
195       break;
196     case LoongArchMCExpr::VK_LoongArch_GOT64_LO20:
197       FixupKind = LoongArch::fixup_loongarch_got64_lo20;
198       break;
199     case LoongArchMCExpr::VK_LoongArch_GOT64_HI12:
200       FixupKind = LoongArch::fixup_loongarch_got64_hi12;
201       break;
202     case LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20:
203       FixupKind = LoongArch::fixup_loongarch_tls_le_hi20;
204       break;
205     case LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12:
206       FixupKind = LoongArch::fixup_loongarch_tls_le_lo12;
207       break;
208     case LoongArchMCExpr::VK_LoongArch_TLS_LE64_LO20:
209       FixupKind = LoongArch::fixup_loongarch_tls_le64_lo20;
210       break;
211     case LoongArchMCExpr::VK_LoongArch_TLS_LE64_HI12:
212       FixupKind = LoongArch::fixup_loongarch_tls_le64_hi12;
213       break;
214     case LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20:
215       FixupKind = LoongArch::fixup_loongarch_tls_ie_pc_hi20;
216       break;
217     case LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12:
218       FixupKind = LoongArch::fixup_loongarch_tls_ie_pc_lo12;
219       break;
220     case LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_LO20:
221       FixupKind = LoongArch::fixup_loongarch_tls_ie64_pc_lo20;
222       break;
223     case LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_HI12:
224       FixupKind = LoongArch::fixup_loongarch_tls_ie64_pc_hi12;
225       break;
226     case LoongArchMCExpr::VK_LoongArch_TLS_IE_HI20:
227       FixupKind = LoongArch::fixup_loongarch_tls_ie_hi20;
228       break;
229     case LoongArchMCExpr::VK_LoongArch_TLS_IE_LO12:
230       FixupKind = LoongArch::fixup_loongarch_tls_ie_lo12;
231       break;
232     case LoongArchMCExpr::VK_LoongArch_TLS_IE64_LO20:
233       FixupKind = LoongArch::fixup_loongarch_tls_ie64_lo20;
234       break;
235     case LoongArchMCExpr::VK_LoongArch_TLS_IE64_HI12:
236       FixupKind = LoongArch::fixup_loongarch_tls_ie64_hi12;
237       break;
238     case LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20:
239       FixupKind = LoongArch::fixup_loongarch_tls_ld_pc_hi20;
240       break;
241     case LoongArchMCExpr::VK_LoongArch_TLS_LD_HI20:
242       FixupKind = LoongArch::fixup_loongarch_tls_ld_hi20;
243       break;
244     case LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20:
245       FixupKind = LoongArch::fixup_loongarch_tls_gd_pc_hi20;
246       break;
247     case LoongArchMCExpr::VK_LoongArch_TLS_GD_HI20:
248       FixupKind = LoongArch::fixup_loongarch_tls_gd_hi20;
249       break;
250     case LoongArchMCExpr::VK_LoongArch_CALL36:
251       FixupKind = LoongArch::fixup_loongarch_call36;
252       RelaxCandidate = true;
253       break;
254     case LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_HI20:
255       FixupKind = LoongArch::fixup_loongarch_tls_desc_pc_hi20;
256       break;
257     case LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_LO12:
258       FixupKind = LoongArch::fixup_loongarch_tls_desc_pc_lo12;
259       break;
260     case LoongArchMCExpr::VK_LoongArch_TLS_DESC64_PC_LO20:
261       FixupKind = LoongArch::fixup_loongarch_tls_desc64_pc_lo20;
262       break;
263     case LoongArchMCExpr::VK_LoongArch_TLS_DESC64_PC_HI12:
264       FixupKind = LoongArch::fixup_loongarch_tls_desc64_pc_hi12;
265       break;
266     case LoongArchMCExpr::VK_LoongArch_TLS_DESC_HI20:
267       FixupKind = LoongArch::fixup_loongarch_tls_desc_hi20;
268       break;
269     case LoongArchMCExpr::VK_LoongArch_TLS_DESC_LO12:
270       FixupKind = LoongArch::fixup_loongarch_tls_desc_lo12;
271       break;
272     case LoongArchMCExpr::VK_LoongArch_TLS_DESC64_LO20:
273       FixupKind = LoongArch::fixup_loongarch_tls_desc64_lo20;
274       break;
275     case LoongArchMCExpr::VK_LoongArch_TLS_DESC64_HI12:
276       FixupKind = LoongArch::fixup_loongarch_tls_desc64_hi12;
277       break;
278     case LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD:
279       FixupKind = LoongArch::fixup_loongarch_tls_desc_ld;
280       break;
281     case LoongArchMCExpr::VK_LoongArch_TLS_DESC_CALL:
282       FixupKind = LoongArch::fixup_loongarch_tls_desc_call;
283       break;
284     case LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20_R:
285       FixupKind = LoongArch::fixup_loongarch_tls_le_hi20_r;
286       RelaxCandidate = true;
287       break;
288     case LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12_R:
289       FixupKind = LoongArch::fixup_loongarch_tls_le_lo12_r;
290       RelaxCandidate = true;
291       break;
292     case LoongArchMCExpr::VK_LoongArch_PCREL20_S2:
293       FixupKind = LoongArch::fixup_loongarch_pcrel20_s2;
294       break;
295     case LoongArchMCExpr::VK_LoongArch_TLS_LD_PCREL20_S2:
296       FixupKind = LoongArch::fixup_loongarch_tls_ld_pcrel20_s2;
297       break;
298     case LoongArchMCExpr::VK_LoongArch_TLS_GD_PCREL20_S2:
299       FixupKind = LoongArch::fixup_loongarch_tls_gd_pcrel20_s2;
300       break;
301     case LoongArchMCExpr::VK_LoongArch_TLS_DESC_PCREL20_S2:
302       FixupKind = LoongArch::fixup_loongarch_tls_desc_pcrel20_s2;
303       break;
304     }
305   } else if (Kind == MCExpr::SymbolRef &&
306              cast<MCSymbolRefExpr>(Expr)->getKind() ==
307                  MCSymbolRefExpr::VK_None) {
308     switch (MI.getOpcode()) {
309     default:
310       break;
311     case LoongArch::BEQ:
312     case LoongArch::BNE:
313     case LoongArch::BLT:
314     case LoongArch::BGE:
315     case LoongArch::BLTU:
316     case LoongArch::BGEU:
317       FixupKind = LoongArch::fixup_loongarch_b16;
318       break;
319     case LoongArch::BEQZ:
320     case LoongArch::BNEZ:
321     case LoongArch::BCEQZ:
322     case LoongArch::BCNEZ:
323       FixupKind = LoongArch::fixup_loongarch_b21;
324       break;
325     case LoongArch::B:
326     case LoongArch::BL:
327       FixupKind = LoongArch::fixup_loongarch_b26;
328       break;
329     }
330   }
331 
332   assert(FixupKind != LoongArch::fixup_loongarch_invalid &&
333          "Unhandled expression!");
334 
335   Fixups.push_back(
336       MCFixup::create(0, Expr, MCFixupKind(FixupKind), MI.getLoc()));
337 
338   // Emit an R_LARCH_RELAX if linker relaxation is enabled and LAExpr has relax
339   // hint.
340   if (EnableRelax && RelaxCandidate) {
341     const MCConstantExpr *Dummy = MCConstantExpr::create(0, Ctx);
342     Fixups.push_back(MCFixup::create(
343         0, Dummy, MCFixupKind(LoongArch::fixup_loongarch_relax), MI.getLoc()));
344   }
345 
346   return 0;
347 }
348 
349 template <unsigned Opc>
350 void LoongArchMCCodeEmitter::expandToVectorLDI(
351     const MCInst &MI, SmallVectorImpl<char> &CB,
352     SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const {
353   int64_t Imm = MI.getOperand(1).getImm() & 0x3FF;
354   switch (MI.getOpcode()) {
355   case LoongArch::PseudoVREPLI_B:
356   case LoongArch::PseudoXVREPLI_B:
357     break;
358   case LoongArch::PseudoVREPLI_H:
359   case LoongArch::PseudoXVREPLI_H:
360     Imm |= 0x400;
361     break;
362   case LoongArch::PseudoVREPLI_W:
363   case LoongArch::PseudoXVREPLI_W:
364     Imm |= 0x800;
365     break;
366   case LoongArch::PseudoVREPLI_D:
367   case LoongArch::PseudoXVREPLI_D:
368     Imm |= 0xC00;
369     break;
370   }
371   MCInst TmpInst = MCInstBuilder(Opc).addOperand(MI.getOperand(0)).addImm(Imm);
372   uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
373   support::endian::write(CB, Binary, llvm::endianness::little);
374 }
375 
376 void LoongArchMCCodeEmitter::expandAddTPRel(const MCInst &MI,
377                                             SmallVectorImpl<char> &CB,
378                                             SmallVectorImpl<MCFixup> &Fixups,
379                                             const MCSubtargetInfo &STI) const {
380   MCOperand Rd = MI.getOperand(0);
381   MCOperand Rj = MI.getOperand(1);
382   MCOperand Rk = MI.getOperand(2);
383   MCOperand Symbol = MI.getOperand(3);
384   assert(Symbol.isExpr() &&
385          "Expected expression as third input to TP-relative add");
386 
387   const LoongArchMCExpr *Expr = dyn_cast<LoongArchMCExpr>(Symbol.getExpr());
388   assert(Expr &&
389          Expr->getKind() == LoongArchMCExpr::VK_LoongArch_TLS_LE_ADD_R &&
390          "Expected %le_add_r relocation on TP-relative symbol");
391 
392   // Emit the correct %le_add_r relocation for the symbol.
393   Fixups.push_back(MCFixup::create(
394       0, Expr, MCFixupKind(LoongArch::fixup_loongarch_tls_le_add_r),
395       MI.getLoc()));
396 
397   // Emit R_LARCH_RELAX for %le_add_r when the relax feature is enabled.
398   if (STI.hasFeature(LoongArch::FeatureRelax)) {
399     const MCConstantExpr *Dummy = MCConstantExpr::create(0, Ctx);
400     Fixups.push_back(MCFixup::create(
401         0, Dummy, MCFixupKind(LoongArch::fixup_loongarch_relax), MI.getLoc()));
402   }
403 
404   // Emit a normal ADD instruction with the given operands.
405   unsigned ADD = MI.getOpcode() == LoongArch::PseudoAddTPRel_D
406                      ? LoongArch::ADD_D
407                      : LoongArch::ADD_W;
408   MCInst TmpInst =
409       MCInstBuilder(ADD).addOperand(Rd).addOperand(Rj).addOperand(Rk);
410   uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
411   support::endian::write(CB, Binary, llvm::endianness::little);
412 }
413 
414 void LoongArchMCCodeEmitter::encodeInstruction(
415     const MCInst &MI, SmallVectorImpl<char> &CB,
416     SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const {
417   const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
418   // Get byte count of instruction.
419   unsigned Size = Desc.getSize();
420 
421   switch (MI.getOpcode()) {
422   default:
423     break;
424   case LoongArch::PseudoVREPLI_B:
425   case LoongArch::PseudoVREPLI_H:
426   case LoongArch::PseudoVREPLI_W:
427   case LoongArch::PseudoVREPLI_D:
428     return expandToVectorLDI<LoongArch::VLDI>(MI, CB, Fixups, STI);
429   case LoongArch::PseudoXVREPLI_B:
430   case LoongArch::PseudoXVREPLI_H:
431   case LoongArch::PseudoXVREPLI_W:
432   case LoongArch::PseudoXVREPLI_D:
433     return expandToVectorLDI<LoongArch::XVLDI>(MI, CB, Fixups, STI);
434   case LoongArch::PseudoAddTPRel_W:
435   case LoongArch::PseudoAddTPRel_D:
436     return expandAddTPRel(MI, CB, Fixups, STI);
437   }
438 
439   switch (Size) {
440   default:
441     llvm_unreachable("Unhandled encodeInstruction length!");
442   case 4: {
443     uint32_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
444     support::endian::write(CB, Bits, llvm::endianness::little);
445     break;
446   }
447   }
448 }
449 
450 MCCodeEmitter *llvm::createLoongArchMCCodeEmitter(const MCInstrInfo &MCII,
451                                                   MCContext &Ctx) {
452   return new LoongArchMCCodeEmitter(Ctx, MCII);
453 }
454 
455 #include "LoongArchGenMCCodeEmitter.inc"
456