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