LLVM 22.0.0git
CSKYAsmPrinter.cpp
Go to the documentation of this file.
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"
16#include "CSKYTargetMachine.h"
21#include "llvm/ADT/Statistic.h"
25#include "llvm/IR/DataLayout.h"
26#include "llvm/MC/MCAsmInfo.h"
27#include "llvm/MC/MCContext.h"
29#include "llvm/MC/MCStreamer.h"
31
32using namespace llvm;
33
34#define DEBUG_TYPE "csky-asm-printer"
35
36STATISTIC(CSKYNumInstrsCompressed,
37 "Number of C-SKY Compressed instructions emitted");
38
40 std::unique_ptr<llvm::MCStreamer> Streamer)
41 : AsmPrinter(TM, std::move(Streamer)), MCInstLowering(OutContext, *this) {}
42
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
55}
56
57#define GEN_COMPRESS_INSTR
58#include "CSKYGenCompressInstEmitter.inc"
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
71void CSKYAsmPrinter::expandTLSLA(const MachineInstr *MI) {
72 DebugLoc DL = MI->getDebugLoc();
73
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
96void 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];
117 else
118 emitGlobalConstant(MF->getDataLayout(), MCPE.Val.ConstVal);
119 return;
120}
121
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
131 if (TM.getTargetTriple().isOSBinFormatELF())
132 emitAttributes();
133}
134
136 CSKYTargetStreamer &CTS =
137 static_cast<CSKYTargetStreamer &>(*OutStreamer->getTargetStreamer());
138
139 if (TM.getTargetTriple().isOSBinFormatELF())
141}
142
144 CSKY_MC::verifyInstructionPredicates(MI->getOpcode(),
145 getSubtargetInfo().getFeatureBits());
146
147 // Do any auto-generated pseudo lowerings.
148 if (MCInst OutInst; lowerPseudoInstExpansion(MI, OutInst)) {
149 EmitToStreamer(*OutStreamer, OutInst);
150 return;
151 }
152
153 // If we just ended a constant pool, mark it as such.
154 if (InConstantPool && MI->getOpcode() != CSKY::CONSTPOOL_ENTRY) {
155 InConstantPool = false;
156 }
157
158 if (MI->getOpcode() == CSKY::PseudoTLSLA32)
159 return expandTLSLA(MI);
160
161 if (MI->getOpcode() == CSKY::CONSTPOOL_ENTRY)
162 return emitCustomConstantPool(MI);
163
164 MCInst TmpInst;
165 MCInstLowering.Lower(MI, TmpInst);
166 EmitToStreamer(*OutStreamer, TmpInst);
167}
168
169// Convert a CSKY-specific constant pool modifier into the associated
170// MCSymbolRefExpr variant kind.
172 switch (Modifier) {
173 case CSKYCP::NO_MOD:
174 return CSKY::S_None;
175 case CSKYCP::ADDR:
176 return CSKY::S_ADDR;
177 case CSKYCP::GOT:
178 return CSKY::S_GOT;
179 case CSKYCP::GOTOFF:
180 return CSKY::S_GOTOFF;
181 case CSKYCP::PLT:
182 return CSKY::S_PLT;
183 case CSKYCP::TLSGD:
184 return CSKY::S_TLSGD;
185 case CSKYCP::TLSLE:
186 return CSKY::S_TLSLE;
187 case CSKYCP::TLSIE:
188 return CSKY::S_TLSIE;
189 }
190 llvm_unreachable("Invalid CSKYCPModifier!");
191}
192
196 CSKYConstantPoolValue *CCPV = static_cast<CSKYConstantPoolValue *>(MCPV);
197 MCSymbol *MCSym;
198
199 if (CCPV->isBlockAddress()) {
200 const BlockAddress *BA =
201 cast<CSKYConstantPoolConstant>(CCPV)->getBlockAddress();
202 MCSym = GetBlockAddressSymbol(BA);
203 } else if (CCPV->isGlobalValue()) {
204 const GlobalValue *GV = cast<CSKYConstantPoolConstant>(CCPV)->getGV();
205 MCSym = getSymbol(GV);
206 } else if (CCPV->isMachineBasicBlock()) {
207 const MachineBasicBlock *MBB = cast<CSKYConstantPoolMBB>(CCPV)->getMBB();
208 MCSym = MBB->getSymbol();
209 } else if (CCPV->isJT()) {
210 signed JTI = cast<CSKYConstantPoolJT>(CCPV)->getJTI();
211 MCSym = GetJTISymbol(JTI);
212 } else if (CCPV->isConstPool()) {
213 const Constant *C = cast<CSKYConstantPoolConstant>(CCPV)->getConstantPool();
214 MCSym = GetCPISymbol(MCP->getConstantPoolIndex(C, Align(4)));
215 } else {
216 assert(CCPV->isExtSymbol() && "unrecognized constant pool value");
217 StringRef Sym = cast<CSKYConstantPoolSymbol>(CCPV)->getSymbol();
218 MCSym = GetExternalSymbolSymbol(Sym);
219 }
220 // Create an MCSymbol for the reference.
221 const MCExpr *Expr = MCSymbolRefExpr::create(MCSym, 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.
244
245 OutStreamer->emitValue(Expr, Size);
246}
247
248void CSKYAsmPrinter::emitAttributes() {
249 CSKYTargetStreamer &CTS =
250 static_cast<CSKYTargetStreamer &>(*OutStreamer->getTargetStreamer());
251
252 const Triple &TT = TM.getTargetTriple();
253 StringRef CPU = TM.getTargetCPU();
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
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':
280 return false;
281 }
282 }
283 }
284
285 switch (MO.getType()) {
287 OS << MO.getImm();
288 return false;
290 if (MO.getReg() == CSKY::C)
291 return false;
293 return false;
295 PrintSymbolOperand(MO, OS);
296 return false;
299 Sym->print(OS, MAI);
300 return false;
301 }
302 default:
303 break;
304 }
305
306 return true;
307}
308
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
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeCSKYAsmPrinter()
static CSKY::Specifier getModifierVariantKind(CSKYCP::CSKYCPModifier Modifier)
#define LLVM_EXTERNAL_VISIBILITY
Definition Compiler.h:132
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition Statistic.h:167
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
MCSymbol * getSymbol(const GlobalValue *GV) const
void EmitToStreamer(MCStreamer &S, const MCInst &Inst)
TargetMachine & TM
Target machine description.
Definition AsmPrinter.h:93
virtual MCSymbol * GetCPISymbol(unsigned CPID) const
Return the symbol for the specified constant pool entry.
virtual void PrintSymbolOperand(const MachineOperand &MO, raw_ostream &OS)
Print the MachineOperand as a symbol.
const MCAsmInfo * MAI
Target Asm Printer information.
Definition AsmPrinter.h:96
MachineFunction * MF
The current machine function.
Definition AsmPrinter.h:108
MCSymbol * GetJTISymbol(unsigned JTID, bool isLinkerPrivate=false) const
Return the symbol for the specified jump table entry.
unsigned getFunctionNumber() const
Return a unique ID for the current function.
AsmPrinter(TargetMachine &TM, std::unique_ptr< MCStreamer > Streamer, char &ID=AsmPrinter::ID)
void emitGlobalConstant(const DataLayout &DL, const Constant *CV, AliasMapTy *AliasList=nullptr)
EmitGlobalConstant - Print a general LLVM constant to the .s file.
MCContext & OutContext
This is the context for the output file that we are streaming.
Definition AsmPrinter.h:100
bool runOnMachineFunction(MachineFunction &MF) override
Emit the specified function out to the OutStreamer.
Definition AsmPrinter.h:452
std::unique_ptr< MCStreamer > OutStreamer
This is the MCStreamer object for the file we are generating.
Definition AsmPrinter.h:105
virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS)
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant as...
MCSymbol * GetBlockAddressSymbol(const BlockAddress *BA) const
Return the MCSymbol used to satisfy BlockAddress uses of the specified basic block.
const DataLayout & getDataLayout() const
Return information about data layout.
MCSymbol * GetExternalSymbolSymbol(const Twine &Sym) const
Return the MCSymbol for the specified ExternalSymbol.
const MCSubtargetInfo & getSubtargetInfo() const
Return information about subtarget.
virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS)
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant.
The address of a basic block.
Definition Constants.h:899
void emitFunctionBodyEnd() override
Targets can override this to emit stuff after the last basic block in the function.
void EmitToStreamer(MCStreamer &S, const MCInst &Inst)
CSKYAsmPrinter(TargetMachine &TM, std::unique_ptr< MCStreamer > Streamer)
bool lowerPseudoInstExpansion(const MachineInstr *MI, MCInst &Inst)
tblgen'erated driver function for lowering simple MI->MC pseudo instructions.
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS) override
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant.
void emitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) override
bool runOnMachineFunction(MachineFunction &MF) override
Emit the specified function out to the OutStreamer.
void emitEndOfAsmFile(Module &M) override
This virtual method can be overridden by targets that want to emit something at the end of their file...
void emitInstruction(const MachineInstr *MI) override
Targets should implement this to emit instructions.
void emitStartOfAsmFile(Module &M) override
This virtual method can be overridden by targets that want to emit something at the start of their fi...
bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS) override
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant as...
CSKYConstantPoolValue - CSKY specific constantpool value.
CSKYCP::CSKYCPModifier getModifier() const
static const char * getRegisterName(MCRegister Reg)
void Lower(const MachineInstr *MI, MCInst &OutMI) const
virtual void emitTargetAttributes(const MCSubtargetInfo &STI)
This is an important base class in LLVM.
Definition Constant.h:43
TypeSize getTypeAllocSize(Type *Ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...
A debug info location.
Definition DebugLoc.h:124
StringRef getPrivateGlobalPrefix() const
Definition MCAsmInfo.h:545
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:428
LLVM_ABI MCSymbol * getOrCreateSymbol(const Twine &Name)
Lookup the symbol inside with the specified Name.
Base class for the full range of assembler expressions which are needed for parsing.
Definition MCExpr.h:34
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
static const MCSpecifierExpr * create(const MCExpr *Expr, Spec S, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.cpp:743
Streaming machine code generation interface.
Definition MCStreamer.h:220
Generic base class for all target subtargets.
void setFeatureBits(const FeatureBitset &FeatureBits_)
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:214
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition MCSymbol.h:42
LLVM_ABI void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
Definition MCSymbol.cpp:59
union llvm::MachineConstantPoolEntry::@004270020304201266316354007027341142157160323045 Val
The constant itself.
bool isMachineConstantPoolEntry() const
isMachineConstantPoolEntry - Return true if the MachineConstantPoolEntry is indeed a target specific ...
MachineConstantPoolValue * MachineCPVal
Abstract base class for all machine specific constantpool value subclasses.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addSym(MCSymbol *Sym, unsigned char TargetFlags=0) const
Representation of each machine instruction.
MachineOperand class - Representation of each machine instruction operand.
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
const BlockAddress * getBlockAddress() const
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
Register getReg() const
getReg - Returns the register number.
@ MO_Immediate
Immediate operand.
@ MO_GlobalAddress
Address of a global value.
@ MO_BlockAddress
Address of a basic block.
@ MO_Register
Register operand.
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
Primary interface to the complete machine description for the target machine.
const Triple & getTargetTriple() const
StringRef getTargetFeatureString() const
StringRef getTargetCPU() const
Triple - Helper class for working with autoconf configuration names.
Definition Triple.h:47
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
uint8_t Specifier
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
Target & getTheCSKYTarget()
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1849
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:565
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:851
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
RegisterAsmPrinter - Helper template for registering a target specific assembly printer,...