LLVM 23.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 = default;
42
43 void encodeInstruction(const MCInst &MI, SmallVectorImpl<char> &CB,
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
101 const MCExpr *Value, uint16_t Kind) {
102 bool PCRel = false;
103 switch (Kind) {
107 PCRel = true;
108 }
109 Fixups.push_back(MCFixup::create(Offset, Value, Kind, PCRel));
110}
111
112unsigned
113LoongArchMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
115 const MCSubtargetInfo &STI) const {
116
117 if (MO.isReg())
118 return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
119
120 if (MO.isImm())
121 return static_cast<unsigned>(MO.getImm());
122
123 // MO must be an Expr.
124 assert(MO.isExpr());
125 return getExprOpValue(MI, MO, Fixups, STI);
126}
127
128unsigned
129LoongArchMCCodeEmitter::getImmOpValueSub1(const MCInst &MI, unsigned OpNo,
130 SmallVectorImpl<MCFixup> &Fixups,
131 const MCSubtargetInfo &STI) const {
132 return MI.getOperand(OpNo).getImm() - 1;
133}
134
135unsigned
136LoongArchMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCOperand &MO,
137 SmallVectorImpl<MCFixup> &Fixups,
138 const MCSubtargetInfo &STI) const {
139 assert(MO.isExpr() && "getExprOpValue expects only expressions");
140 bool RelaxCandidate = false;
141 bool EnableRelax = STI.hasFeature(LoongArch::FeatureRelax);
142 const MCExpr *Expr = MO.getExpr();
143 MCExpr::ExprKind Kind = Expr->getKind();
145 if (Kind == MCExpr::Specifier) {
146 const LoongArchMCExpr *LAExpr = cast<LoongArchMCExpr>(Expr);
147 FixupKind = LAExpr->getSpecifier();
148 RelaxCandidate = LAExpr->getRelaxHint();
149 switch (uint16_t(LAExpr->getSpecifier())) {
151 llvm_unreachable("Unhandled fixup kind!");
152 case ELF::R_LARCH_TLS_LE_ADD_R:
153 llvm_unreachable("ELF::R_LARCH_TLS_LE_ADD_R should not represent an "
154 "instruction operand");
155 case ELF::R_LARCH_B16:
157 break;
158 case ELF::R_LARCH_B21:
160 break;
161 case ELF::R_LARCH_B26:
163 break;
164 case ELF::R_LARCH_MARK_LA:
165 // Match gas behavior: generate `R_LARCH_MARK_LA` relocation when using
166 // `la.abs`.
167 Fixups.push_back(
169 FirstLiteralRelocationKind + ELF::R_LARCH_MARK_LA));
170 [[fallthrough]];
171 case ELF::R_LARCH_ABS_HI20:
173 break;
174 case ELF::R_LARCH_ABS_LO12:
176 break;
177 case ELF::R_LARCH_ABS64_LO20:
179 break;
180 case ELF::R_LARCH_ABS64_HI12:
182 break;
183 case ELF::R_LARCH_CALL30:
184 case ELF::R_LARCH_CALL36:
185 case ELF::R_LARCH_TLS_LE_HI20_R:
186 case ELF::R_LARCH_TLS_LE_LO12_R:
187 RelaxCandidate = true;
188 break;
189 }
190 } else if (Kind == MCExpr::SymbolRef) {
191 switch (MI.getOpcode()) {
192 default:
193 break;
194 case LoongArch::BEQ:
195 case LoongArch::BNE:
196 case LoongArch::BLT:
197 case LoongArch::BGE:
198 case LoongArch::BLTU:
199 case LoongArch::BGEU:
201 break;
202 case LoongArch::BEQZ:
203 case LoongArch::BNEZ:
204 case LoongArch::BCEQZ:
205 case LoongArch::BCNEZ:
207 break;
208 case LoongArch::B:
209 case LoongArch::BL:
211 break;
212 }
213 }
214
216 "Unhandled expression!");
217
218 addFixup(Fixups, 0, Expr, FixupKind);
219 // If linker relaxation is enabled and supported by this relocation, set
220 // a bit so that if fixup is unresolved, a R_LARCH_RELAX relocation will be
221 // appended.
222 if (EnableRelax && RelaxCandidate)
223 Fixups.back().setLinkerRelaxable();
224
225 return 0;
226}
227
228template <unsigned Opc>
229void LoongArchMCCodeEmitter::expandToVectorLDI(
230 const MCInst &MI, SmallVectorImpl<char> &CB,
231 SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const {
232 int64_t Imm = MI.getOperand(1).getImm() & 0x3FF;
233 switch (MI.getOpcode()) {
234 case LoongArch::PseudoVREPLI_B:
235 case LoongArch::PseudoXVREPLI_B:
236 break;
237 case LoongArch::PseudoVREPLI_H:
238 case LoongArch::PseudoXVREPLI_H:
239 Imm |= 0x400;
240 break;
241 case LoongArch::PseudoVREPLI_W:
242 case LoongArch::PseudoXVREPLI_W:
243 Imm |= 0x800;
244 break;
245 case LoongArch::PseudoVREPLI_D:
246 case LoongArch::PseudoXVREPLI_D:
247 Imm |= 0xC00;
248 break;
249 }
250 MCInst TmpInst = MCInstBuilder(Opc).addOperand(MI.getOperand(0)).addImm(Imm);
251 uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
253}
254
255void LoongArchMCCodeEmitter::expandAddTPRel(const MCInst &MI,
256 SmallVectorImpl<char> &CB,
257 SmallVectorImpl<MCFixup> &Fixups,
258 const MCSubtargetInfo &STI) const {
259 MCOperand Rd = MI.getOperand(0);
260 MCOperand Rj = MI.getOperand(1);
261 MCOperand Rk = MI.getOperand(2);
262 MCOperand Symbol = MI.getOperand(3);
263 assert(Symbol.isExpr() &&
264 "Expected expression as third input to TP-relative add");
265
266 const LoongArchMCExpr *Expr = dyn_cast<LoongArchMCExpr>(Symbol.getExpr());
267 assert(Expr && Expr->getSpecifier() == ELF::R_LARCH_TLS_LE_ADD_R &&
268 "Expected %le_add_r relocation on TP-relative symbol");
269
270 // Emit the correct %le_add_r relocation for the symbol.
271 addFixup(Fixups, 0, Expr, ELF::R_LARCH_TLS_LE_ADD_R);
272 if (STI.hasFeature(LoongArch::FeatureRelax))
273 Fixups.back().setLinkerRelaxable();
274
275 // Emit a normal ADD instruction with the given operands.
276 unsigned ADD = MI.getOpcode() == LoongArch::PseudoAddTPRel_D
277 ? LoongArch::ADD_D
278 : LoongArch::ADD_W;
279 MCInst TmpInst =
280 MCInstBuilder(ADD).addOperand(Rd).addOperand(Rj).addOperand(Rk);
281 uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
283}
284
285void LoongArchMCCodeEmitter::encodeInstruction(
286 const MCInst &MI, SmallVectorImpl<char> &CB,
287 SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const {
288 const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
289 // Get byte count of instruction.
290 unsigned Size = Desc.getSize();
291
292 switch (MI.getOpcode()) {
293 default:
294 break;
295 case LoongArch::PseudoVREPLI_B:
296 case LoongArch::PseudoVREPLI_H:
297 case LoongArch::PseudoVREPLI_W:
298 case LoongArch::PseudoVREPLI_D:
299 return expandToVectorLDI<LoongArch::VLDI>(MI, CB, Fixups, STI);
300 case LoongArch::PseudoXVREPLI_B:
301 case LoongArch::PseudoXVREPLI_H:
302 case LoongArch::PseudoXVREPLI_W:
303 case LoongArch::PseudoXVREPLI_D:
304 return expandToVectorLDI<LoongArch::XVLDI>(MI, CB, Fixups, STI);
305 case LoongArch::PseudoAddTPRel_W:
306 case LoongArch::PseudoAddTPRel_D:
307 return expandAddTPRel(MI, CB, Fixups, STI);
308 }
309
310 switch (Size) {
311 default:
312 llvm_unreachable("Unhandled encodeInstruction length!");
313 case 4: {
314 uint32_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
316 break;
317 }
318 }
319}
320
322 MCContext &Ctx) {
323 return new LoongArchMCCodeEmitter(Ctx, MCII);
324}
325
326#include "LoongArchGenMCCodeEmitter.inc"
static void addFixup(SmallVectorImpl< MCFixup > &Fixups, uint32_t Offset, const MCExpr *Value, uint16_t Kind, bool PCRel=false)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
IRTranslator LLVM IR MI
MCCodeEmitter - Generic instruction encoding interface.
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition MCExpr.cpp:212
Context object for machine code objects.
Definition MCContext.h:83
const MCRegisterInfo * getRegisterInfo() const
Definition MCContext.h:414
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:43
@ Specifier
Expression with a relocation specifier.
Definition MCExpr.h:45
ExprKind getKind() const
Definition MCExpr.h:85
static MCFixup create(uint32_t Offset, const MCExpr *Value, MCFixupKind Kind, bool PCRel=false)
Consider bit fields if we need more flags.
Definition MCFixup.h:86
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
void addOperand(const MCOperand Op)
Definition MCInst.h:215
Interface to description of machine instruction set.
Definition MCInstrInfo.h:27
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
Definition MCInstrInfo.h:90
Instances of this class represent operands of the MCInst class.
Definition MCInst.h:40
int64_t getImm() const
Definition MCInst.h:84
bool isImm() const
Definition MCInst.h:66
bool isReg() const
Definition MCInst.h:65
MCRegister getReg() const
Returns the register number.
Definition MCInst.h:73
const MCExpr * getExpr() const
Definition MCInst.h:118
bool isExpr() const
Definition MCInst.h:69
uint16_t getEncodingValue(MCRegister Reg) const
Returns the encoding for Reg.
Spec getSpecifier() const
Definition MCExpr.h:508
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...
LLVM Value Representation.
Definition Value.h:75
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ ADD
Simple integer binary arithmetic operators.
Definition ISDOpcodes.h:264
void write(void *memory, value_type value, endianness endian)
Write a value to memory with a particular endianness.
Definition Endian.h:96
This is an optimization pass for GlobalISel generic memory operations.
Definition Types.h:26
@ Offset
Definition DWP.cpp:532
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
MCCodeEmitter * createLoongArchMCCodeEmitter(const MCInstrInfo &MCII, MCContext &Ctx)
Op::Description Desc
static Lanai::Fixups FixupKind(const MCExpr *Expr)
static void addFixup(SmallVectorImpl< MCFixup > &Fixups, uint32_t Offset, const MCExpr *Value, uint16_t Kind)
@ FirstLiteralRelocationKind
Definition MCFixup.h:29
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
#define N