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
26using namespace llvm;
27
28#define DEBUG_TYPE "mccodeemitter"
29
30namespace {
31class LoongArchMCCodeEmitter : public MCCodeEmitter {
32 LoongArchMCCodeEmitter(const LoongArchMCCodeEmitter &) = delete;
33 void operator=(const LoongArchMCCodeEmitter &) = delete;
34 MCContext &Ctx;
35 MCInstrInfo const &MCII;
36
37public:
38 LoongArchMCCodeEmitter(MCContext &ctx, MCInstrInfo const &MCII)
39 : Ctx(ctx), MCII(MCII) {}
40
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>
82 unsigned getImmOpValueAsr(const MCInst &MI, unsigned OpNo,
83 SmallVectorImpl<MCFixup> &Fixups,
84 const MCSubtargetInfo &STI) const {
85 const MCOperand &MO = MI.getOperand(i: OpNo);
86 if (MO.isImm()) {
87 unsigned Res = MI.getOperand(i: 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
100unsigned
101LoongArchMCCodeEmitter::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(RegNo: 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
116unsigned
117LoongArchMCCodeEmitter::getImmOpValueSub1(const MCInst &MI, unsigned OpNo,
118 SmallVectorImpl<MCFixup> &Fixups,
119 const MCSubtargetInfo &STI) const {
120 return MI.getOperand(i: OpNo).getImm() - 1;
121}
122
123unsigned
124LoongArchMCCodeEmitter::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(Feature: 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>(Val: 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>(Val: 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 Elt: MCFixup::create(Offset: 0, Value: Expr, Kind: MCFixupKind(FixupKind), Loc: 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(Value: 0, Ctx);
340 Fixups.push_back(Elt: MCFixup::create(
341 Offset: 0, Value: Dummy, Kind: MCFixupKind(LoongArch::fixup_loongarch_relax), Loc: MI.getLoc()));
342 }
343
344 return 0;
345}
346
347template <unsigned Opc>
348void LoongArchMCCodeEmitter::expandToVectorLDI(
349 const MCInst &MI, SmallVectorImpl<char> &CB,
350 SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const {
351 int64_t Imm = MI.getOperand(i: 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(Op: MI.getOperand(i: 0)).addImm(Val: Imm);
370 uint32_t Binary = getBinaryCodeForInstr(MI: TmpInst, Fixups, STI);
371 support::endian::write(Out&: CB, V: Binary, E: llvm::endianness::little);
372}
373
374void LoongArchMCCodeEmitter::expandAddTPRel(const MCInst &MI,
375 SmallVectorImpl<char> &CB,
376 SmallVectorImpl<MCFixup> &Fixups,
377 const MCSubtargetInfo &STI) const {
378 MCOperand Rd = MI.getOperand(i: 0);
379 MCOperand Rj = MI.getOperand(i: 1);
380 MCOperand Rk = MI.getOperand(i: 2);
381 MCOperand Symbol = MI.getOperand(i: 3);
382 assert(Symbol.isExpr() &&
383 "Expected expression as third input to TP-relative add");
384
385 const LoongArchMCExpr *Expr = dyn_cast<LoongArchMCExpr>(Val: 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(Elt: MCFixup::create(
393 Offset: 0, Value: Expr, Kind: MCFixupKind(LoongArch::fixup_loongarch_tls_le_add_r),
394 Loc: 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(Op: Rd).addOperand(Op: Rj).addOperand(Op: Rk);
402 uint32_t Binary = getBinaryCodeForInstr(MI: TmpInst, Fixups, STI);
403 support::endian::write(Out&: CB, V: Binary, E: llvm::endianness::little);
404}
405
406void LoongArchMCCodeEmitter::encodeInstruction(
407 const MCInst &MI, SmallVectorImpl<char> &CB,
408 SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const {
409 const MCInstrDesc &Desc = MCII.get(Opcode: 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(Out&: CB, V: Bits, E: llvm::endianness::little);
437 break;
438 }
439 }
440}
441
442MCCodeEmitter *llvm::createLoongArchMCCodeEmitter(const MCInstrInfo &MCII,
443 MCContext &Ctx) {
444 return new LoongArchMCCodeEmitter(Ctx, MCII);
445}
446
447#include "LoongArchGenMCCodeEmitter.inc"
448