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