1 //===- XtensaAsmPrinter.cpp Xtensa LLVM Assembly Printer ------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file contains a printer that converts from our internal representation
10 // of machine-dependent LLVM code to GAS-format Xtensa assembly language.
12 //===----------------------------------------------------------------------===//
14 #include "XtensaAsmPrinter.h"
15 #include "MCTargetDesc/XtensaInstPrinter.h"
16 #include "MCTargetDesc/XtensaMCExpr.h"
17 #include "MCTargetDesc/XtensaTargetStreamer.h"
18 #include "TargetInfo/XtensaTargetInfo.h"
19 #include "XtensaConstantPoolValue.h"
20 #include "llvm/ADT/StringExtras.h"
21 #include "llvm/BinaryFormat/ELF.h"
22 #include "llvm/CodeGen/MachineConstantPool.h"
23 #include "llvm/CodeGen/MachineModuleInfoImpls.h"
24 #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
25 #include "llvm/MC/MCExpr.h"
26 #include "llvm/MC/MCInstBuilder.h"
27 #include "llvm/MC/MCSectionELF.h"
28 #include "llvm/MC/MCStreamer.h"
29 #include "llvm/MC/MCSymbol.h"
30 #include "llvm/MC/MCSymbolELF.h"
31 #include "llvm/MC/TargetRegistry.h"
35 static MCSymbolRefExpr::VariantKind
36 getModifierVariantKind(XtensaCP::XtensaCPModifier Modifier
) {
38 case XtensaCP::no_modifier
:
39 return MCSymbolRefExpr::VK_None
;
41 return MCSymbolRefExpr::VK_TPOFF
;
43 report_fatal_error("Invalid XtensaCPModifier!");
46 void XtensaAsmPrinter::emitInstruction(const MachineInstr
*MI
) {
47 unsigned Opc
= MI
->getOpcode();
53 MCInstBuilder(Xtensa::JX
).addReg(MI
->getOperand(0).getReg()));
57 lowerToMCInst(MI
, LoweredMI
);
58 EmitToStreamer(*OutStreamer
, LoweredMI
);
63 void XtensaAsmPrinter::emitMachineConstantPoolValue(
64 MachineConstantPoolValue
*MCPV
) {
65 XtensaConstantPoolValue
*ACPV
= static_cast<XtensaConstantPoolValue
*>(MCPV
);
68 if (ACPV
->isBlockAddress()) {
69 const BlockAddress
*BA
=
70 cast
<XtensaConstantPoolConstant
>(ACPV
)->getBlockAddress();
71 MCSym
= GetBlockAddressSymbol(BA
);
72 } else if (ACPV
->isMachineBasicBlock()) {
73 const MachineBasicBlock
*MBB
= cast
<XtensaConstantPoolMBB
>(ACPV
)->getMBB();
74 MCSym
= MBB
->getSymbol();
75 } else if (ACPV
->isJumpTable()) {
76 unsigned Idx
= cast
<XtensaConstantPoolJumpTable
>(ACPV
)->getIndex();
77 MCSym
= this->GetJTISymbol(Idx
, false);
79 assert(ACPV
->isExtSymbol() && "unrecognized constant pool value");
80 XtensaConstantPoolSymbol
*XtensaSym
= cast
<XtensaConstantPoolSymbol
>(ACPV
);
81 const char *SymName
= XtensaSym
->getSymbol();
83 if (XtensaSym
->isPrivateLinkage()) {
84 const DataLayout
&DL
= getDataLayout();
85 MCSym
= OutContext
.getOrCreateSymbol(Twine(DL
.getPrivateGlobalPrefix()) +
88 MCSym
= OutContext
.getOrCreateSymbol(SymName
);
92 MCSymbol
*LblSym
= GetCPISymbol(ACPV
->getLabelId());
94 static_cast<XtensaTargetStreamer
*>(OutStreamer
->getTargetStreamer());
95 MCSymbolRefExpr::VariantKind VK
= getModifierVariantKind(ACPV
->getModifier());
97 if (ACPV
->getModifier() != XtensaCP::no_modifier
) {
98 std::string
SymName(MCSym
->getName());
99 StringRef Modifier
= ACPV
->getModifierText();
101 MCSym
= OutContext
.getOrCreateSymbol(SymName
);
104 const MCExpr
*Expr
= MCSymbolRefExpr::create(MCSym
, VK
, OutContext
);
105 TS
->emitLiteral(LblSym
, Expr
, false);
108 void XtensaAsmPrinter::emitMachineConstantPoolEntry(
109 const MachineConstantPoolEntry
&CPE
, int i
) {
110 if (CPE
.isMachineConstantPoolEntry()) {
111 XtensaConstantPoolValue
*ACPV
=
112 static_cast<XtensaConstantPoolValue
*>(CPE
.Val
.MachineCPVal
);
114 emitMachineConstantPoolValue(CPE
.Val
.MachineCPVal
);
116 MCSymbol
*LblSym
= GetCPISymbol(i
);
118 static_cast<XtensaTargetStreamer
*>(OutStreamer
->getTargetStreamer());
119 const Constant
*C
= CPE
.Val
.ConstVal
;
120 const MCExpr
*Value
= nullptr;
122 Type
*Ty
= C
->getType();
123 if (const auto *CFP
= dyn_cast
<ConstantFP
>(C
)) {
124 Value
= MCConstantExpr::create(
125 CFP
->getValueAPF().bitcastToAPInt().getSExtValue(), OutContext
);
126 } else if (const auto *CI
= dyn_cast
<ConstantInt
>(C
)) {
127 Value
= MCConstantExpr::create(CI
->getValue().getSExtValue(), OutContext
);
128 } else if (isa
<PointerType
>(Ty
)) {
129 Value
= lowerConstant(C
);
131 llvm_unreachable("unexpected constant pool entry type");
134 TS
->emitLiteral(LblSym
, Value
, false);
138 // EmitConstantPool - Print to the current output stream assembly
139 // representations of the constants in the constant pool MCP. This is
140 // used to print out constants which have been "spilled to memory" by
141 // the code generator.
142 void XtensaAsmPrinter::emitConstantPool() {
143 const Function
&F
= MF
->getFunction();
144 const MachineConstantPool
*MCP
= MF
->getConstantPool();
145 const std::vector
<MachineConstantPoolEntry
> &CP
= MCP
->getConstants();
149 OutStreamer
->pushSection();
152 static_cast<XtensaTargetStreamer
*>(OutStreamer
->getTargetStreamer());
153 MCSection
*CS
= getObjFileLowering().SectionForGlobal(&F
, TM
);
154 TS
->startLiteralSection(CS
);
157 for (const MachineConstantPoolEntry
&CPE
: CP
) {
158 emitMachineConstantPoolEntry(CPE
, CPIdx
++);
161 OutStreamer
->popSection();
164 void XtensaAsmPrinter::printOperand(const MachineInstr
*MI
, int OpNo
,
166 const MachineOperand
&MO
= MI
->getOperand(OpNo
);
168 switch (MO
.getType()) {
169 case MachineOperand::MO_Register
:
170 case MachineOperand::MO_Immediate
: {
171 MCOperand MC
= lowerOperand(MI
->getOperand(OpNo
));
172 XtensaInstPrinter::printOperand(MC
, O
);
176 llvm_unreachable("unknown operand type");
180 bool XtensaAsmPrinter::PrintAsmOperand(const MachineInstr
*MI
, unsigned OpNo
,
181 const char *ExtraCode
, raw_ostream
&O
) {
182 // Print the operand if there is no operand modifier.
183 if (!ExtraCode
|| !ExtraCode
[0]) {
184 printOperand(MI
, OpNo
, O
);
188 // Fallback to the default implementation.
189 return AsmPrinter::PrintAsmOperand(MI
, OpNo
, ExtraCode
, O
);
192 bool XtensaAsmPrinter::PrintAsmMemoryOperand(const MachineInstr
*MI
,
194 const char *ExtraCode
,
196 if (ExtraCode
&& ExtraCode
[0])
197 return true; // Unknown modifier.
199 assert(OpNo
+ 1 < MI
->getNumOperands() && "Insufficient operands");
201 const MachineOperand
&Base
= MI
->getOperand(OpNo
);
202 const MachineOperand
&Offset
= MI
->getOperand(OpNo
+ 1);
204 assert(Base
.isReg() &&
205 "Unexpected base pointer for inline asm memory operand.");
206 assert(Offset
.isImm() && "Unexpected offset for inline asm memory operand.");
208 OS
<< XtensaInstPrinter::getRegisterName(Base
.getReg());
210 OS
<< Offset
.getImm();
216 XtensaAsmPrinter::GetConstantPoolIndexSymbol(const MachineOperand
&MO
) const {
217 // Create a symbol for the name.
218 return GetCPISymbol(MO
.getIndex());
221 MCSymbol
*XtensaAsmPrinter::GetJumpTableSymbol(const MachineOperand
&MO
) const {
222 return GetJTISymbol(MO
.getIndex());
226 XtensaAsmPrinter::LowerSymbolOperand(const MachineOperand
&MO
,
227 MachineOperand::MachineOperandType MOTy
,
228 unsigned Offset
) const {
229 const MCSymbol
*Symbol
;
230 XtensaMCExpr::VariantKind Kind
= XtensaMCExpr::VK_Xtensa_None
;
233 case MachineOperand::MO_GlobalAddress
:
234 Symbol
= getSymbol(MO
.getGlobal());
235 Offset
+= MO
.getOffset();
237 case MachineOperand::MO_MachineBasicBlock
:
238 Symbol
= MO
.getMBB()->getSymbol();
240 case MachineOperand::MO_BlockAddress
:
241 Symbol
= GetBlockAddressSymbol(MO
.getBlockAddress());
242 Offset
+= MO
.getOffset();
244 case MachineOperand::MO_ExternalSymbol
:
245 Symbol
= GetExternalSymbolSymbol(MO
.getSymbolName());
246 Offset
+= MO
.getOffset();
248 case MachineOperand::MO_JumpTableIndex
:
249 Symbol
= GetJumpTableSymbol(MO
);
251 case MachineOperand::MO_ConstantPoolIndex
:
252 Symbol
= GetConstantPoolIndexSymbol(MO
);
253 Offset
+= MO
.getOffset();
256 report_fatal_error("<unknown operand type>");
260 MCSymbolRefExpr::create(Symbol
, MCSymbolRefExpr::VK_None
, OutContext
);
261 ME
= XtensaMCExpr::create(ME
, Kind
, OutContext
);
264 // Assume offset is never negative.
267 const MCConstantExpr
*OffsetExpr
=
268 MCConstantExpr::create(Offset
, OutContext
);
269 ME
= MCBinaryExpr::createAdd(ME
, OffsetExpr
, OutContext
);
272 return MCOperand::createExpr(ME
);
275 MCOperand
XtensaAsmPrinter::lowerOperand(const MachineOperand
&MO
,
276 unsigned Offset
) const {
277 MachineOperand::MachineOperandType MOTy
= MO
.getType();
280 case MachineOperand::MO_Register
:
281 // Ignore all implicit register operands.
284 return MCOperand::createReg(MO
.getReg());
285 case MachineOperand::MO_Immediate
:
286 return MCOperand::createImm(MO
.getImm() + Offset
);
287 case MachineOperand::MO_RegisterMask
:
289 case MachineOperand::MO_GlobalAddress
:
290 case MachineOperand::MO_MachineBasicBlock
:
291 case MachineOperand::MO_BlockAddress
:
292 case MachineOperand::MO_ExternalSymbol
:
293 case MachineOperand::MO_JumpTableIndex
:
294 case MachineOperand::MO_ConstantPoolIndex
:
295 return LowerSymbolOperand(MO
, MOTy
, Offset
);
297 report_fatal_error("unknown operand type");
303 void XtensaAsmPrinter::lowerToMCInst(const MachineInstr
*MI
,
304 MCInst
&OutMI
) const {
305 OutMI
.setOpcode(MI
->getOpcode());
307 for (unsigned i
= 0, e
= MI
->getNumOperands(); i
!= e
; ++i
) {
308 const MachineOperand
&MO
= MI
->getOperand(i
);
309 MCOperand MCOp
= lowerOperand(MO
);
312 OutMI
.addOperand(MCOp
);
316 extern "C" LLVM_EXTERNAL_VISIBILITY
void LLVMInitializeXtensaAsmPrinter() {
317 RegisterAsmPrinter
<XtensaAsmPrinter
> A(getTheXtensaTarget());