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