Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/VE/VEAsmPrinter.cpp
35294 views
1
//===-- VEAsmPrinter.cpp - VE LLVM assembly writer ------------------------===//
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 contains a printer that converts from our internal representation
10
// of machine-dependent LLVM code to GAS-format VE assembly language.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "MCTargetDesc/VEInstPrinter.h"
15
#include "MCTargetDesc/VEMCExpr.h"
16
#include "MCTargetDesc/VETargetStreamer.h"
17
#include "TargetInfo/VETargetInfo.h"
18
#include "VE.h"
19
#include "VEInstrInfo.h"
20
#include "VETargetMachine.h"
21
#include "llvm/CodeGen/AsmPrinter.h"
22
#include "llvm/CodeGen/MachineInstr.h"
23
#include "llvm/CodeGen/MachineModuleInfoImpls.h"
24
#include "llvm/CodeGen/MachineRegisterInfo.h"
25
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
26
#include "llvm/IR/Mangler.h"
27
#include "llvm/MC/MCAsmInfo.h"
28
#include "llvm/MC/MCContext.h"
29
#include "llvm/MC/MCInst.h"
30
#include "llvm/MC/MCInstBuilder.h"
31
#include "llvm/MC/MCStreamer.h"
32
#include "llvm/MC/MCSymbol.h"
33
#include "llvm/MC/TargetRegistry.h"
34
#include "llvm/Support/raw_ostream.h"
35
using namespace llvm;
36
37
#define DEBUG_TYPE "ve-asmprinter"
38
39
namespace {
40
class VEAsmPrinter : public AsmPrinter {
41
VETargetStreamer &getTargetStreamer() {
42
return static_cast<VETargetStreamer &>(*OutStreamer->getTargetStreamer());
43
}
44
45
public:
46
explicit VEAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
47
: AsmPrinter(TM, std::move(Streamer)) {}
48
49
StringRef getPassName() const override { return "VE Assembly Printer"; }
50
51
void lowerGETGOTAndEmitMCInsts(const MachineInstr *MI,
52
const MCSubtargetInfo &STI);
53
void lowerGETFunPLTAndEmitMCInsts(const MachineInstr *MI,
54
const MCSubtargetInfo &STI);
55
void lowerGETTLSAddrAndEmitMCInsts(const MachineInstr *MI,
56
const MCSubtargetInfo &STI);
57
58
void emitInstruction(const MachineInstr *MI) override;
59
60
static const char *getRegisterName(MCRegister Reg) {
61
return VEInstPrinter::getRegisterName(Reg);
62
}
63
void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &OS);
64
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
65
const char *ExtraCode, raw_ostream &O) override;
66
bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
67
const char *ExtraCode, raw_ostream &O) override;
68
};
69
} // end of anonymous namespace
70
71
static MCOperand createVEMCOperand(VEMCExpr::VariantKind Kind, MCSymbol *Sym,
72
MCContext &OutContext) {
73
const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::create(Sym, OutContext);
74
const VEMCExpr *expr = VEMCExpr::create(Kind, MCSym, OutContext);
75
return MCOperand::createExpr(expr);
76
}
77
78
static MCOperand createGOTRelExprOp(VEMCExpr::VariantKind Kind,
79
MCSymbol *GOTLabel, MCContext &OutContext) {
80
const MCSymbolRefExpr *GOT = MCSymbolRefExpr::create(GOTLabel, OutContext);
81
const VEMCExpr *expr = VEMCExpr::create(Kind, GOT, OutContext);
82
return MCOperand::createExpr(expr);
83
}
84
85
static void emitSIC(MCStreamer &OutStreamer, MCOperand &RD,
86
const MCSubtargetInfo &STI) {
87
MCInst SICInst;
88
SICInst.setOpcode(VE::SIC);
89
SICInst.addOperand(RD);
90
OutStreamer.emitInstruction(SICInst, STI);
91
}
92
93
static void emitBSIC(MCStreamer &OutStreamer, MCOperand &R1, MCOperand &R2,
94
const MCSubtargetInfo &STI) {
95
MCInst BSICInst;
96
BSICInst.setOpcode(VE::BSICrii);
97
BSICInst.addOperand(R1);
98
BSICInst.addOperand(R2);
99
MCOperand czero = MCOperand::createImm(0);
100
BSICInst.addOperand(czero);
101
BSICInst.addOperand(czero);
102
OutStreamer.emitInstruction(BSICInst, STI);
103
}
104
105
static void emitLEAzzi(MCStreamer &OutStreamer, MCOperand &Imm, MCOperand &RD,
106
const MCSubtargetInfo &STI) {
107
MCInst LEAInst;
108
LEAInst.setOpcode(VE::LEAzii);
109
LEAInst.addOperand(RD);
110
MCOperand CZero = MCOperand::createImm(0);
111
LEAInst.addOperand(CZero);
112
LEAInst.addOperand(CZero);
113
LEAInst.addOperand(Imm);
114
OutStreamer.emitInstruction(LEAInst, STI);
115
}
116
117
static void emitLEASLzzi(MCStreamer &OutStreamer, MCOperand &Imm, MCOperand &RD,
118
const MCSubtargetInfo &STI) {
119
MCInst LEASLInst;
120
LEASLInst.setOpcode(VE::LEASLzii);
121
LEASLInst.addOperand(RD);
122
MCOperand CZero = MCOperand::createImm(0);
123
LEASLInst.addOperand(CZero);
124
LEASLInst.addOperand(CZero);
125
LEASLInst.addOperand(Imm);
126
OutStreamer.emitInstruction(LEASLInst, STI);
127
}
128
129
static void emitLEAzii(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &Imm,
130
MCOperand &RD, const MCSubtargetInfo &STI) {
131
MCInst LEAInst;
132
LEAInst.setOpcode(VE::LEAzii);
133
LEAInst.addOperand(RD);
134
MCOperand CZero = MCOperand::createImm(0);
135
LEAInst.addOperand(CZero);
136
LEAInst.addOperand(RS1);
137
LEAInst.addOperand(Imm);
138
OutStreamer.emitInstruction(LEAInst, STI);
139
}
140
141
static void emitLEASLrri(MCStreamer &OutStreamer, MCOperand &RS1,
142
MCOperand &RS2, MCOperand &Imm, MCOperand &RD,
143
const MCSubtargetInfo &STI) {
144
MCInst LEASLInst;
145
LEASLInst.setOpcode(VE::LEASLrri);
146
LEASLInst.addOperand(RD);
147
LEASLInst.addOperand(RS1);
148
LEASLInst.addOperand(RS2);
149
LEASLInst.addOperand(Imm);
150
OutStreamer.emitInstruction(LEASLInst, STI);
151
}
152
153
static void emitBinary(MCStreamer &OutStreamer, unsigned Opcode, MCOperand &RS1,
154
MCOperand &Src2, MCOperand &RD,
155
const MCSubtargetInfo &STI) {
156
MCInst Inst;
157
Inst.setOpcode(Opcode);
158
Inst.addOperand(RD);
159
Inst.addOperand(RS1);
160
Inst.addOperand(Src2);
161
OutStreamer.emitInstruction(Inst, STI);
162
}
163
164
static void emitANDrm(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &Imm,
165
MCOperand &RD, const MCSubtargetInfo &STI) {
166
emitBinary(OutStreamer, VE::ANDrm, RS1, Imm, RD, STI);
167
}
168
169
static void emitHiLo(MCStreamer &OutStreamer, MCSymbol *GOTSym,
170
VEMCExpr::VariantKind HiKind, VEMCExpr::VariantKind LoKind,
171
MCOperand &RD, MCContext &OutContext,
172
const MCSubtargetInfo &STI) {
173
174
MCOperand hi = createVEMCOperand(HiKind, GOTSym, OutContext);
175
MCOperand lo = createVEMCOperand(LoKind, GOTSym, OutContext);
176
emitLEAzzi(OutStreamer, lo, RD, STI);
177
MCOperand M032 = MCOperand::createImm(M0(32));
178
emitANDrm(OutStreamer, RD, M032, RD, STI);
179
emitLEASLzzi(OutStreamer, hi, RD, STI);
180
}
181
182
void VEAsmPrinter::lowerGETGOTAndEmitMCInsts(const MachineInstr *MI,
183
const MCSubtargetInfo &STI) {
184
MCSymbol *GOTLabel =
185
OutContext.getOrCreateSymbol(Twine("_GLOBAL_OFFSET_TABLE_"));
186
187
const MachineOperand &MO = MI->getOperand(0);
188
MCOperand MCRegOP = MCOperand::createReg(MO.getReg());
189
190
if (!isPositionIndependent()) {
191
// Just load the address of GOT to MCRegOP.
192
switch (TM.getCodeModel()) {
193
default:
194
llvm_unreachable("Unsupported absolute code model");
195
case CodeModel::Small:
196
case CodeModel::Medium:
197
case CodeModel::Large:
198
emitHiLo(*OutStreamer, GOTLabel, VEMCExpr::VK_VE_HI32,
199
VEMCExpr::VK_VE_LO32, MCRegOP, OutContext, STI);
200
break;
201
}
202
return;
203
}
204
205
MCOperand RegGOT = MCOperand::createReg(VE::SX15); // GOT
206
MCOperand RegPLT = MCOperand::createReg(VE::SX16); // PLT
207
208
// lea %got, _GLOBAL_OFFSET_TABLE_@PC_LO(-24)
209
// and %got, %got, (32)0
210
// sic %plt
211
// lea.sl %got, _GLOBAL_OFFSET_TABLE_@PC_HI(%plt, %got)
212
MCOperand cim24 = MCOperand::createImm(-24);
213
MCOperand loImm =
214
createGOTRelExprOp(VEMCExpr::VK_VE_PC_LO32, GOTLabel, OutContext);
215
emitLEAzii(*OutStreamer, cim24, loImm, MCRegOP, STI);
216
MCOperand M032 = MCOperand::createImm(M0(32));
217
emitANDrm(*OutStreamer, MCRegOP, M032, MCRegOP, STI);
218
emitSIC(*OutStreamer, RegPLT, STI);
219
MCOperand hiImm =
220
createGOTRelExprOp(VEMCExpr::VK_VE_PC_HI32, GOTLabel, OutContext);
221
emitLEASLrri(*OutStreamer, RegGOT, RegPLT, hiImm, MCRegOP, STI);
222
}
223
224
void VEAsmPrinter::lowerGETFunPLTAndEmitMCInsts(const MachineInstr *MI,
225
const MCSubtargetInfo &STI) {
226
const MachineOperand &MO = MI->getOperand(0);
227
MCOperand MCRegOP = MCOperand::createReg(MO.getReg());
228
const MachineOperand &Addr = MI->getOperand(1);
229
MCSymbol *AddrSym = nullptr;
230
231
switch (Addr.getType()) {
232
default:
233
llvm_unreachable("<unknown operand type>");
234
return;
235
case MachineOperand::MO_MachineBasicBlock:
236
report_fatal_error("MBB is not supported yet");
237
return;
238
case MachineOperand::MO_ConstantPoolIndex:
239
report_fatal_error("ConstantPool is not supported yet");
240
return;
241
case MachineOperand::MO_ExternalSymbol:
242
AddrSym = GetExternalSymbolSymbol(Addr.getSymbolName());
243
break;
244
case MachineOperand::MO_GlobalAddress:
245
AddrSym = getSymbol(Addr.getGlobal());
246
break;
247
}
248
249
if (!isPositionIndependent()) {
250
llvm_unreachable("Unsupported uses of %plt in not PIC code");
251
return;
252
}
253
254
MCOperand RegPLT = MCOperand::createReg(VE::SX16); // PLT
255
256
// lea %dst, func@plt_lo(-24)
257
// and %dst, %dst, (32)0
258
// sic %plt ; FIXME: is it safe to use %plt here?
259
// lea.sl %dst, func@plt_hi(%plt, %dst)
260
MCOperand cim24 = MCOperand::createImm(-24);
261
MCOperand loImm =
262
createGOTRelExprOp(VEMCExpr::VK_VE_PLT_LO32, AddrSym, OutContext);
263
emitLEAzii(*OutStreamer, cim24, loImm, MCRegOP, STI);
264
MCOperand M032 = MCOperand::createImm(M0(32));
265
emitANDrm(*OutStreamer, MCRegOP, M032, MCRegOP, STI);
266
emitSIC(*OutStreamer, RegPLT, STI);
267
MCOperand hiImm =
268
createGOTRelExprOp(VEMCExpr::VK_VE_PLT_HI32, AddrSym, OutContext);
269
emitLEASLrri(*OutStreamer, MCRegOP, RegPLT, hiImm, MCRegOP, STI);
270
}
271
272
void VEAsmPrinter::lowerGETTLSAddrAndEmitMCInsts(const MachineInstr *MI,
273
const MCSubtargetInfo &STI) {
274
const MachineOperand &Addr = MI->getOperand(0);
275
MCSymbol *AddrSym = nullptr;
276
277
switch (Addr.getType()) {
278
default:
279
llvm_unreachable("<unknown operand type>");
280
return;
281
case MachineOperand::MO_MachineBasicBlock:
282
report_fatal_error("MBB is not supported yet");
283
return;
284
case MachineOperand::MO_ConstantPoolIndex:
285
report_fatal_error("ConstantPool is not supported yet");
286
return;
287
case MachineOperand::MO_ExternalSymbol:
288
AddrSym = GetExternalSymbolSymbol(Addr.getSymbolName());
289
break;
290
case MachineOperand::MO_GlobalAddress:
291
AddrSym = getSymbol(Addr.getGlobal());
292
break;
293
}
294
295
MCOperand RegLR = MCOperand::createReg(VE::SX10); // LR
296
MCOperand RegS0 = MCOperand::createReg(VE::SX0); // S0
297
MCOperand RegS12 = MCOperand::createReg(VE::SX12); // S12
298
MCSymbol *GetTLSLabel = OutContext.getOrCreateSymbol(Twine("__tls_get_addr"));
299
300
// lea %s0, sym@tls_gd_lo(-24)
301
// and %s0, %s0, (32)0
302
// sic %lr
303
// lea.sl %s0, sym@tls_gd_hi(%lr, %s0)
304
// lea %s12, __tls_get_addr@plt_lo(8)
305
// and %s12, %s12, (32)0
306
// lea.sl %s12, __tls_get_addr@plt_hi(%s12, %lr)
307
// bsic %lr, (, %s12)
308
MCOperand cim24 = MCOperand::createImm(-24);
309
MCOperand loImm =
310
createGOTRelExprOp(VEMCExpr::VK_VE_TLS_GD_LO32, AddrSym, OutContext);
311
emitLEAzii(*OutStreamer, cim24, loImm, RegS0, STI);
312
MCOperand M032 = MCOperand::createImm(M0(32));
313
emitANDrm(*OutStreamer, RegS0, M032, RegS0, STI);
314
emitSIC(*OutStreamer, RegLR, STI);
315
MCOperand hiImm =
316
createGOTRelExprOp(VEMCExpr::VK_VE_TLS_GD_HI32, AddrSym, OutContext);
317
emitLEASLrri(*OutStreamer, RegS0, RegLR, hiImm, RegS0, STI);
318
MCOperand ci8 = MCOperand::createImm(8);
319
MCOperand loImm2 =
320
createGOTRelExprOp(VEMCExpr::VK_VE_PLT_LO32, GetTLSLabel, OutContext);
321
emitLEAzii(*OutStreamer, ci8, loImm2, RegS12, STI);
322
emitANDrm(*OutStreamer, RegS12, M032, RegS12, STI);
323
MCOperand hiImm2 =
324
createGOTRelExprOp(VEMCExpr::VK_VE_PLT_HI32, GetTLSLabel, OutContext);
325
emitLEASLrri(*OutStreamer, RegS12, RegLR, hiImm2, RegS12, STI);
326
emitBSIC(*OutStreamer, RegLR, RegS12, STI);
327
}
328
329
void VEAsmPrinter::emitInstruction(const MachineInstr *MI) {
330
VE_MC::verifyInstructionPredicates(MI->getOpcode(),
331
getSubtargetInfo().getFeatureBits());
332
333
switch (MI->getOpcode()) {
334
default:
335
break;
336
case TargetOpcode::DBG_VALUE:
337
// FIXME: Debug Value.
338
return;
339
case VE::GETGOT:
340
lowerGETGOTAndEmitMCInsts(MI, getSubtargetInfo());
341
return;
342
case VE::GETFUNPLT:
343
lowerGETFunPLTAndEmitMCInsts(MI, getSubtargetInfo());
344
return;
345
case VE::GETTLSADDR:
346
lowerGETTLSAddrAndEmitMCInsts(MI, getSubtargetInfo());
347
return;
348
}
349
350
MachineBasicBlock::const_instr_iterator I = MI->getIterator();
351
MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end();
352
do {
353
MCInst TmpInst;
354
LowerVEMachineInstrToMCInst(&*I, TmpInst, *this);
355
EmitToStreamer(*OutStreamer, TmpInst);
356
} while ((++I != E) && I->isInsideBundle()); // Delay slot check.
357
}
358
359
void VEAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
360
raw_ostream &O) {
361
const MachineOperand &MO = MI->getOperand(OpNum);
362
363
switch (MO.getType()) {
364
case MachineOperand::MO_Register:
365
O << "%" << StringRef(getRegisterName(MO.getReg())).lower();
366
break;
367
case MachineOperand::MO_Immediate:
368
O << (int)MO.getImm();
369
break;
370
default:
371
llvm_unreachable("<unknown operand type>");
372
}
373
}
374
375
// PrintAsmOperand - Print out an operand for an inline asm expression.
376
bool VEAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
377
const char *ExtraCode, raw_ostream &O) {
378
if (ExtraCode && ExtraCode[0]) {
379
if (ExtraCode[1] != 0)
380
return true; // Unknown modifier.
381
382
switch (ExtraCode[0]) {
383
default:
384
// See if this is a generic print operand
385
return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);
386
case 'r':
387
case 'v':
388
break;
389
}
390
}
391
392
printOperand(MI, OpNo, O);
393
394
return false;
395
}
396
397
bool VEAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
398
const char *ExtraCode,
399
raw_ostream &O) {
400
if (ExtraCode && ExtraCode[0])
401
return true; // Unknown modifier
402
403
if (MI->getOperand(OpNo+1).isImm() &&
404
MI->getOperand(OpNo+1).getImm() == 0) {
405
// don't print "+0"
406
} else {
407
printOperand(MI, OpNo+1, O);
408
}
409
if (MI->getOperand(OpNo).isImm() &&
410
MI->getOperand(OpNo).getImm() == 0) {
411
if (MI->getOperand(OpNo+1).isImm() &&
412
MI->getOperand(OpNo+1).getImm() == 0) {
413
O << "0";
414
} else {
415
// don't print "(0)"
416
}
417
} else {
418
O << "(";
419
printOperand(MI, OpNo, O);
420
O << ")";
421
}
422
return false;
423
}
424
425
// Force static initialization.
426
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeVEAsmPrinter() {
427
RegisterAsmPrinter<VEAsmPrinter> X(getTheVETarget());
428
}
429
430