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/MCSectionELF.h"
26#include "llvm/MC/MCStreamer.h"
27#include "llvm/MC/MCSymbol.h"
28#include "llvm/MC/MCSymbolELF.h"
29#include "llvm/MC/TargetRegistry.h"
30
31using namespace llvm;
32
33static MCSymbolRefExpr::VariantKind
34getModifierVariantKind(XtensaCP::XtensaCPModifier Modifier) {
35 switch (Modifier) {
36 case XtensaCP::no_modifier:
37 return MCSymbolRefExpr::VK_None;
38 case XtensaCP::TPOFF:
39 return MCSymbolRefExpr::VK_TPOFF;
40 }
41 report_fatal_error(reason: "Invalid XtensaCPModifier!");
42}
43
44void XtensaAsmPrinter::emitInstruction(const MachineInstr *MI) {
45 MCInst LoweredMI;
46 lowerToMCInst(MI, OutMI&: LoweredMI);
47 EmitToStreamer(S&: *OutStreamer, Inst: LoweredMI);
48}
49
50void XtensaAsmPrinter::emitMachineConstantPoolValue(
51 MachineConstantPoolValue *MCPV) {
52 XtensaConstantPoolValue *ACPV = static_cast<XtensaConstantPoolValue *>(MCPV);
53 MCSymbol *MCSym;
54
55 assert(ACPV->isExtSymbol() && "unrecognized constant pool value");
56
57 XtensaConstantPoolSymbol *XtensaSym = cast<XtensaConstantPoolSymbol>(Val: ACPV);
58 const char *Sym = XtensaSym->getSymbol();
59 std::string SymName(Sym);
60
61 if (XtensaSym->isPrivateLinkage())
62 SymName = ".L" + SymName;
63
64 MCSym = GetExternalSymbolSymbol(Sym: StringRef(SymName));
65 MCSymbol *LblSym = GetCPISymbol(CPID: ACPV->getLabelId());
66 auto *TS =
67 static_cast<XtensaTargetStreamer *>(OutStreamer->getTargetStreamer());
68 MCSymbolRefExpr::VariantKind VK = getModifierVariantKind(Modifier: ACPV->getModifier());
69
70 if (ACPV->getModifier() != XtensaCP::no_modifier) {
71 std::string SymName(MCSym->getName());
72 StringRef Modifier = ACPV->getModifierText();
73 SymName += Modifier;
74 MCSym = GetExternalSymbolSymbol(Sym: StringRef(SymName));
75 }
76
77 const MCExpr *Expr = MCSymbolRefExpr::create(Symbol: MCSym, Kind: VK, Ctx&: OutContext);
78 TS->emitLiteral(LblSym, Value: Expr, SwitchLiteralSection: false);
79}
80
81void XtensaAsmPrinter::emitMachineConstantPoolEntry(
82 const MachineConstantPoolEntry &CPE, int i) {
83 if (CPE.isMachineConstantPoolEntry()) {
84 XtensaConstantPoolValue *ACPV =
85 static_cast<XtensaConstantPoolValue *>(CPE.Val.MachineCPVal);
86 ACPV->setLabelId(i);
87 emitMachineConstantPoolValue(MCPV: CPE.Val.MachineCPVal);
88 } else {
89 MCSymbol *LblSym = GetCPISymbol(CPID: i);
90 auto *TS =
91 static_cast<XtensaTargetStreamer *>(OutStreamer->getTargetStreamer());
92 const Constant *C = CPE.Val.ConstVal;
93 const MCExpr *Value = nullptr;
94
95 Type *Ty = C->getType();
96 if (const auto *CFP = dyn_cast<ConstantFP>(Val: C)) {
97 Value = MCConstantExpr::create(
98 Value: CFP->getValueAPF().bitcastToAPInt().getSExtValue(), Ctx&: OutContext);
99 } else if (const auto *CI = dyn_cast<ConstantInt>(Val: C)) {
100 Value = MCConstantExpr::create(Value: CI->getValue().getSExtValue(), Ctx&: OutContext);
101 } else if (isa<PointerType>(Val: Ty)) {
102 Value = lowerConstant(CV: C);
103 } else {
104 llvm_unreachable("unexpected constant pool entry type");
105 }
106
107 TS->emitLiteral(LblSym, Value, SwitchLiteralSection: false);
108 }
109}
110
111// EmitConstantPool - Print to the current output stream assembly
112// representations of the constants in the constant pool MCP. This is
113// used to print out constants which have been "spilled to memory" by
114// the code generator.
115void XtensaAsmPrinter::emitConstantPool() {
116 const Function &F = MF->getFunction();
117 const MachineConstantPool *MCP = MF->getConstantPool();
118 const std::vector<MachineConstantPoolEntry> &CP = MCP->getConstants();
119 if (CP.empty())
120 return;
121
122 OutStreamer->pushSection();
123
124 auto *TS =
125 static_cast<XtensaTargetStreamer *>(OutStreamer->getTargetStreamer());
126 MCSection *CS = getObjFileLowering().SectionForGlobal(GO: &F, TM);
127 TS->startLiteralSection(BaseSection: CS);
128
129 int CPIdx = 0;
130 for (const MachineConstantPoolEntry &CPE : CP) {
131 emitMachineConstantPoolEntry(CPE, i: CPIdx++);
132 }
133
134 OutStreamer->popSection();
135}
136
137MCSymbol *
138XtensaAsmPrinter::GetConstantPoolIndexSymbol(const MachineOperand &MO) const {
139 // Create a symbol for the name.
140 return GetCPISymbol(CPID: MO.getIndex());
141}
142
143MCOperand
144XtensaAsmPrinter::LowerSymbolOperand(const MachineOperand &MO,
145 MachineOperand::MachineOperandType MOTy,
146 unsigned Offset) const {
147 const MCSymbol *Symbol;
148 XtensaMCExpr::VariantKind Kind = XtensaMCExpr::VK_Xtensa_None;
149
150 switch (MOTy) {
151 case MachineOperand::MO_GlobalAddress:
152 Symbol = getSymbol(GV: MO.getGlobal());
153 Offset += MO.getOffset();
154 break;
155 case MachineOperand::MO_ConstantPoolIndex:
156 Symbol = GetConstantPoolIndexSymbol(MO);
157 Offset += MO.getOffset();
158 break;
159 default:
160 report_fatal_error(reason: "<unknown operand type>");
161 }
162
163 const MCExpr *ME =
164 MCSymbolRefExpr::create(Symbol, Kind: MCSymbolRefExpr::VK_None, Ctx&: OutContext);
165 ME = XtensaMCExpr::create(Expr: ME, Kind, Ctx&: OutContext);
166
167 if (Offset) {
168 // Assume offset is never negative.
169 assert(Offset > 0);
170
171 const MCConstantExpr *OffsetExpr =
172 MCConstantExpr::create(Value: Offset, Ctx&: OutContext);
173 ME = MCBinaryExpr::createAdd(LHS: ME, RHS: OffsetExpr, Ctx&: OutContext);
174 }
175
176 return MCOperand::createExpr(Val: ME);
177}
178
179MCOperand XtensaAsmPrinter::lowerOperand(const MachineOperand &MO,
180 unsigned Offset) const {
181 MachineOperand::MachineOperandType MOTy = MO.getType();
182
183 switch (MOTy) {
184 case MachineOperand::MO_Register:
185 // Ignore all implicit register operands.
186 if (MO.isImplicit())
187 break;
188 return MCOperand::createReg(Reg: MO.getReg());
189 case MachineOperand::MO_Immediate:
190 return MCOperand::createImm(Val: MO.getImm() + Offset);
191 case MachineOperand::MO_RegisterMask:
192 break;
193 case MachineOperand::MO_GlobalAddress:
194 case MachineOperand::MO_ConstantPoolIndex:
195 return LowerSymbolOperand(MO, MOTy, Offset);
196 default:
197 report_fatal_error(reason: "unknown operand type");
198 }
199
200 return MCOperand();
201}
202
203void XtensaAsmPrinter::lowerToMCInst(const MachineInstr *MI,
204 MCInst &OutMI) const {
205 OutMI.setOpcode(MI->getOpcode());
206
207 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
208 const MachineOperand &MO = MI->getOperand(i);
209 MCOperand MCOp = lowerOperand(MO);
210
211 if (MCOp.isValid())
212 OutMI.addOperand(Op: MCOp);
213 }
214}
215
216extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXtensaAsmPrinter() {
217 RegisterAsmPrinter<XtensaAsmPrinter> A(getTheXtensaTarget());
218}
219

source code of llvm/lib/Target/Xtensa/XtensaAsmPrinter.cpp