LLVM 19.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"
18#include "llvm/MC/MCContext.h"
20#include "llvm/MC/MCInstrInfo.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
45 const MCSubtargetInfo &STI) const override;
46
47 template <unsigned Opc>
48 void expandToVectorLDI(const MCInst &MI, SmallVectorImpl<char> &CB,
50 const MCSubtargetInfo &STI) const;
51
52 void expandAddTPRel(const MCInst &MI, SmallVectorImpl<char> &CB,
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,
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,
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,
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,
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,
96 const MCSubtargetInfo &STI) const;
97};
98} // end namespace
99
100unsigned
101LoongArchMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
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
116unsigned
117LoongArchMCCodeEmitter::getImmOpValueSub1(const MCInst &MI, unsigned OpNo,
119 const MCSubtargetInfo &STI) const {
120 return MI.getOperand(OpNo).getImm() - 1;
121}
122
123unsigned
124LoongArchMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCOperand &MO,
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();
133 if (Kind == MCExpr::Target) {
134 const LoongArchMCExpr *LAExpr = cast<LoongArchMCExpr>(Expr);
135
136 RelaxCandidate = LAExpr->getRelaxHint();
137 switch (LAExpr->getKind()) {
140 llvm_unreachable("Unhandled fixup kind!");
142 llvm_unreachable("VK_LoongArch_TLS_LE_ADD_R should not represent an "
143 "instruction operand");
146 break;
149 break;
154 break;
157 break;
160 break;
163 break;
166 break;
169 break;
172 break;
175 break;
178 break;
181 break;
184 break;
187 break;
190 break;
193 break;
196 break;
199 break;
202 break;
205 break;
208 break;
211 break;
214 break;
217 break;
220 break;
223 break;
226 break;
229 break;
232 break;
235 break;
238 break;
241 break;
244 break;
247 break;
250 break;
253 break;
256 break;
259 break;
262 break;
265 break;
268 break;
271 break;
274 break;
277 break;
280 break;
283 break;
286 break;
289 break;
290 }
291 } else if (Kind == MCExpr::SymbolRef &&
292 cast<MCSymbolRefExpr>(Expr)->getKind() ==
294 switch (MI.getOpcode()) {
295 default:
296 break;
297 case LoongArch::BEQ:
298 case LoongArch::BNE:
299 case LoongArch::BLT:
300 case LoongArch::BGE:
301 case LoongArch::BLTU:
302 case LoongArch::BGEU:
304 break;
305 case LoongArch::BEQZ:
306 case LoongArch::BNEZ:
307 case LoongArch::BCEQZ:
308 case LoongArch::BCNEZ:
310 break;
311 case LoongArch::B:
312 case LoongArch::BL:
314 break;
315 }
316 }
317
319 "Unhandled expression!");
320
321 Fixups.push_back(
322 MCFixup::create(0, Expr, MCFixupKind(FixupKind), MI.getLoc()));
323
324 // Emit an R_LARCH_RELAX if linker relaxation is enabled and LAExpr has relax
325 // hint.
326 if (EnableRelax && RelaxCandidate) {
328 Fixups.push_back(MCFixup::create(
329 0, Dummy, MCFixupKind(LoongArch::fixup_loongarch_relax), MI.getLoc()));
330 }
331
332 return 0;
333}
334
335template <unsigned Opc>
336void LoongArchMCCodeEmitter::expandToVectorLDI(
337 const MCInst &MI, SmallVectorImpl<char> &CB,
338 SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const {
339 int64_t Imm = MI.getOperand(1).getImm() & 0x3FF;
340 switch (MI.getOpcode()) {
341 case LoongArch::PseudoVREPLI_B:
342 case LoongArch::PseudoXVREPLI_B:
343 break;
344 case LoongArch::PseudoVREPLI_H:
345 case LoongArch::PseudoXVREPLI_H:
346 Imm |= 0x400;
347 break;
348 case LoongArch::PseudoVREPLI_W:
349 case LoongArch::PseudoXVREPLI_W:
350 Imm |= 0x800;
351 break;
352 case LoongArch::PseudoVREPLI_D:
353 case LoongArch::PseudoXVREPLI_D:
354 Imm |= 0xC00;
355 break;
356 }
357 MCInst TmpInst = MCInstBuilder(Opc).addOperand(MI.getOperand(0)).addImm(Imm);
358 uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
360}
361
362void LoongArchMCCodeEmitter::expandAddTPRel(const MCInst &MI,
365 const MCSubtargetInfo &STI) const {
366 MCOperand Rd = MI.getOperand(0);
367 MCOperand Rj = MI.getOperand(1);
368 MCOperand Rk = MI.getOperand(2);
369 MCOperand Symbol = MI.getOperand(3);
370 assert(Symbol.isExpr() &&
371 "Expected expression as third input to TP-relative add");
372
373 const LoongArchMCExpr *Expr = dyn_cast<LoongArchMCExpr>(Symbol.getExpr());
374 assert(Expr &&
376 "Expected %le_add_r relocation on TP-relative symbol");
377
378 // Emit the correct %le_add_r relocation for the symbol.
379 // TODO: Emit R_LARCH_RELAX for %le_add_r where the relax feature is enabled.
380 Fixups.push_back(MCFixup::create(
382 MI.getLoc()));
383
384 // Emit a normal ADD instruction with the given operands.
385 unsigned ADD = MI.getOpcode() == LoongArch::PseudoAddTPRel_D
386 ? LoongArch::ADD_D
387 : LoongArch::ADD_W;
388 MCInst TmpInst =
390 uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
392}
393
394void LoongArchMCCodeEmitter::encodeInstruction(
395 const MCInst &MI, SmallVectorImpl<char> &CB,
396 SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const {
397 const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
398 // Get byte count of instruction.
399 unsigned Size = Desc.getSize();
400
401 switch (MI.getOpcode()) {
402 default:
403 break;
404 case LoongArch::PseudoVREPLI_B:
405 case LoongArch::PseudoVREPLI_H:
406 case LoongArch::PseudoVREPLI_W:
407 case LoongArch::PseudoVREPLI_D:
408 return expandToVectorLDI<LoongArch::VLDI>(MI, CB, Fixups, STI);
409 case LoongArch::PseudoXVREPLI_B:
410 case LoongArch::PseudoXVREPLI_H:
411 case LoongArch::PseudoXVREPLI_W:
412 case LoongArch::PseudoXVREPLI_D:
413 return expandToVectorLDI<LoongArch::XVLDI>(MI, CB, Fixups, STI);
414 case LoongArch::PseudoAddTPRel_W:
415 case LoongArch::PseudoAddTPRel_D:
416 return expandAddTPRel(MI, CB, Fixups, STI);
417 }
418
419 switch (Size) {
420 default:
421 llvm_unreachable("Unhandled encodeInstruction length!");
422 case 4: {
423 uint32_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
425 break;
426 }
427 }
428}
429
431 MCContext &Ctx) {
432 return new LoongArchMCCodeEmitter(Ctx, MCII);
433}
434
435#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:193
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:184
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:36
int64_t getImm() const
Definition: MCInst.h:80
bool isImm() const
Definition: MCInst.h:62
unsigned getReg() const
Returns the register number.
Definition: MCInst.h:69
bool isReg() const
Definition: MCInst.h:61
const MCExpr * getExpr() const
Definition: MCInst.h:114
bool isExpr() const
Definition: MCInst.h:65
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:586
#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.