LLVM 20.0.0git
LoongArchMCCodeEmitter.cpp
Go to the documentation of this file.
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"
17#include "llvm/MC/MCContext.h"
19#include "llvm/MC/MCInstrInfo.h"
24
25using namespace llvm;
26
27#define DEBUG_TYPE "mccodeemitter"
28
29namespace {
30class LoongArchMCCodeEmitter : public MCCodeEmitter {
31 LoongArchMCCodeEmitter(const LoongArchMCCodeEmitter &) = delete;
32 void operator=(const LoongArchMCCodeEmitter &) = delete;
33 MCContext &Ctx;
34 MCInstrInfo const &MCII;
35
36public:
37 LoongArchMCCodeEmitter(MCContext &ctx, MCInstrInfo const &MCII)
38 : Ctx(ctx), MCII(MCII) {}
39
40 ~LoongArchMCCodeEmitter() override {}
41
44 const MCSubtargetInfo &STI) const override;
45
46 template <unsigned Opc>
47 void expandToVectorLDI(const MCInst &MI, SmallVectorImpl<char> &CB,
49 const MCSubtargetInfo &STI) const;
50
51 void expandAddTPRel(const MCInst &MI, SmallVectorImpl<char> &CB,
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,
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,
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,
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,
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,
95 const MCSubtargetInfo &STI) const;
96};
97} // end namespace
98
99unsigned
100LoongArchMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
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
115unsigned
116LoongArchMCCodeEmitter::getImmOpValueSub1(const MCInst &MI, unsigned OpNo,
118 const MCSubtargetInfo &STI) const {
119 return MI.getOperand(OpNo).getImm() - 1;
120}
121
122unsigned
123LoongArchMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCOperand &MO,
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();
132 if (Kind == MCExpr::Target) {
133 const LoongArchMCExpr *LAExpr = cast<LoongArchMCExpr>(Expr);
134
135 RelaxCandidate = LAExpr->getRelaxHint();
136 switch (LAExpr->getKind()) {
139 llvm_unreachable("Unhandled fixup kind!");
141 llvm_unreachable("VK_LoongArch_TLS_LE_ADD_R should not represent an "
142 "instruction operand");
145 break;
148 break;
153 break;
156 break;
159 break;
162 break;
165 break;
168 break;
171 break;
174 break;
177 break;
180 break;
183 break;
186 break;
189 break;
192 break;
195 break;
198 break;
201 break;
204 break;
207 break;
210 break;
213 break;
216 break;
219 break;
222 break;
225 break;
228 break;
231 break;
234 break;
237 break;
240 break;
243 break;
246 break;
249 break;
252 RelaxCandidate = true;
253 break;
256 break;
259 break;
262 break;
265 break;
268 break;
271 break;
274 break;
277 break;
280 break;
283 break;
286 RelaxCandidate = true;
287 break;
290 RelaxCandidate = true;
291 break;
294 break;
297 break;
300 break;
303 break;
304 }
305 } else if (Kind == MCExpr::SymbolRef &&
306 cast<MCSymbolRefExpr>(Expr)->getKind() ==
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:
318 break;
319 case LoongArch::BEQZ:
320 case LoongArch::BNEZ:
321 case LoongArch::BCEQZ:
322 case LoongArch::BCNEZ:
324 break;
325 case LoongArch::B:
326 case LoongArch::BL:
328 break;
329 }
330 }
331
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) {
342 Fixups.push_back(MCFixup::create(
343 0, Dummy, MCFixupKind(LoongArch::fixup_loongarch_relax), MI.getLoc()));
344 }
345
346 return 0;
347}
348
349template <unsigned Opc>
350void 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);
374}
375
376void LoongArchMCCodeEmitter::expandAddTPRel(const MCInst &MI,
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 &&
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(
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)) {
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 =
410 uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
412}
413
414void 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);
445 break;
446 }
447 }
448}
449
451 MCContext &Ctx) {
452 return new LoongArchMCCodeEmitter(Ctx, MCII);
453}
454
455#include "LoongArchGenMCCodeEmitter.inc"
uint64_t Size
IRTranslator LLVM IR MI
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
VariantKind getKind() const
bool getRelaxHint() const
MCCodeEmitter - Generic instruction encoding interface.
Definition: MCCodeEmitter.h:21
virtual void encodeInstruction(const MCInst &Inst, SmallVectorImpl< char > &CB, SmallVectorImpl< MCFixup > &Fixups, const MCSubtargetInfo &STI) const =0
Encode the given Inst to bytes and append to CB.
MCCodeEmitter & operator=(const MCCodeEmitter &)=delete
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition: MCExpr.cpp:222
Context object for machine code objects.
Definition: MCContext.h:83
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:34
@ SymbolRef
References to labels and assigned expressions.
Definition: MCExpr.h:39
@ Target
Target specific expression.
Definition: MCExpr.h:41
ExprKind getKind() const
Definition: MCExpr.h:78
static MCFixup create(uint32_t Offset, const MCExpr *Value, MCFixupKind Kind, SMLoc Loc=SMLoc())
Definition: MCFixup.h:87
MCInstBuilder & addOperand(const MCOperand &Op)
Add an operand.
Definition: MCInstBuilder.h:73
MCInstBuilder & addImm(int64_t Val)
Add a new integer immediate operand.
Definition: MCInstBuilder.h:43
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:185
Describe properties that are true of each instruction in the target description file.
Definition: MCInstrDesc.h:198
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:26
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:37
int64_t getImm() const
Definition: MCInst.h:81
bool isImm() const
Definition: MCInst.h:63
bool isReg() const
Definition: MCInst.h:62
MCRegister getReg() const
Returns the register number.
Definition: MCInst.h:70
const MCExpr * getExpr() const
Definition: MCInst.h:115
bool isExpr() const
Definition: MCInst.h:66
Generic base class for all target subtargets.
bool hasFeature(unsigned Feature) const
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:573
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ ADD
Simple integer binary arithmetic operators.
Definition: ISDOpcodes.h:246
void write(void *memory, value_type value, endianness endian)
Write a value to memory with a particular endianness.
Definition: Endian.h:92
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
MCCodeEmitter * createLoongArchMCCodeEmitter(const MCInstrInfo &MCII, MCContext &Ctx)
MCFixupKind
Extensible enumeration to represent the type of a fixup.
Definition: MCFixup.h:21
#define N
Description of the encoding of one expression Op.