AMDGPU: Mark test as XFAIL in expensive_checks builds
[llvm-project.git] / llvm / lib / Target / Xtensa / XtensaAsmPrinter.cpp
blob95dfafc13f3908339878d2b5831c30e2d5e8a910
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.
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"
33 using namespace llvm;
35 static MCSymbolRefExpr::VariantKind
36 getModifierVariantKind(XtensaCP::XtensaCPModifier Modifier) {
37 switch (Modifier) {
38 case XtensaCP::no_modifier:
39 return MCSymbolRefExpr::VK_None;
40 case XtensaCP::TPOFF:
41 return MCSymbolRefExpr::VK_TPOFF;
43 report_fatal_error("Invalid XtensaCPModifier!");
46 void XtensaAsmPrinter::emitInstruction(const MachineInstr *MI) {
47 unsigned Opc = MI->getOpcode();
49 switch (Opc) {
50 case Xtensa::BR_JT:
51 EmitToStreamer(
52 *OutStreamer,
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;
63 void XtensaAsmPrinter::emitMachineConstantPoolValue(
64 MachineConstantPoolValue *MCPV) {
65 XtensaConstantPoolValue *ACPV = static_cast<XtensaConstantPoolValue *>(MCPV);
66 MCSymbol *MCSym;
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);
78 } else {
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()) +
86 SymName);
87 } else {
88 MCSym = OutContext.getOrCreateSymbol(SymName);
92 MCSymbol *LblSym = GetCPISymbol(ACPV->getLabelId());
93 auto *TS =
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();
100 SymName += Modifier;
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);
113 ACPV->setLabelId(i);
114 emitMachineConstantPoolValue(CPE.Val.MachineCPVal);
115 } else {
116 MCSymbol *LblSym = GetCPISymbol(i);
117 auto *TS =
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);
130 } else {
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();
146 if (CP.empty())
147 return;
149 OutStreamer->pushSection();
151 auto *TS =
152 static_cast<XtensaTargetStreamer *>(OutStreamer->getTargetStreamer());
153 MCSection *CS = getObjFileLowering().SectionForGlobal(&F, TM);
154 TS->startLiteralSection(CS);
156 int CPIdx = 0;
157 for (const MachineConstantPoolEntry &CPE : CP) {
158 emitMachineConstantPoolEntry(CPE, CPIdx++);
161 OutStreamer->popSection();
164 void XtensaAsmPrinter::printOperand(const MachineInstr *MI, int OpNo,
165 raw_ostream &O) {
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);
173 break;
175 default:
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);
185 return false;
188 // Fallback to the default implementation.
189 return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);
192 bool XtensaAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
193 unsigned OpNo,
194 const char *ExtraCode,
195 raw_ostream &OS) {
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());
209 OS << ", ";
210 OS << Offset.getImm();
212 return false;
215 MCSymbol *
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());
225 MCOperand
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;
232 switch (MOTy) {
233 case MachineOperand::MO_GlobalAddress:
234 Symbol = getSymbol(MO.getGlobal());
235 Offset += MO.getOffset();
236 break;
237 case MachineOperand::MO_MachineBasicBlock:
238 Symbol = MO.getMBB()->getSymbol();
239 break;
240 case MachineOperand::MO_BlockAddress:
241 Symbol = GetBlockAddressSymbol(MO.getBlockAddress());
242 Offset += MO.getOffset();
243 break;
244 case MachineOperand::MO_ExternalSymbol:
245 Symbol = GetExternalSymbolSymbol(MO.getSymbolName());
246 Offset += MO.getOffset();
247 break;
248 case MachineOperand::MO_JumpTableIndex:
249 Symbol = GetJumpTableSymbol(MO);
250 break;
251 case MachineOperand::MO_ConstantPoolIndex:
252 Symbol = GetConstantPoolIndexSymbol(MO);
253 Offset += MO.getOffset();
254 break;
255 default:
256 report_fatal_error("<unknown operand type>");
259 const MCExpr *ME =
260 MCSymbolRefExpr::create(Symbol, MCSymbolRefExpr::VK_None, OutContext);
261 ME = XtensaMCExpr::create(ME, Kind, OutContext);
263 if (Offset) {
264 // Assume offset is never negative.
265 assert(Offset > 0);
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();
279 switch (MOTy) {
280 case MachineOperand::MO_Register:
281 // Ignore all implicit register operands.
282 if (MO.isImplicit())
283 break;
284 return MCOperand::createReg(MO.getReg());
285 case MachineOperand::MO_Immediate:
286 return MCOperand::createImm(MO.getImm() + Offset);
287 case MachineOperand::MO_RegisterMask:
288 break;
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);
296 default:
297 report_fatal_error("unknown operand type");
300 return MCOperand();
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);
311 if (MCOp.isValid())
312 OutMI.addOperand(MCOp);
316 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXtensaAsmPrinter() {
317 RegisterAsmPrinter<XtensaAsmPrinter> A(getTheXtensaTarget());