Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp
35294 views
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:
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(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
101
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
117
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
124
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>
348
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
374
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
406
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
442
MCCodeEmitter *llvm::createLoongArchMCCodeEmitter(const MCInstrInfo &MCII,
443
MCContext &Ctx) {
444
return new LoongArchMCCodeEmitter(Ctx, MCII);
445
}
446
447
#include "LoongArchGenMCCodeEmitter.inc"
448
449