xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Xtensa/XtensaAsmPrinter.cpp (revision 5036d9652a5701d00e9e40ea942c278e9f77d33d)
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
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 
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 
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 
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.
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 *
161 XtensaAsmPrinter::GetConstantPoolIndexSymbol(const MachineOperand &MO) const {
162   // Create a symbol for the name.
163   return GetCPISymbol(MO.getIndex());
164 }
165 
166 MCSymbol *XtensaAsmPrinter::GetJumpTableSymbol(const MachineOperand &MO) const {
167   return GetJTISymbol(MO.getIndex());
168 }
169 
170 MCOperand
171 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 
220 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 
248 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 
261 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXtensaAsmPrinter() {
262   RegisterAsmPrinter<XtensaAsmPrinter> A(getTheXtensaTarget());
263 }
264