LLVM 20.0.0git
LanaiInstPrinter.cpp
Go to the documentation of this file.
1//===-- LanaiInstPrinter.cpp - Convert Lanai MCInst to asm syntax ---------===//
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 class prints an Lanai MCInst to a .s file.
10//
11//===----------------------------------------------------------------------===//
12
13#include "LanaiInstPrinter.h"
14#include "LanaiAluCode.h"
15#include "LanaiCondCode.h"
17#include "llvm/MC/MCAsmInfo.h"
18#include "llvm/MC/MCExpr.h"
19#include "llvm/MC/MCInst.h"
20#include "llvm/MC/MCSymbol.h"
22
23using namespace llvm;
24
25#define DEBUG_TYPE "asm-printer"
26
27// Include the auto-generated portion of the assembly writer.
28#define PRINT_ALIAS_INSTR
29#include "LanaiGenAsmWriter.inc"
30
33}
34
36 StringRef Alias, unsigned OpNo0,
37 unsigned OpNo1) {
38 OS << "\t" << Alias << " ";
39 printOperand(MI, OpNo0, OS);
40 OS << ", ";
41 printOperand(MI, OpNo1, OS);
42 return true;
43}
44
45static bool usesGivenOffset(const MCInst *MI, int AddOffset) {
46 unsigned AluCode = MI->getOperand(3).getImm();
47 return LPAC::encodeLanaiAluCode(AluCode) == LPAC::ADD &&
48 (MI->getOperand(2).getImm() == AddOffset ||
49 MI->getOperand(2).getImm() == -AddOffset);
50}
51
52static bool isPreIncrementForm(const MCInst *MI, int AddOffset) {
53 unsigned AluCode = MI->getOperand(3).getImm();
54 return LPAC::isPreOp(AluCode) && usesGivenOffset(MI, AddOffset);
55}
56
57static bool isPostIncrementForm(const MCInst *MI, int AddOffset) {
58 unsigned AluCode = MI->getOperand(3).getImm();
59 return LPAC::isPostOp(AluCode) && usesGivenOffset(MI, AddOffset);
60}
61
63 if (MI->getOperand(2).getImm() < 0)
64 return "--";
65 return "++";
66}
67
68bool LanaiInstPrinter::printMemoryLoadIncrement(const MCInst *MI,
70 StringRef Opcode,
71 int AddOffset) {
72 if (isPreIncrementForm(MI, AddOffset)) {
73 OS << "\t" << Opcode << "\t[" << decIncOperator(MI) << "%"
74 << getRegisterName(MI->getOperand(1).getReg()) << "], %"
75 << getRegisterName(MI->getOperand(0).getReg());
76 return true;
77 }
78 if (isPostIncrementForm(MI, AddOffset)) {
79 OS << "\t" << Opcode << "\t[%"
80 << getRegisterName(MI->getOperand(1).getReg()) << decIncOperator(MI)
81 << "], %" << getRegisterName(MI->getOperand(0).getReg());
82 return true;
83 }
84 return false;
85}
86
87bool LanaiInstPrinter::printMemoryStoreIncrement(const MCInst *MI,
89 StringRef Opcode,
90 int AddOffset) {
91 if (isPreIncrementForm(MI, AddOffset)) {
92 OS << "\t" << Opcode << "\t%" << getRegisterName(MI->getOperand(0).getReg())
93 << ", [" << decIncOperator(MI) << "%"
94 << getRegisterName(MI->getOperand(1).getReg()) << "]";
95 return true;
96 }
97 if (isPostIncrementForm(MI, AddOffset)) {
98 OS << "\t" << Opcode << "\t%" << getRegisterName(MI->getOperand(0).getReg())
99 << ", [%" << getRegisterName(MI->getOperand(1).getReg())
100 << decIncOperator(MI) << "]";
101 return true;
102 }
103 return false;
104}
105
106bool LanaiInstPrinter::printAlias(const MCInst *MI, raw_ostream &OS) {
107 switch (MI->getOpcode()) {
108 case Lanai::LDW_RI:
109 // ld 4[*%rN], %rX => ld [++imm], %rX
110 // ld -4[*%rN], %rX => ld [--imm], %rX
111 // ld 4[%rN*], %rX => ld [imm++], %rX
112 // ld -4[%rN*], %rX => ld [imm--], %rX
113 return printMemoryLoadIncrement(MI, OS, "ld", 4);
114 case Lanai::LDHs_RI:
115 return printMemoryLoadIncrement(MI, OS, "ld.h", 2);
116 case Lanai::LDHz_RI:
117 return printMemoryLoadIncrement(MI, OS, "uld.h", 2);
118 case Lanai::LDBs_RI:
119 return printMemoryLoadIncrement(MI, OS, "ld.b", 1);
120 case Lanai::LDBz_RI:
121 return printMemoryLoadIncrement(MI, OS, "uld.b", 1);
122 case Lanai::SW_RI:
123 // st %rX, 4[*%rN] => st %rX, [++imm]
124 // st %rX, -4[*%rN] => st %rX, [--imm]
125 // st %rX, 4[%rN*] => st %rX, [imm++]
126 // st %rX, -4[%rN*] => st %rX, [imm--]
127 return printMemoryStoreIncrement(MI, OS, "st", 4);
128 case Lanai::STH_RI:
129 return printMemoryStoreIncrement(MI, OS, "st.h", 2);
130 case Lanai::STB_RI:
131 return printMemoryStoreIncrement(MI, OS, "st.b", 1);
132 default:
133 return false;
134 }
135}
136
138 StringRef Annotation,
139 const MCSubtargetInfo & /*STI*/,
140 raw_ostream &OS) {
141 if (!printAlias(MI, OS) && !printAliasInstr(MI, Address, OS))
143 printAnnotation(OS, Annotation);
144}
145
146void LanaiInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
147 raw_ostream &OS, const char *Modifier) {
148 assert((Modifier == nullptr || Modifier[0] == 0) && "No modifiers supported");
149 const MCOperand &Op = MI->getOperand(OpNo);
150 if (Op.isReg())
151 OS << "%" << getRegisterName(Op.getReg());
152 else if (Op.isImm())
153 OS << formatHex(Op.getImm());
154 else {
155 assert(Op.isExpr() && "Expected an expression");
156 Op.getExpr()->print(OS, &MAI);
157 }
158}
159
161 raw_ostream &OS) {
162 const MCOperand &Op = MI->getOperand(OpNo);
163 if (Op.isImm()) {
164 OS << '[' << formatHex(Op.getImm()) << ']';
165 } else {
166 // Symbolic operand will be lowered to immediate value by linker
167 assert(Op.isExpr() && "Expected an expression");
168 OS << '[';
169 Op.getExpr()->print(OS, &MAI);
170 OS << ']';
171 }
172}
173
175 raw_ostream &OS) {
176 const MCOperand &Op = MI->getOperand(OpNo);
177 if (Op.isImm()) {
178 OS << formatHex(Op.getImm() << 16);
179 } else {
180 // Symbolic operand will be lowered to immediate value by linker
181 assert(Op.isExpr() && "Expected an expression");
182 Op.getExpr()->print(OS, &MAI);
183 }
184}
185
187 raw_ostream &OS) {
188 const MCOperand &Op = MI->getOperand(OpNo);
189 if (Op.isImm()) {
190 OS << formatHex((Op.getImm() << 16) | 0xffff);
191 } else {
192 // Symbolic operand will be lowered to immediate value by linker
193 assert(Op.isExpr() && "Expected an expression");
194 Op.getExpr()->print(OS, &MAI);
195 }
196}
197
199 raw_ostream &OS) {
200 const MCOperand &Op = MI->getOperand(OpNo);
201 if (Op.isImm()) {
202 OS << formatHex(0xffff0000 | Op.getImm());
203 } else {
204 // Symbolic operand will be lowered to immediate value by linker
205 assert(Op.isExpr() && "Expected an expression");
206 Op.getExpr()->print(OS, &MAI);
207 }
208}
209
210static void printMemoryBaseRegister(raw_ostream &OS, const unsigned AluCode,
211 const MCOperand &RegOp) {
212 assert(RegOp.isReg() && "Register operand expected");
213 OS << "[";
214 if (LPAC::isPreOp(AluCode))
215 OS << "*";
217 if (LPAC::isPostOp(AluCode))
218 OS << "*";
219 OS << "]";
220}
221
222template <unsigned SizeInBits>
224 const MCOperand &OffsetOp,
225 raw_ostream &OS) {
226 assert((OffsetOp.isImm() || OffsetOp.isExpr()) && "Immediate expected");
227 if (OffsetOp.isImm()) {
228 assert(isInt<SizeInBits>(OffsetOp.getImm()) && "Constant value truncated");
229 OS << OffsetOp.getImm();
230 } else
231 OffsetOp.getExpr()->print(OS, &MAI);
232}
233
236 const char * /*Modifier*/) {
237 const MCOperand &RegOp = MI->getOperand(OpNo);
238 const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
239 const MCOperand &AluOp = MI->getOperand(OpNo + 2);
240 const unsigned AluCode = AluOp.getImm();
241
242 // Offset
243 printMemoryImmediateOffset<16>(MAI, OffsetOp, OS);
244
245 // Register
246 printMemoryBaseRegister(OS, AluCode, RegOp);
247}
248
251 const char * /*Modifier*/) {
252 const MCOperand &RegOp = MI->getOperand(OpNo);
253 const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
254 const MCOperand &AluOp = MI->getOperand(OpNo + 2);
255 const unsigned AluCode = AluOp.getImm();
256 assert(OffsetOp.isReg() && RegOp.isReg() && "Registers expected.");
257
258 // [ Base OP Offset ]
259 OS << "[";
260 if (LPAC::isPreOp(AluCode))
261 OS << "*";
262 OS << "%" << getRegisterName(RegOp.getReg());
263 if (LPAC::isPostOp(AluCode))
264 OS << "*";
265 OS << " " << LPAC::lanaiAluCodeToString(AluCode) << " ";
266 OS << "%" << getRegisterName(OffsetOp.getReg());
267 OS << "]";
268}
269
272 const char * /*Modifier*/) {
273 const MCOperand &RegOp = MI->getOperand(OpNo);
274 const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
275 const MCOperand &AluOp = MI->getOperand(OpNo + 2);
276 const unsigned AluCode = AluOp.getImm();
277
278 // Offset
279 printMemoryImmediateOffset<10>(MAI, OffsetOp, OS);
280
281 // Register
282 printMemoryBaseRegister(OS, AluCode, RegOp);
283}
284
286 raw_ostream &OS) {
288 static_cast<LPCC::CondCode>(MI->getOperand(OpNo).getImm());
289 // Handle the undefined value here for printing so we don't abort().
290 if (CC >= LPCC::UNKNOWN)
291 OS << "<und>";
292 else
293 OS << lanaiCondCodeToString(CC);
294}
295
297 raw_ostream &OS) {
299 static_cast<LPCC::CondCode>(MI->getOperand(OpNo).getImm());
300 // Handle the undefined value here for printing so we don't abort().
301 if (CC >= LPCC::UNKNOWN)
302 OS << "<und>";
303 else if (CC != LPCC::ICC_T)
304 OS << "." << lanaiCondCodeToString(CC);
305}
IRTranslator LLVM IR MI
static bool isPostIncrementForm(const MCInst *MI, int AddOffset)
static StringRef decIncOperator(const MCInst *MI)
static void printMemoryBaseRegister(raw_ostream &OS, const unsigned AluCode, const MCOperand &RegOp)
static bool usesGivenOffset(const MCInst *MI, int AddOffset)
static void printMemoryImmediateOffset(const MCAsmInfo &MAI, const MCOperand &OffsetOp, raw_ostream &OS)
static bool isPreIncrementForm(const MCInst *MI, int AddOffset)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
raw_pwrite_stream & OS
This class represents an Operation in the Expression.
bool print(raw_ostream &OS, DIDumpOptions DumpOpts, const DWARFExpression *Expr, DWARFUnit *U) const
void printMemRrOperand(const MCInst *MI, int OpNo, raw_ostream &O, const char *Modifier=nullptr)
static const char * getRegisterName(MCRegister Reg)
bool printAliasInstr(const MCInst *MI, uint64_t Address, raw_ostream &OS)
void printMemImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O)
void printMemRiOperand(const MCInst *MI, int OpNo, raw_ostream &O, const char *Modifier=nullptr)
void printRegName(raw_ostream &OS, MCRegister Reg) override
Print the assembler register name.
void printHi16AndImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O)
void printMemSplsOperand(const MCInst *MI, int OpNo, raw_ostream &O, const char *Modifier=nullptr)
void printInst(const MCInst *MI, uint64_t Address, StringRef Annot, const MCSubtargetInfo &STI, raw_ostream &O) override
Print the specified MCInst to the specified raw_ostream.
void printCCOperand(const MCInst *MI, int OpNo, raw_ostream &O)
void printLo16AndImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O)
void printHi16ImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O)
void printInstruction(const MCInst *MI, uint64_t Address, raw_ostream &O)
void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O, const char *Modifier=nullptr)
void printPredicateOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O)
This class is intended to be used as a base class for asm properties and features specific to the tar...
Definition: MCAsmInfo.h:56
void print(raw_ostream &OS, const MCAsmInfo *MAI, bool InParens=false) const
Definition: MCExpr.cpp:40
format_object< int64_t > formatHex(int64_t Value) const
void printAnnotation(raw_ostream &OS, StringRef Annot)
Utility function for printing annotations.
const MCAsmInfo & MAI
Definition: MCInstPrinter.h:52
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:185
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:37
int64_t getImm() const
Definition: MCInst.h:81
bool isImm() const
Definition: MCInst.h:63
bool isReg() const
Definition: MCInst.h:62
MCRegister getReg() const
Returns the register number.
Definition: MCInst.h:70
const MCExpr * getExpr() const
Definition: MCInst.h:115
bool isExpr() const
Definition: MCInst.h:66
Wrapper class representing physical registers. Should be passed by value.
Definition: MCRegister.h:33
Generic base class for all target subtargets.
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
std::string lower() const
Definition: StringRef.cpp:113
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
static bool isPreOp(unsigned AluOp)
Definition: LanaiAluCode.h:57
static const char * lanaiAluCodeToString(unsigned AluOp)
Definition: LanaiAluCode.h:75
static unsigned encodeLanaiAluCode(unsigned AluOp)
Definition: LanaiAluCode.h:47
static bool isPostOp(unsigned AluOp)
Definition: LanaiAluCode.h:59
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18