Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/CSKY/CSKYAsmPrinter.cpp
35266 views
1
//===-- CSKYAsmPrinter.cpp - CSKY 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 the CSKY assembly language.
11
//
12
//===----------------------------------------------------------------------===//
13
#include "CSKYAsmPrinter.h"
14
#include "CSKY.h"
15
#include "CSKYConstantPoolValue.h"
16
#include "CSKYTargetMachine.h"
17
#include "MCTargetDesc/CSKYInstPrinter.h"
18
#include "MCTargetDesc/CSKYMCExpr.h"
19
#include "MCTargetDesc/CSKYTargetStreamer.h"
20
#include "TargetInfo/CSKYTargetInfo.h"
21
#include "llvm/ADT/Statistic.h"
22
#include "llvm/CodeGen/AsmPrinter.h"
23
#include "llvm/CodeGen/MachineConstantPool.h"
24
#include "llvm/CodeGen/MachineFrameInfo.h"
25
#include "llvm/IR/DataLayout.h"
26
#include "llvm/MC/MCAsmInfo.h"
27
#include "llvm/MC/MCContext.h"
28
#include "llvm/MC/MCInstBuilder.h"
29
#include "llvm/MC/MCStreamer.h"
30
#include "llvm/MC/TargetRegistry.h"
31
32
using namespace llvm;
33
34
#define DEBUG_TYPE "csky-asm-printer"
35
36
STATISTIC(CSKYNumInstrsCompressed,
37
"Number of C-SKY Compressed instructions emitted");
38
39
CSKYAsmPrinter::CSKYAsmPrinter(llvm::TargetMachine &TM,
40
std::unique_ptr<llvm::MCStreamer> Streamer)
41
: AsmPrinter(TM, std::move(Streamer)), MCInstLowering(OutContext, *this) {}
42
43
bool CSKYAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
44
MCP = MF.getConstantPool();
45
TII = MF.getSubtarget().getInstrInfo();
46
47
// Set the current MCSubtargetInfo to a copy which has the correct
48
// feature bits for the current MachineFunction
49
MCSubtargetInfo &NewSTI =
50
OutStreamer->getContext().getSubtargetCopy(*TM.getMCSubtargetInfo());
51
NewSTI.setFeatureBits(MF.getSubtarget().getFeatureBits());
52
Subtarget = &NewSTI;
53
54
return AsmPrinter::runOnMachineFunction(MF);
55
}
56
57
#define GEN_COMPRESS_INSTR
58
#include "CSKYGenCompressInstEmitter.inc"
59
void CSKYAsmPrinter::EmitToStreamer(MCStreamer &S, const MCInst &Inst) {
60
MCInst CInst;
61
bool Res = compressInst(CInst, Inst, *Subtarget);
62
if (Res)
63
++CSKYNumInstrsCompressed;
64
AsmPrinter::EmitToStreamer(*OutStreamer, Res ? CInst : Inst);
65
}
66
67
// Simple pseudo-instructions have their lowering (with expansion to real
68
// instructions) auto-generated.
69
#include "CSKYGenMCPseudoLowering.inc"
70
71
void CSKYAsmPrinter::expandTLSLA(const MachineInstr *MI) {
72
DebugLoc DL = MI->getDebugLoc();
73
74
MCSymbol *PCLabel = OutContext.getOrCreateSymbol(
75
Twine(MAI->getPrivateGlobalPrefix()) + "PC" + Twine(getFunctionNumber()) +
76
"_" + Twine(MI->getOperand(3).getImm()));
77
78
OutStreamer->emitLabel(PCLabel);
79
80
auto Instr = BuildMI(*MF, DL, TII->get(CSKY::LRW32))
81
.add(MI->getOperand(0))
82
.add(MI->getOperand(2));
83
MCInst LRWInst;
84
MCInstLowering.Lower(Instr, LRWInst);
85
EmitToStreamer(*OutStreamer, LRWInst);
86
87
Instr = BuildMI(*MF, DL, TII->get(CSKY::GRS32))
88
.add(MI->getOperand(1))
89
.addSym(PCLabel);
90
MCInst GRSInst;
91
MCInstLowering.Lower(Instr, GRSInst);
92
EmitToStreamer(*OutStreamer, GRSInst);
93
return;
94
}
95
96
void CSKYAsmPrinter::emitCustomConstantPool(const MachineInstr *MI) {
97
98
// This instruction represents a floating constant pool in the function.
99
// The first operand is the ID# for this instruction, the second is the
100
// index into the MachineConstantPool that this is, the third is the size
101
// in bytes of this constant pool entry.
102
// The required alignment is specified on the basic block holding this MI.
103
unsigned LabelId = (unsigned)MI->getOperand(0).getImm();
104
unsigned CPIdx = (unsigned)MI->getOperand(1).getIndex();
105
106
// If this is the first entry of the pool, mark it.
107
if (!InConstantPool) {
108
OutStreamer->emitValueToAlignment(Align(4));
109
InConstantPool = true;
110
}
111
112
OutStreamer->emitLabel(GetCPISymbol(LabelId));
113
114
const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx];
115
if (MCPE.isMachineConstantPoolEntry())
116
emitMachineConstantPoolValue(MCPE.Val.MachineCPVal);
117
else
118
emitGlobalConstant(MF->getDataLayout(), MCPE.Val.ConstVal);
119
return;
120
}
121
122
void CSKYAsmPrinter::emitFunctionBodyEnd() {
123
// Make sure to terminate any constant pools that were at the end
124
// of the function.
125
if (!InConstantPool)
126
return;
127
InConstantPool = false;
128
}
129
130
void CSKYAsmPrinter::emitStartOfAsmFile(Module &M) {
131
if (TM.getTargetTriple().isOSBinFormatELF())
132
emitAttributes();
133
}
134
135
void CSKYAsmPrinter::emitEndOfAsmFile(Module &M) {
136
CSKYTargetStreamer &CTS =
137
static_cast<CSKYTargetStreamer &>(*OutStreamer->getTargetStreamer());
138
139
if (TM.getTargetTriple().isOSBinFormatELF())
140
CTS.finishAttributeSection();
141
}
142
143
void CSKYAsmPrinter::emitInstruction(const MachineInstr *MI) {
144
CSKY_MC::verifyInstructionPredicates(MI->getOpcode(),
145
getSubtargetInfo().getFeatureBits());
146
147
// Do any auto-generated pseudo lowerings.
148
if (emitPseudoExpansionLowering(*OutStreamer, MI))
149
return;
150
151
// If we just ended a constant pool, mark it as such.
152
if (InConstantPool && MI->getOpcode() != CSKY::CONSTPOOL_ENTRY) {
153
InConstantPool = false;
154
}
155
156
if (MI->getOpcode() == CSKY::PseudoTLSLA32)
157
return expandTLSLA(MI);
158
159
if (MI->getOpcode() == CSKY::CONSTPOOL_ENTRY)
160
return emitCustomConstantPool(MI);
161
162
MCInst TmpInst;
163
MCInstLowering.Lower(MI, TmpInst);
164
EmitToStreamer(*OutStreamer, TmpInst);
165
}
166
167
// Convert a CSKY-specific constant pool modifier into the associated
168
// MCSymbolRefExpr variant kind.
169
static CSKYMCExpr::VariantKind
170
getModifierVariantKind(CSKYCP::CSKYCPModifier Modifier) {
171
switch (Modifier) {
172
case CSKYCP::NO_MOD:
173
return CSKYMCExpr::VK_CSKY_None;
174
case CSKYCP::ADDR:
175
return CSKYMCExpr::VK_CSKY_ADDR;
176
case CSKYCP::GOT:
177
return CSKYMCExpr::VK_CSKY_GOT;
178
case CSKYCP::GOTOFF:
179
return CSKYMCExpr::VK_CSKY_GOTOFF;
180
case CSKYCP::PLT:
181
return CSKYMCExpr::VK_CSKY_PLT;
182
case CSKYCP::TLSGD:
183
return CSKYMCExpr::VK_CSKY_TLSGD;
184
case CSKYCP::TLSLE:
185
return CSKYMCExpr::VK_CSKY_TLSLE;
186
case CSKYCP::TLSIE:
187
return CSKYMCExpr::VK_CSKY_TLSIE;
188
}
189
llvm_unreachable("Invalid CSKYCPModifier!");
190
}
191
192
void CSKYAsmPrinter::emitMachineConstantPoolValue(
193
MachineConstantPoolValue *MCPV) {
194
int Size = getDataLayout().getTypeAllocSize(MCPV->getType());
195
CSKYConstantPoolValue *CCPV = static_cast<CSKYConstantPoolValue *>(MCPV);
196
MCSymbol *MCSym;
197
198
if (CCPV->isBlockAddress()) {
199
const BlockAddress *BA =
200
cast<CSKYConstantPoolConstant>(CCPV)->getBlockAddress();
201
MCSym = GetBlockAddressSymbol(BA);
202
} else if (CCPV->isGlobalValue()) {
203
const GlobalValue *GV = cast<CSKYConstantPoolConstant>(CCPV)->getGV();
204
MCSym = getSymbol(GV);
205
} else if (CCPV->isMachineBasicBlock()) {
206
const MachineBasicBlock *MBB = cast<CSKYConstantPoolMBB>(CCPV)->getMBB();
207
MCSym = MBB->getSymbol();
208
} else if (CCPV->isJT()) {
209
signed JTI = cast<CSKYConstantPoolJT>(CCPV)->getJTI();
210
MCSym = GetJTISymbol(JTI);
211
} else if (CCPV->isConstPool()) {
212
const Constant *C = cast<CSKYConstantPoolConstant>(CCPV)->getConstantPool();
213
MCSym = GetCPISymbol(MCP->getConstantPoolIndex(C, Align(4)));
214
} else {
215
assert(CCPV->isExtSymbol() && "unrecognized constant pool value");
216
StringRef Sym = cast<CSKYConstantPoolSymbol>(CCPV)->getSymbol();
217
MCSym = GetExternalSymbolSymbol(Sym);
218
}
219
// Create an MCSymbol for the reference.
220
const MCExpr *Expr =
221
MCSymbolRefExpr::create(MCSym, MCSymbolRefExpr::VK_None, OutContext);
222
223
if (CCPV->getPCAdjustment()) {
224
225
MCSymbol *PCLabel = OutContext.getOrCreateSymbol(
226
Twine(MAI->getPrivateGlobalPrefix()) + "PC" +
227
Twine(getFunctionNumber()) + "_" + Twine(CCPV->getLabelID()));
228
229
const MCExpr *PCRelExpr = MCSymbolRefExpr::create(PCLabel, OutContext);
230
if (CCPV->mustAddCurrentAddress()) {
231
// We want "(<expr> - .)", but MC doesn't have a concept of the '.'
232
// label, so just emit a local label end reference that instead.
233
MCSymbol *DotSym = OutContext.createTempSymbol();
234
OutStreamer->emitLabel(DotSym);
235
const MCExpr *DotExpr = MCSymbolRefExpr::create(DotSym, OutContext);
236
PCRelExpr = MCBinaryExpr::createSub(PCRelExpr, DotExpr, OutContext);
237
}
238
Expr = MCBinaryExpr::createSub(Expr, PCRelExpr, OutContext);
239
}
240
241
// Create an MCSymbol for the reference.
242
Expr = CSKYMCExpr::create(Expr, getModifierVariantKind(CCPV->getModifier()),
243
OutContext);
244
245
OutStreamer->emitValue(Expr, Size);
246
}
247
248
void CSKYAsmPrinter::emitAttributes() {
249
CSKYTargetStreamer &CTS =
250
static_cast<CSKYTargetStreamer &>(*OutStreamer->getTargetStreamer());
251
252
const Triple &TT = TM.getTargetTriple();
253
StringRef CPU = TM.getTargetCPU();
254
StringRef FS = TM.getTargetFeatureString();
255
const CSKYTargetMachine &CTM = static_cast<const CSKYTargetMachine &>(TM);
256
/* TuneCPU doesn't impact emission of ELF attributes, ELF attributes only
257
care about arch related features, so we can set TuneCPU as CPU. */
258
const CSKYSubtarget STI(TT, CPU, /*TuneCPU=*/CPU, FS, CTM);
259
260
CTS.emitTargetAttributes(STI);
261
}
262
263
bool CSKYAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
264
const char *ExtraCode, raw_ostream &OS) {
265
// First try the generic code, which knows about modifiers like 'c' and 'n'.
266
if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS))
267
return false;
268
269
const MachineOperand &MO = MI->getOperand(OpNo);
270
if (ExtraCode && ExtraCode[0]) {
271
if (ExtraCode[1] != 0)
272
return true; // Unknown modifier.
273
274
switch (ExtraCode[0]) {
275
default:
276
return true; // Unknown modifier.
277
case 'R':
278
if (MO.getType() == MachineOperand::MO_Register) {
279
OS << CSKYInstPrinter::getRegisterName(MO.getReg() + 1);
280
return false;
281
}
282
}
283
}
284
285
switch (MO.getType()) {
286
case MachineOperand::MO_Immediate:
287
OS << MO.getImm();
288
return false;
289
case MachineOperand::MO_Register:
290
if (MO.getReg() == CSKY::C)
291
return false;
292
OS << CSKYInstPrinter::getRegisterName(MO.getReg());
293
return false;
294
case MachineOperand::MO_GlobalAddress:
295
PrintSymbolOperand(MO, OS);
296
return false;
297
case MachineOperand::MO_BlockAddress: {
298
MCSymbol *Sym = GetBlockAddressSymbol(MO.getBlockAddress());
299
Sym->print(OS, MAI);
300
return false;
301
}
302
default:
303
break;
304
}
305
306
return true;
307
}
308
309
bool CSKYAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
310
unsigned OpNo, const char *ExtraCode,
311
raw_ostream &OS) {
312
if (!ExtraCode) {
313
const MachineOperand &MO = MI->getOperand(OpNo);
314
// For now, we only support register memory operands in registers and
315
// assume there is no addend
316
if (!MO.isReg())
317
return true;
318
319
OS << "(" << CSKYInstPrinter::getRegisterName(MO.getReg()) << ", 0)";
320
return false;
321
}
322
323
return AsmPrinter::PrintAsmMemoryOperand(MI, OpNo, ExtraCode, OS);
324
}
325
326
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeCSKYAsmPrinter() {
327
RegisterAsmPrinter<CSKYAsmPrinter> X(getTheCSKYTarget());
328
}
329
330