LLVM 22.0.0git
XtensaAsmPrinter.cpp
Go to the documentation of this file.
1//===- XtensaAsmPrinter.cpp Xtensa LLVM Assembly Printer ------------------===//
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 Xtensa assembly language.
11//
12//===----------------------------------------------------------------------===//
13
14#include "XtensaAsmPrinter.h"
25#include "llvm/MC/MCExpr.h"
28#include "llvm/MC/MCStreamer.h"
29#include "llvm/MC/MCSymbol.h"
30#include "llvm/MC/MCSymbolELF.h"
32
33using namespace llvm;
34
37 switch (Modifier) {
39 return Xtensa::S_None;
40 case XtensaCP::TPOFF:
41 return Xtensa::S_TPOFF;
42 }
43 report_fatal_error("Invalid XtensaCPModifier!");
44}
45
47 unsigned Opc = MI->getOpcode();
48
49 switch (Opc) {
50 case Xtensa::BR_JT:
53 MCInstBuilder(Xtensa::JX).addReg(MI->getOperand(0).getReg()));
54 return;
55 default:
56 MCInst LoweredMI;
57 lowerToMCInst(MI, LoweredMI);
58 EmitToStreamer(*OutStreamer, LoweredMI);
59 return;
60 }
61}
62
65 XtensaConstantPoolValue *XtensaCPV =
66 static_cast<XtensaConstantPoolValue *>(MCPV);
67 MCSymbol *MCSym;
68
69 if (XtensaCPV->isBlockAddress()) {
70 const BlockAddress *BA =
71 cast<XtensaConstantPoolConstant>(XtensaCPV)->getBlockAddress();
72 MCSym = GetBlockAddressSymbol(BA);
73 } else if (XtensaCPV->isMachineBasicBlock()) {
74 const MachineBasicBlock *MBB =
75 cast<XtensaConstantPoolMBB>(XtensaCPV)->getMBB();
76 MCSym = MBB->getSymbol();
77 } else if (XtensaCPV->isJumpTable()) {
78 unsigned Idx = cast<XtensaConstantPoolJumpTable>(XtensaCPV)->getIndex();
79 MCSym = this->GetJTISymbol(Idx, false);
80 } else {
81 assert(XtensaCPV->isExtSymbol() && "unrecognized constant pool value");
82 XtensaConstantPoolSymbol *XtensaSym =
83 cast<XtensaConstantPoolSymbol>(XtensaCPV);
84 const char *SymName = XtensaSym->getSymbol();
85
86 if (XtensaSym->isPrivateLinkage()) {
87 const DataLayout &DL = getDataLayout();
88 MCSym = OutContext.getOrCreateSymbol(Twine(DL.getPrivateGlobalPrefix()) +
89 SymName);
90 } else {
91 MCSym = OutContext.getOrCreateSymbol(SymName);
92 }
93 }
94
95 MCSymbol *LblSym = GetCPISymbol(XtensaCPV->getLabelId());
96 auto *TS =
97 static_cast<XtensaTargetStreamer *>(OutStreamer->getTargetStreamer());
98 auto Spec = getModifierSpecifier(XtensaCPV->getModifier());
99
100 if (XtensaCPV->getModifier() != XtensaCP::no_modifier) {
101 std::string SymName(MCSym->getName());
102 StringRef Modifier = XtensaCPV->getModifierText();
103 SymName += Modifier;
104 MCSym = OutContext.getOrCreateSymbol(SymName);
105 }
106
107 const MCExpr *Expr = MCSymbolRefExpr::create(MCSym, Spec, OutContext);
108 TS->emitLiteral(LblSym, Expr, false);
109}
110
112 const MachineConstantPoolEntry &CPE, int i) {
113 if (CPE.isMachineConstantPoolEntry()) {
114 XtensaConstantPoolValue *XtensaCPV =
115 static_cast<XtensaConstantPoolValue *>(CPE.Val.MachineCPVal);
116 XtensaCPV->setLabelId(i);
118 } else {
119 MCSymbol *LblSym = GetCPISymbol(i);
120 auto *TS =
121 static_cast<XtensaTargetStreamer *>(OutStreamer->getTargetStreamer());
122 const Constant *C = CPE.Val.ConstVal;
123 const MCExpr *Value = nullptr;
124
125 Type *Ty = C->getType();
126 if (const auto *CFP = dyn_cast<ConstantFP>(C)) {
128 CFP->getValueAPF().bitcastToAPInt().getSExtValue(), OutContext);
129 } else if (const auto *CI = dyn_cast<ConstantInt>(C)) {
130 Value = MCConstantExpr::create(CI->getValue().getSExtValue(), OutContext);
131 } else if (isa<PointerType>(Ty)) {
133 } else {
134 llvm_unreachable("unexpected constant pool entry type");
135 }
136
137 TS->emitLiteral(LblSym, Value, false);
138 }
139}
140
141// EmitConstantPool - Print to the current output stream assembly
142// representations of the constants in the constant pool MCP. This is
143// used to print out constants which have been "spilled to memory" by
144// the code generator.
146 const Function &F = MF->getFunction();
147 const MachineConstantPool *MCP = MF->getConstantPool();
148 const std::vector<MachineConstantPoolEntry> &CP = MCP->getConstants();
149 if (CP.empty())
150 return;
151
152 OutStreamer->pushSection();
153
154 auto *TS =
155 static_cast<XtensaTargetStreamer *>(OutStreamer->getTargetStreamer());
157 TS->startLiteralSection(CS);
158
159 int CPIdx = 0;
160 for (const MachineConstantPoolEntry &CPE : CP) {
161 emitMachineConstantPoolEntry(CPE, CPIdx++);
162 }
163
164 OutStreamer->popSection();
165}
166
168 raw_ostream &O) {
169 const MachineOperand &MO = MI->getOperand(OpNo);
170
171 switch (MO.getType()) {
174 MCOperand MC = lowerOperand(MI->getOperand(OpNo));
176 break;
177 }
178 default:
179 llvm_unreachable("unknown operand type");
180 }
181}
182
184 const char *ExtraCode, raw_ostream &O) {
185 // Print the operand if there is no operand modifier.
186 if (!ExtraCode || !ExtraCode[0]) {
187 printOperand(MI, OpNo, O);
188 return false;
189 }
190
191 // Fallback to the default implementation.
192 return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);
193}
194
196 unsigned OpNo,
197 const char *ExtraCode,
198 raw_ostream &OS) {
199 if (ExtraCode && ExtraCode[0])
200 return true; // Unknown modifier.
201
202 assert(OpNo + 1 < MI->getNumOperands() && "Insufficient operands");
203
204 const MachineOperand &Base = MI->getOperand(OpNo);
205 const MachineOperand &Offset = MI->getOperand(OpNo + 1);
206
207 assert(Base.isReg() &&
208 "Unexpected base pointer for inline asm memory operand.");
209 assert(Offset.isImm() && "Unexpected offset for inline asm memory operand.");
210
212 OS << ", ";
213 OS << Offset.getImm();
214
215 return false;
216}
217
218MCSymbol *
220 // Create a symbol for the name.
221 return GetCPISymbol(MO.getIndex());
222}
223
225 return GetJTISymbol(MO.getIndex());
226}
227
231 unsigned Offset) const {
232 const MCSymbol *Symbol;
233 switch (MOTy) {
235 Symbol = getSymbol(MO.getGlobal());
236 Offset += MO.getOffset();
237 break;
239 Symbol = MO.getMBB()->getSymbol();
240 break;
243 Offset += MO.getOffset();
244 break;
247 Offset += MO.getOffset();
248 break;
250 Symbol = GetJumpTableSymbol(MO);
251 break;
253 Symbol = GetConstantPoolIndexSymbol(MO);
254 Offset += MO.getOffset();
255 break;
256 default:
257 report_fatal_error("<unknown operand type>");
258 }
259
260 const MCExpr *ME = MCSymbolRefExpr::create(Symbol, OutContext);
261 if (Offset) {
262 // Assume offset is never negative.
263 assert(Offset > 0);
264
265 const MCConstantExpr *OffsetExpr =
267 ME = MCBinaryExpr::createAdd(ME, OffsetExpr, OutContext);
268 }
269
270 return MCOperand::createExpr(ME);
271}
272
274 unsigned Offset) const {
276
277 switch (MOTy) {
279 // Ignore all implicit register operands.
280 if (MO.isImplicit())
281 break;
282 return MCOperand::createReg(MO.getReg());
284 return MCOperand::createImm(MO.getImm() + Offset);
286 break;
293 return LowerSymbolOperand(MO, MOTy, Offset);
294 default:
295 report_fatal_error("unknown operand type");
296 }
297
298 return MCOperand();
299}
300
302 MCInst &OutMI) const {
303 OutMI.setOpcode(MI->getOpcode());
304
305 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
306 const MachineOperand &MO = MI->getOperand(i);
307 MCOperand MCOp = lowerOperand(MO);
308
309 if (MCOp.isValid())
310 OutMI.addOperand(MCOp);
311 }
312}
313
314char XtensaAsmPrinter::ID = 0;
315
316INITIALIZE_PASS(XtensaAsmPrinter, "xtensa-asm-printer",
317 "Xtensa Assembly Printer", false, false)
318
319extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXtensaAsmPrinter() {
321}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static uint8_t getModifierSpecifier(ARMCP::ARMCPModifier Modifier)
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
#define LLVM_EXTERNAL_VISIBILITY
Definition: Compiler.h:132
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
IRTranslator LLVM IR MI
#define F(x, y, z)
Definition: MD5.cpp:55
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:56
raw_pwrite_stream & OS
This file contains some functions that are useful when dealing with strings.
static Xtensa::Specifier getModifierSpecifier(XtensaCP::XtensaCPModifier Modifier)
const TargetLoweringObjectFile & getObjFileLowering() const
Return information about object file lowering.
Definition: AsmPrinter.cpp:413
MCSymbol * getSymbol(const GlobalValue *GV) const
Definition: AsmPrinter.cpp:706
void EmitToStreamer(MCStreamer &S, const MCInst &Inst)
Definition: AsmPrinter.cpp:433
TargetMachine & TM
Target machine description.
Definition: AsmPrinter.h:93
virtual MCSymbol * GetCPISymbol(unsigned CPID) const
Return the symbol for the specified constant pool entry.
MachineFunction * MF
The current machine function.
Definition: AsmPrinter.h:108
virtual const MCExpr * lowerConstant(const Constant *CV, const Constant *BaseCV=nullptr, uint64_t Offset=0)
Lower the specified LLVM Constant to an MCExpr.
MCSymbol * GetJTISymbol(unsigned JTID, bool isLinkerPrivate=false) const
Return the symbol for the specified jump table entry.
MCContext & OutContext
This is the context for the output file that we are streaming.
Definition: AsmPrinter.h:100
std::unique_ptr< MCStreamer > OutStreamer
This is the MCStreamer object for the file we are generating.
Definition: AsmPrinter.h:105
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.
Definition: AsmPrinter.cpp:417
MCSymbol * GetExternalSymbolSymbol(const Twine &Sym) const
Return the MCSymbol for the specified ExternalSymbol.
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
This is an important base class in LLVM.
Definition: Constant.h:43
A parsed version of the target data layout string in and methods for querying it.
Definition: DataLayout.h:63
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition: MCExpr.h:343
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition: MCExpr.cpp:212
LLVM_ABI MCSymbol * getOrCreateSymbol(const Twine &Name)
Lookup the symbol inside with the specified Name.
Definition: MCContext.cpp:203
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
void addOperand(const MCOperand Op)
Definition: MCInst.h:215
void setOpcode(unsigned Op)
Definition: MCInst.h:201
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:40
static MCOperand createExpr(const MCExpr *Val)
Definition: MCInst.h:166
static MCOperand createReg(MCRegister Reg)
Definition: MCInst.h:138
static MCOperand createImm(int64_t Val)
Definition: MCInst.h:145
bool isValid() const
Definition: MCInst.h:64
Instances of this class represent a uniqued identifier for a section in the current translation unit.
Definition: MCSection.h:496
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
StringRef getName() const
getName - Get the symbol name.
Definition: MCSymbol.h:188
LLVM_ABI MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
This class is a data container for one entry in a MachineConstantPool.
union llvm::MachineConstantPoolEntry::@205 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.
The MachineConstantPool class keeps track of constants referenced by a function which must be spilled...
const std::vector< MachineConstantPoolEntry > & getConstants() const
Function & getFunction()
Return the LLVM function that this machine code represents.
MachineConstantPool * getConstantPool()
getConstantPool - Return the constant pool object for the current function.
Representation of each machine instruction.
Definition: MachineInstr.h:72
MachineOperand class - Representation of each machine instruction operand.
const GlobalValue * getGlobal() const
int64_t getImm() const
bool isImplicit() const
MachineBasicBlock * getMBB() const
const BlockAddress * getBlockAddress() const
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
const char * getSymbolName() const
Register getReg() const
getReg - Returns the register number.
@ MO_Immediate
Immediate operand.
@ MO_ConstantPoolIndex
Address of indexed Constant in Constant Pool.
@ MO_GlobalAddress
Address of a global value.
@ MO_RegisterMask
Mask of preserved registers.
@ MO_BlockAddress
Address of a basic block.
@ MO_MachineBasicBlock
MachineBasicBlock reference.
@ MO_Register
Register operand.
@ MO_ExternalSymbol
Name of external global symbol.
@ MO_JumpTableIndex
Address of indexed Jump Table for switch.
int64_t getOffset() const
Return the offset from the symbol in this operand.
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:55
MCSection * SectionForGlobal(const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const
This method computes the appropriate section to emit the specified global variable or function defini...
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:82
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
LLVM Value Representation.
Definition: Value.h:75
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &O) override
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant.
MCOperand LowerSymbolOperand(const MachineOperand &MO, MachineOperand::MachineOperandType MOTy, unsigned Offset) const
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...
void emitMachineConstantPoolEntry(const MachineConstantPoolEntry &CPE, int i)
void emitConstantPool() override
Print to the current output stream assembly representations of the constants in the constant pool MCP...
void lowerToMCInst(const MachineInstr *MI, MCInst &OutMI) const
void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O)
MCSymbol * GetConstantPoolIndexSymbol(const MachineOperand &MO) const
void emitInstruction(const MachineInstr *MI) override
Targets should implement this to emit instructions.
MCSymbol * GetJumpTableSymbol(const MachineOperand &MO) const
void emitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) override
MCOperand lowerOperand(const MachineOperand &MO, unsigned Offset=0) const
XtensaConstantPoolSymbol - Xtensa-specific constantpool values for external symbols.
XtensaConstantPoolValue - Xtensa specific constantpool value.
XtensaCP::XtensaCPModifier getModifier() const
static const char * getRegisterName(MCRegister Reg)
static void printOperand(const MCOperand &MO, raw_ostream &O)
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.
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:477
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition: Error.cpp:167
Target & getTheXtensaTarget()
RegisterAsmPrinter - Helper template for registering a target specific assembly printer,...