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 | |
31 | using namespace llvm; |
32 | |
33 | static MCSymbolRefExpr::VariantKind |
34 | getModifierVariantKind(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 | |
44 | void XtensaAsmPrinter::emitInstruction(const MachineInstr *MI) { |
45 | MCInst LoweredMI; |
46 | lowerToMCInst(MI, OutMI&: LoweredMI); |
47 | EmitToStreamer(S&: *OutStreamer, Inst: LoweredMI); |
48 | } |
49 | |
50 | void 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 | |
81 | void 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. |
115 | void 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 | |
137 | MCSymbol * |
138 | XtensaAsmPrinter::GetConstantPoolIndexSymbol(const MachineOperand &MO) const { |
139 | // Create a symbol for the name. |
140 | return GetCPISymbol(CPID: MO.getIndex()); |
141 | } |
142 | |
143 | MCOperand |
144 | XtensaAsmPrinter::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 | |
179 | MCOperand 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 | |
203 | void 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 | |
216 | extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXtensaAsmPrinter() { |
217 | RegisterAsmPrinter<XtensaAsmPrinter> A(getTheXtensaTarget()); |
218 | } |
219 | |