1*0fca6ea1SDimitry Andric //===- XtensaAsmPrinter.cpp Xtensa LLVM Assembly Printer ------------------===//
2*0fca6ea1SDimitry Andric //
3*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0fca6ea1SDimitry Andric //
7*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===//
8*0fca6ea1SDimitry Andric //
9*0fca6ea1SDimitry Andric // This file contains a printer that converts from our internal representation
10*0fca6ea1SDimitry Andric // of machine-dependent LLVM code to GAS-format Xtensa assembly language.
11*0fca6ea1SDimitry Andric //
12*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===//
13*0fca6ea1SDimitry Andric
14*0fca6ea1SDimitry Andric #include "XtensaAsmPrinter.h"
15*0fca6ea1SDimitry Andric #include "MCTargetDesc/XtensaMCExpr.h"
16*0fca6ea1SDimitry Andric #include "MCTargetDesc/XtensaTargetStreamer.h"
17*0fca6ea1SDimitry Andric #include "TargetInfo/XtensaTargetInfo.h"
18*0fca6ea1SDimitry Andric #include "XtensaConstantPoolValue.h"
19*0fca6ea1SDimitry Andric #include "llvm/ADT/StringExtras.h"
20*0fca6ea1SDimitry Andric #include "llvm/BinaryFormat/ELF.h"
21*0fca6ea1SDimitry Andric #include "llvm/CodeGen/MachineConstantPool.h"
22*0fca6ea1SDimitry Andric #include "llvm/CodeGen/MachineModuleInfoImpls.h"
23*0fca6ea1SDimitry Andric #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
24*0fca6ea1SDimitry Andric #include "llvm/MC/MCExpr.h"
25*0fca6ea1SDimitry Andric #include "llvm/MC/MCInstBuilder.h"
26*0fca6ea1SDimitry Andric #include "llvm/MC/MCSectionELF.h"
27*0fca6ea1SDimitry Andric #include "llvm/MC/MCStreamer.h"
28*0fca6ea1SDimitry Andric #include "llvm/MC/MCSymbol.h"
29*0fca6ea1SDimitry Andric #include "llvm/MC/MCSymbolELF.h"
30*0fca6ea1SDimitry Andric #include "llvm/MC/TargetRegistry.h"
31*0fca6ea1SDimitry Andric
32*0fca6ea1SDimitry Andric using namespace llvm;
33*0fca6ea1SDimitry Andric
34*0fca6ea1SDimitry Andric static MCSymbolRefExpr::VariantKind
getModifierVariantKind(XtensaCP::XtensaCPModifier Modifier)35*0fca6ea1SDimitry Andric getModifierVariantKind(XtensaCP::XtensaCPModifier Modifier) {
36*0fca6ea1SDimitry Andric switch (Modifier) {
37*0fca6ea1SDimitry Andric case XtensaCP::no_modifier:
38*0fca6ea1SDimitry Andric return MCSymbolRefExpr::VK_None;
39*0fca6ea1SDimitry Andric case XtensaCP::TPOFF:
40*0fca6ea1SDimitry Andric return MCSymbolRefExpr::VK_TPOFF;
41*0fca6ea1SDimitry Andric }
42*0fca6ea1SDimitry Andric report_fatal_error("Invalid XtensaCPModifier!");
43*0fca6ea1SDimitry Andric }
44*0fca6ea1SDimitry Andric
emitInstruction(const MachineInstr * MI)45*0fca6ea1SDimitry Andric void XtensaAsmPrinter::emitInstruction(const MachineInstr *MI) {
46*0fca6ea1SDimitry Andric unsigned Opc = MI->getOpcode();
47*0fca6ea1SDimitry Andric
48*0fca6ea1SDimitry Andric switch (Opc) {
49*0fca6ea1SDimitry Andric case Xtensa::BR_JT:
50*0fca6ea1SDimitry Andric EmitToStreamer(
51*0fca6ea1SDimitry Andric *OutStreamer,
52*0fca6ea1SDimitry Andric MCInstBuilder(Xtensa::JX).addReg(MI->getOperand(0).getReg()));
53*0fca6ea1SDimitry Andric return;
54*0fca6ea1SDimitry Andric default:
55*0fca6ea1SDimitry Andric MCInst LoweredMI;
56*0fca6ea1SDimitry Andric lowerToMCInst(MI, LoweredMI);
57*0fca6ea1SDimitry Andric EmitToStreamer(*OutStreamer, LoweredMI);
58*0fca6ea1SDimitry Andric return;
59*0fca6ea1SDimitry Andric }
60*0fca6ea1SDimitry Andric }
61*0fca6ea1SDimitry Andric
emitMachineConstantPoolValue(MachineConstantPoolValue * MCPV)62*0fca6ea1SDimitry Andric void XtensaAsmPrinter::emitMachineConstantPoolValue(
63*0fca6ea1SDimitry Andric MachineConstantPoolValue *MCPV) {
64*0fca6ea1SDimitry Andric XtensaConstantPoolValue *ACPV = static_cast<XtensaConstantPoolValue *>(MCPV);
65*0fca6ea1SDimitry Andric MCSymbol *MCSym;
66*0fca6ea1SDimitry Andric
67*0fca6ea1SDimitry Andric if (ACPV->isBlockAddress()) {
68*0fca6ea1SDimitry Andric const BlockAddress *BA =
69*0fca6ea1SDimitry Andric cast<XtensaConstantPoolConstant>(ACPV)->getBlockAddress();
70*0fca6ea1SDimitry Andric MCSym = GetBlockAddressSymbol(BA);
71*0fca6ea1SDimitry Andric } else if (ACPV->isJumpTable()) {
72*0fca6ea1SDimitry Andric unsigned Idx = cast<XtensaConstantPoolJumpTable>(ACPV)->getIndex();
73*0fca6ea1SDimitry Andric MCSym = this->GetJTISymbol(Idx, false);
74*0fca6ea1SDimitry Andric } else {
75*0fca6ea1SDimitry Andric assert(ACPV->isExtSymbol() && "unrecognized constant pool value");
76*0fca6ea1SDimitry Andric XtensaConstantPoolSymbol *XtensaSym = cast<XtensaConstantPoolSymbol>(ACPV);
77*0fca6ea1SDimitry Andric const char *SymName = XtensaSym->getSymbol();
78*0fca6ea1SDimitry Andric
79*0fca6ea1SDimitry Andric if (XtensaSym->isPrivateLinkage()) {
80*0fca6ea1SDimitry Andric const DataLayout &DL = getDataLayout();
81*0fca6ea1SDimitry Andric MCSym = OutContext.getOrCreateSymbol(Twine(DL.getPrivateGlobalPrefix()) +
82*0fca6ea1SDimitry Andric SymName);
83*0fca6ea1SDimitry Andric } else {
84*0fca6ea1SDimitry Andric MCSym = OutContext.getOrCreateSymbol(SymName);
85*0fca6ea1SDimitry Andric }
86*0fca6ea1SDimitry Andric }
87*0fca6ea1SDimitry Andric
88*0fca6ea1SDimitry Andric MCSymbol *LblSym = GetCPISymbol(ACPV->getLabelId());
89*0fca6ea1SDimitry Andric auto *TS =
90*0fca6ea1SDimitry Andric static_cast<XtensaTargetStreamer *>(OutStreamer->getTargetStreamer());
91*0fca6ea1SDimitry Andric MCSymbolRefExpr::VariantKind VK = getModifierVariantKind(ACPV->getModifier());
92*0fca6ea1SDimitry Andric
93*0fca6ea1SDimitry Andric if (ACPV->getModifier() != XtensaCP::no_modifier) {
94*0fca6ea1SDimitry Andric std::string SymName(MCSym->getName());
95*0fca6ea1SDimitry Andric StringRef Modifier = ACPV->getModifierText();
96*0fca6ea1SDimitry Andric SymName += Modifier;
97*0fca6ea1SDimitry Andric MCSym = OutContext.getOrCreateSymbol(SymName);
98*0fca6ea1SDimitry Andric }
99*0fca6ea1SDimitry Andric
100*0fca6ea1SDimitry Andric const MCExpr *Expr = MCSymbolRefExpr::create(MCSym, VK, OutContext);
101*0fca6ea1SDimitry Andric TS->emitLiteral(LblSym, Expr, false);
102*0fca6ea1SDimitry Andric }
103*0fca6ea1SDimitry Andric
emitMachineConstantPoolEntry(const MachineConstantPoolEntry & CPE,int i)104*0fca6ea1SDimitry Andric void XtensaAsmPrinter::emitMachineConstantPoolEntry(
105*0fca6ea1SDimitry Andric const MachineConstantPoolEntry &CPE, int i) {
106*0fca6ea1SDimitry Andric if (CPE.isMachineConstantPoolEntry()) {
107*0fca6ea1SDimitry Andric XtensaConstantPoolValue *ACPV =
108*0fca6ea1SDimitry Andric static_cast<XtensaConstantPoolValue *>(CPE.Val.MachineCPVal);
109*0fca6ea1SDimitry Andric ACPV->setLabelId(i);
110*0fca6ea1SDimitry Andric emitMachineConstantPoolValue(CPE.Val.MachineCPVal);
111*0fca6ea1SDimitry Andric } else {
112*0fca6ea1SDimitry Andric MCSymbol *LblSym = GetCPISymbol(i);
113*0fca6ea1SDimitry Andric auto *TS =
114*0fca6ea1SDimitry Andric static_cast<XtensaTargetStreamer *>(OutStreamer->getTargetStreamer());
115*0fca6ea1SDimitry Andric const Constant *C = CPE.Val.ConstVal;
116*0fca6ea1SDimitry Andric const MCExpr *Value = nullptr;
117*0fca6ea1SDimitry Andric
118*0fca6ea1SDimitry Andric Type *Ty = C->getType();
119*0fca6ea1SDimitry Andric if (const auto *CFP = dyn_cast<ConstantFP>(C)) {
120*0fca6ea1SDimitry Andric Value = MCConstantExpr::create(
121*0fca6ea1SDimitry Andric CFP->getValueAPF().bitcastToAPInt().getSExtValue(), OutContext);
122*0fca6ea1SDimitry Andric } else if (const auto *CI = dyn_cast<ConstantInt>(C)) {
123*0fca6ea1SDimitry Andric Value = MCConstantExpr::create(CI->getValue().getSExtValue(), OutContext);
124*0fca6ea1SDimitry Andric } else if (isa<PointerType>(Ty)) {
125*0fca6ea1SDimitry Andric Value = lowerConstant(C);
126*0fca6ea1SDimitry Andric } else {
127*0fca6ea1SDimitry Andric llvm_unreachable("unexpected constant pool entry type");
128*0fca6ea1SDimitry Andric }
129*0fca6ea1SDimitry Andric
130*0fca6ea1SDimitry Andric TS->emitLiteral(LblSym, Value, false);
131*0fca6ea1SDimitry Andric }
132*0fca6ea1SDimitry Andric }
133*0fca6ea1SDimitry Andric
134*0fca6ea1SDimitry Andric // EmitConstantPool - Print to the current output stream assembly
135*0fca6ea1SDimitry Andric // representations of the constants in the constant pool MCP. This is
136*0fca6ea1SDimitry Andric // used to print out constants which have been "spilled to memory" by
137*0fca6ea1SDimitry Andric // the code generator.
emitConstantPool()138*0fca6ea1SDimitry Andric void XtensaAsmPrinter::emitConstantPool() {
139*0fca6ea1SDimitry Andric const Function &F = MF->getFunction();
140*0fca6ea1SDimitry Andric const MachineConstantPool *MCP = MF->getConstantPool();
141*0fca6ea1SDimitry Andric const std::vector<MachineConstantPoolEntry> &CP = MCP->getConstants();
142*0fca6ea1SDimitry Andric if (CP.empty())
143*0fca6ea1SDimitry Andric return;
144*0fca6ea1SDimitry Andric
145*0fca6ea1SDimitry Andric OutStreamer->pushSection();
146*0fca6ea1SDimitry Andric
147*0fca6ea1SDimitry Andric auto *TS =
148*0fca6ea1SDimitry Andric static_cast<XtensaTargetStreamer *>(OutStreamer->getTargetStreamer());
149*0fca6ea1SDimitry Andric MCSection *CS = getObjFileLowering().SectionForGlobal(&F, TM);
150*0fca6ea1SDimitry Andric TS->startLiteralSection(CS);
151*0fca6ea1SDimitry Andric
152*0fca6ea1SDimitry Andric int CPIdx = 0;
153*0fca6ea1SDimitry Andric for (const MachineConstantPoolEntry &CPE : CP) {
154*0fca6ea1SDimitry Andric emitMachineConstantPoolEntry(CPE, CPIdx++);
155*0fca6ea1SDimitry Andric }
156*0fca6ea1SDimitry Andric
157*0fca6ea1SDimitry Andric OutStreamer->popSection();
158*0fca6ea1SDimitry Andric }
159*0fca6ea1SDimitry Andric
160*0fca6ea1SDimitry Andric MCSymbol *
GetConstantPoolIndexSymbol(const MachineOperand & MO) const161*0fca6ea1SDimitry Andric XtensaAsmPrinter::GetConstantPoolIndexSymbol(const MachineOperand &MO) const {
162*0fca6ea1SDimitry Andric // Create a symbol for the name.
163*0fca6ea1SDimitry Andric return GetCPISymbol(MO.getIndex());
164*0fca6ea1SDimitry Andric }
165*0fca6ea1SDimitry Andric
GetJumpTableSymbol(const MachineOperand & MO) const166*0fca6ea1SDimitry Andric MCSymbol *XtensaAsmPrinter::GetJumpTableSymbol(const MachineOperand &MO) const {
167*0fca6ea1SDimitry Andric return GetJTISymbol(MO.getIndex());
168*0fca6ea1SDimitry Andric }
169*0fca6ea1SDimitry Andric
170*0fca6ea1SDimitry Andric MCOperand
LowerSymbolOperand(const MachineOperand & MO,MachineOperand::MachineOperandType MOTy,unsigned Offset) const171*0fca6ea1SDimitry Andric XtensaAsmPrinter::LowerSymbolOperand(const MachineOperand &MO,
172*0fca6ea1SDimitry Andric MachineOperand::MachineOperandType MOTy,
173*0fca6ea1SDimitry Andric unsigned Offset) const {
174*0fca6ea1SDimitry Andric const MCSymbol *Symbol;
175*0fca6ea1SDimitry Andric XtensaMCExpr::VariantKind Kind = XtensaMCExpr::VK_Xtensa_None;
176*0fca6ea1SDimitry Andric
177*0fca6ea1SDimitry Andric switch (MOTy) {
178*0fca6ea1SDimitry Andric case MachineOperand::MO_GlobalAddress:
179*0fca6ea1SDimitry Andric Symbol = getSymbol(MO.getGlobal());
180*0fca6ea1SDimitry Andric Offset += MO.getOffset();
181*0fca6ea1SDimitry Andric break;
182*0fca6ea1SDimitry Andric case MachineOperand::MO_MachineBasicBlock:
183*0fca6ea1SDimitry Andric Symbol = MO.getMBB()->getSymbol();
184*0fca6ea1SDimitry Andric break;
185*0fca6ea1SDimitry Andric case MachineOperand::MO_BlockAddress:
186*0fca6ea1SDimitry Andric Symbol = GetBlockAddressSymbol(MO.getBlockAddress());
187*0fca6ea1SDimitry Andric Offset += MO.getOffset();
188*0fca6ea1SDimitry Andric break;
189*0fca6ea1SDimitry Andric case MachineOperand::MO_ExternalSymbol:
190*0fca6ea1SDimitry Andric Symbol = GetExternalSymbolSymbol(MO.getSymbolName());
191*0fca6ea1SDimitry Andric Offset += MO.getOffset();
192*0fca6ea1SDimitry Andric break;
193*0fca6ea1SDimitry Andric case MachineOperand::MO_JumpTableIndex:
194*0fca6ea1SDimitry Andric Symbol = GetJumpTableSymbol(MO);
195*0fca6ea1SDimitry Andric break;
196*0fca6ea1SDimitry Andric case MachineOperand::MO_ConstantPoolIndex:
197*0fca6ea1SDimitry Andric Symbol = GetConstantPoolIndexSymbol(MO);
198*0fca6ea1SDimitry Andric Offset += MO.getOffset();
199*0fca6ea1SDimitry Andric break;
200*0fca6ea1SDimitry Andric default:
201*0fca6ea1SDimitry Andric report_fatal_error("<unknown operand type>");
202*0fca6ea1SDimitry Andric }
203*0fca6ea1SDimitry Andric
204*0fca6ea1SDimitry Andric const MCExpr *ME =
205*0fca6ea1SDimitry Andric MCSymbolRefExpr::create(Symbol, MCSymbolRefExpr::VK_None, OutContext);
206*0fca6ea1SDimitry Andric ME = XtensaMCExpr::create(ME, Kind, OutContext);
207*0fca6ea1SDimitry Andric
208*0fca6ea1SDimitry Andric if (Offset) {
209*0fca6ea1SDimitry Andric // Assume offset is never negative.
210*0fca6ea1SDimitry Andric assert(Offset > 0);
211*0fca6ea1SDimitry Andric
212*0fca6ea1SDimitry Andric const MCConstantExpr *OffsetExpr =
213*0fca6ea1SDimitry Andric MCConstantExpr::create(Offset, OutContext);
214*0fca6ea1SDimitry Andric ME = MCBinaryExpr::createAdd(ME, OffsetExpr, OutContext);
215*0fca6ea1SDimitry Andric }
216*0fca6ea1SDimitry Andric
217*0fca6ea1SDimitry Andric return MCOperand::createExpr(ME);
218*0fca6ea1SDimitry Andric }
219*0fca6ea1SDimitry Andric
lowerOperand(const MachineOperand & MO,unsigned Offset) const220*0fca6ea1SDimitry Andric MCOperand XtensaAsmPrinter::lowerOperand(const MachineOperand &MO,
221*0fca6ea1SDimitry Andric unsigned Offset) const {
222*0fca6ea1SDimitry Andric MachineOperand::MachineOperandType MOTy = MO.getType();
223*0fca6ea1SDimitry Andric
224*0fca6ea1SDimitry Andric switch (MOTy) {
225*0fca6ea1SDimitry Andric case MachineOperand::MO_Register:
226*0fca6ea1SDimitry Andric // Ignore all implicit register operands.
227*0fca6ea1SDimitry Andric if (MO.isImplicit())
228*0fca6ea1SDimitry Andric break;
229*0fca6ea1SDimitry Andric return MCOperand::createReg(MO.getReg());
230*0fca6ea1SDimitry Andric case MachineOperand::MO_Immediate:
231*0fca6ea1SDimitry Andric return MCOperand::createImm(MO.getImm() + Offset);
232*0fca6ea1SDimitry Andric case MachineOperand::MO_RegisterMask:
233*0fca6ea1SDimitry Andric break;
234*0fca6ea1SDimitry Andric case MachineOperand::MO_GlobalAddress:
235*0fca6ea1SDimitry Andric case MachineOperand::MO_MachineBasicBlock:
236*0fca6ea1SDimitry Andric case MachineOperand::MO_BlockAddress:
237*0fca6ea1SDimitry Andric case MachineOperand::MO_ExternalSymbol:
238*0fca6ea1SDimitry Andric case MachineOperand::MO_JumpTableIndex:
239*0fca6ea1SDimitry Andric case MachineOperand::MO_ConstantPoolIndex:
240*0fca6ea1SDimitry Andric return LowerSymbolOperand(MO, MOTy, Offset);
241*0fca6ea1SDimitry Andric default:
242*0fca6ea1SDimitry Andric report_fatal_error("unknown operand type");
243*0fca6ea1SDimitry Andric }
244*0fca6ea1SDimitry Andric
245*0fca6ea1SDimitry Andric return MCOperand();
246*0fca6ea1SDimitry Andric }
247*0fca6ea1SDimitry Andric
lowerToMCInst(const MachineInstr * MI,MCInst & OutMI) const248*0fca6ea1SDimitry Andric void XtensaAsmPrinter::lowerToMCInst(const MachineInstr *MI,
249*0fca6ea1SDimitry Andric MCInst &OutMI) const {
250*0fca6ea1SDimitry Andric OutMI.setOpcode(MI->getOpcode());
251*0fca6ea1SDimitry Andric
252*0fca6ea1SDimitry Andric for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
253*0fca6ea1SDimitry Andric const MachineOperand &MO = MI->getOperand(i);
254*0fca6ea1SDimitry Andric MCOperand MCOp = lowerOperand(MO);
255*0fca6ea1SDimitry Andric
256*0fca6ea1SDimitry Andric if (MCOp.isValid())
257*0fca6ea1SDimitry Andric OutMI.addOperand(MCOp);
258*0fca6ea1SDimitry Andric }
259*0fca6ea1SDimitry Andric }
260*0fca6ea1SDimitry Andric
LLVMInitializeXtensaAsmPrinter()261*0fca6ea1SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXtensaAsmPrinter() {
262*0fca6ea1SDimitry Andric RegisterAsmPrinter<XtensaAsmPrinter> A(getTheXtensaTarget());
263*0fca6ea1SDimitry Andric }
264