LLVM 24.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/IR/Module.h"
27#include "llvm/MC/MCAsmInfo.h"
28#include "llvm/MC/MCContext.h"
30#include "llvm/MC/MCStreamer.h"
32
33using namespace llvm;
34
35#define DEBUG_TYPE "csky-asm-printer"
36
37STATISTIC(CSKYNumInstrsCompressed,
38 "Number of C-SKY Compressed instructions emitted");
39
41 std::unique_ptr<llvm::MCStreamer> Streamer)
42 : AsmPrinter(TM, std::move(Streamer)), MCInstLowering(OutContext, *this) {}
43
45 MCP = MF.getConstantPool();
46 TII = MF.getSubtarget().getInstrInfo();
47
48 // Set the current MCSubtargetInfo to a copy which has the correct
49 // feature bits for the current MachineFunction
50 MCSubtargetInfo &NewSTI =
51 OutStreamer->getContext().getSubtargetCopy(TM.getMCSubtargetInfo());
52 NewSTI.setFeatureBits(MF.getSubtarget().getFeatureBits());
53 Subtarget = &NewSTI;
54
56}
57
58#define GEN_COMPRESS_INSTR
59#include "CSKYGenCompressInstEmitter.inc"
61 MCInst CInst;
62 bool Res = compressInst(CInst, Inst, *Subtarget);
63 if (Res)
64 ++CSKYNumInstrsCompressed;
65 AsmPrinter::EmitToStreamer(*OutStreamer, Res ? CInst : Inst);
66}
67
68// Simple pseudo-instructions have their lowering (with expansion to real
69// instructions) auto-generated.
70#include "CSKYGenMCPseudoLowering.inc"
71
72void CSKYAsmPrinter::expandTLSLA(const MachineInstr *MI) {
73 DebugLoc DL = MI->getDebugLoc();
74
77 "_" + Twine(MI->getOperand(3).getImm()));
78
79 OutStreamer->emitLabel(PCLabel);
80
81 auto Instr = BuildMI(*MF, DL, TII->get(CSKY::LRW32))
82 .add(MI->getOperand(0))
83 .add(MI->getOperand(2));
84 MCInst LRWInst;
85 MCInstLowering.Lower(Instr, LRWInst);
86 EmitToStreamer(*OutStreamer, LRWInst);
87
88 Instr = BuildMI(*MF, DL, TII->get(CSKY::GRS32))
89 .add(MI->getOperand(1))
90 .addSym(PCLabel);
91 MCInst GRSInst;
92 MCInstLowering.Lower(Instr, GRSInst);
93 EmitToStreamer(*OutStreamer, GRSInst);
94 return;
95}
96
97void CSKYAsmPrinter::emitCustomConstantPool(const MachineInstr *MI) {
98
99 // This instruction represents a floating constant pool in the function.
100 // The first operand is the ID# for this instruction, the second is the
101 // index into the MachineConstantPool that this is, the third is the size
102 // in bytes of this constant pool entry.
103 // The required alignment is specified on the basic block holding this MI.
104 unsigned LabelId = (unsigned)MI->getOperand(0).getImm();
105 unsigned CPIdx = (unsigned)MI->getOperand(1).getIndex();
106
107 // If this is the first entry of the pool, mark it.
108 if (!InConstantPool) {
109 OutStreamer->emitValueToAlignment(Align(4));
110 InConstantPool = true;
111 }
112
113 OutStreamer->emitLabel(GetCPISymbol(LabelId));
114
115 const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx];
118 else
119 emitGlobalConstant(MF->getDataLayout(), MCPE.Val.ConstVal);
120 return;
121}
122
124 // Make sure to terminate any constant pools that were at the end
125 // of the function.
126 if (!InConstantPool)
127 return;
128 InConstantPool = false;
129}
130
132 if (TM.getTargetTriple().isOSBinFormatELF())
133 emitAttributes(M);
134}
135
137 CSKYTargetStreamer &CTS =
138 static_cast<CSKYTargetStreamer &>(*OutStreamer->getTargetStreamer());
139
140 if (TM.getTargetTriple().isOSBinFormatELF())
142}
143
145 CSKY_MC::verifyInstructionPredicates(MI->getOpcode(),
146 getSubtargetInfo().getFeatureBits());
147
148 // Do any auto-generated pseudo lowerings.
149 if (MCInst OutInst; lowerPseudoInstExpansion(MI, OutInst)) {
150 EmitToStreamer(*OutStreamer, OutInst);
151 return;
152 }
153
154 // If we just ended a constant pool, mark it as such.
155 if (InConstantPool && MI->getOpcode() != CSKY::CONSTPOOL_ENTRY) {
156 InConstantPool = false;
157 }
158
159 if (MI->getOpcode() == CSKY::PseudoTLSLA32)
160 return expandTLSLA(MI);
161
162 if (MI->getOpcode() == CSKY::CONSTPOOL_ENTRY)
163 return emitCustomConstantPool(MI);
164
165 MCInst TmpInst;
166 MCInstLowering.Lower(MI, TmpInst);
167 EmitToStreamer(*OutStreamer, TmpInst);
168}
169
170// Convert a CSKY-specific constant pool modifier into the associated
171// MCSymbolRefExpr variant kind.
173 switch (Modifier) {
174 case CSKYCP::NO_MOD:
175 return CSKY::S_None;
176 case CSKYCP::ADDR:
177 return CSKY::S_ADDR;
178 case CSKYCP::GOT:
179 return CSKY::S_GOT;
180 case CSKYCP::GOTOFF:
181 return CSKY::S_GOTOFF;
182 case CSKYCP::PLT:
183 return CSKY::S_PLT;
184 case CSKYCP::TLSGD:
185 return CSKY::S_TLSGD;
186 case CSKYCP::TLSLE:
187 return CSKY::S_TLSLE;
188 case CSKYCP::TLSIE:
189 return CSKY::S_TLSIE;
190 }
191 llvm_unreachable("Invalid CSKYCPModifier!");
192}
193
197 CSKYConstantPoolValue *CCPV = static_cast<CSKYConstantPoolValue *>(MCPV);
198 MCSymbol *MCSym;
199
200 if (CCPV->isBlockAddress()) {
201 const BlockAddress *BA =
202 cast<CSKYConstantPoolConstant>(CCPV)->getBlockAddress();
203 MCSym = GetBlockAddressSymbol(BA);
204 } else if (CCPV->isGlobalValue()) {
205 const GlobalValue *GV = cast<CSKYConstantPoolConstant>(CCPV)->getGV();
206 MCSym = getSymbol(GV);
207 } else if (CCPV->isMachineBasicBlock()) {
208 const MachineBasicBlock *MBB = cast<CSKYConstantPoolMBB>(CCPV)->getMBB();
209 MCSym = MBB->getSymbol();
210 } else if (CCPV->isJT()) {
211 signed JTI = cast<CSKYConstantPoolJT>(CCPV)->getJTI();
212 MCSym = GetJTISymbol(JTI);
213 } else if (CCPV->isConstPool()) {
214 const Constant *C = cast<CSKYConstantPoolConstant>(CCPV)->getConstantPool();
215 MCSym = GetCPISymbol(MCP->getConstantPoolIndex(C, Align(4)));
216 } else {
217 assert(CCPV->isExtSymbol() && "unrecognized constant pool value");
218 StringRef Sym = cast<CSKYConstantPoolSymbol>(CCPV)->getSymbol();
219 MCSym = GetExternalSymbolSymbol(Sym);
220 }
221 // Create an MCSymbol for the reference.
222 const MCExpr *Expr = MCSymbolRefExpr::create(MCSym, OutContext);
223
224 if (CCPV->getPCAdjustment()) {
225
226 MCSymbol *PCLabel = OutContext.getOrCreateSymbol(
227 Twine(MAI.getInternalSymbolPrefix()) + "PC" +
228 Twine(getFunctionNumber()) + "_" + Twine(CCPV->getLabelID()));
229
230 const MCExpr *PCRelExpr = MCSymbolRefExpr::create(PCLabel, OutContext);
231 if (CCPV->mustAddCurrentAddress()) {
232 // We want "(<expr> - .)", but MC doesn't have a concept of the '.'
233 // label, so just emit a local label end reference that instead.
234 MCSymbol *DotSym = OutContext.createTempSymbol();
235 OutStreamer->emitLabel(DotSym);
236 const MCExpr *DotExpr = MCSymbolRefExpr::create(DotSym, OutContext);
237 PCRelExpr = MCBinaryExpr::createSub(PCRelExpr, DotExpr, OutContext);
238 }
239 Expr = MCBinaryExpr::createSub(Expr, PCRelExpr, OutContext);
240 }
241
242 // Create an MCSymbol for the reference.
245
246 OutStreamer->emitValue(Expr, Size);
247}
248
249void CSKYAsmPrinter::emitAttributes(Module &M) {
250 CSKYTargetStreamer &CTS =
251 static_cast<CSKYTargetStreamer &>(*OutStreamer->getTargetStreamer());
252
254 M.getFloatABI() == FloatABI::Hard);
255}
256
258 const char *ExtraCode, raw_ostream &OS) {
259 // First try the generic code, which knows about modifiers like 'c' and 'n'.
260 if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS))
261 return false;
262
263 const MachineOperand &MO = MI->getOperand(OpNo);
264 if (ExtraCode && ExtraCode[0]) {
265 if (ExtraCode[1] != 0)
266 return true; // Unknown modifier.
267
268 switch (ExtraCode[0]) {
269 default:
270 return true; // Unknown modifier.
271 case 'R':
274 return false;
275 }
276 }
277 }
278
279 switch (MO.getType()) {
281 OS << MO.getImm();
282 return false;
284 if (MO.getReg() == CSKY::C)
285 return false;
287 return false;
289 PrintSymbolOperand(MO, OS);
290 return false;
293 Sym->print(OS, MAI);
294 return false;
295 }
296 default:
297 break;
298 }
299
300 return true;
301}
302
304 unsigned OpNo, const char *ExtraCode,
305 raw_ostream &OS) {
306 if (!ExtraCode) {
307 const MachineOperand &MO = MI->getOperand(OpNo);
308 // For now, we only support register memory operands in registers and
309 // assume there is no addend
310 if (!MO.isReg())
311 return true;
312
313 OS << "(" << CSKYInstPrinter::getRegisterName(MO.getReg()) << ", 0)";
314 return false;
315 }
316
317 return AsmPrinter::PrintAsmMemoryOperand(MI, OpNo, ExtraCode, OS);
318}
319
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
#define X(NUM, ENUM, NAME)
Definition ELF.h:856
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
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
Module.h This file contains the declarations for the Module class.
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:171
MCSymbol * getSymbol(const GlobalValue *GV) const
void EmitToStreamer(MCStreamer &S, const MCInst &Inst)
TargetMachine & TM
Target machine description.
Definition AsmPrinter.h:94
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.
MachineFunction * MF
The current machine function.
Definition AsmPrinter.h:109
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:101
bool runOnMachineFunction(MachineFunction &MF) override
Emit the specified function out to the OutStreamer.
Definition AsmPrinter.h:453
std::unique_ptr< MCStreamer > OutStreamer
This is the MCStreamer object for the file we are generating.
Definition AsmPrinter.h:106
const MCAsmInfo & MAI
Target Asm Printer information.
Definition AsmPrinter.h:97
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:1088
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
void emitTargetAttributes(const MCSubtargetInfo &STI, bool HardFloatABI)
This is an important base class in LLVM.
Definition Constant.h:43
LLVM_ABI 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:126
StringRef getInternalSymbolPrefix() const
Definition MCAsmInfo.h:563
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:427
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:222
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:213
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
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
Primary interface to the complete machine description for the target machine.
const MCSubtargetInfo & getMCSubtargetInfo() const
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
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:1917
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878
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,...