LLVM 19.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 "LanaiMCExpr.h"
15#include "LanaiAluCode.h"
16#include "LanaiCondCode.h"
18#include "llvm/MC/MCAsmInfo.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCInst.h"
22#include "llvm/MC/MCSymbol.h"
25
26using namespace llvm;
27
28#define DEBUG_TYPE "asm-printer"
29
30// Include the auto-generated portion of the assembly writer.
31#define PRINT_ALIAS_INSTR
32#include "LanaiGenAsmWriter.inc"
33
36}
37
39 StringRef Alias, unsigned OpNo0,
40 unsigned OpNo1) {
41 OS << "\t" << Alias << " ";
42 printOperand(MI, OpNo0, OS);
43 OS << ", ";
44 printOperand(MI, OpNo1, OS);
45 return true;
46}
47
48static bool usesGivenOffset(const MCInst *MI, int AddOffset) {
49 unsigned AluCode = MI->getOperand(3).getImm();
50 return LPAC::encodeLanaiAluCode(AluCode) == LPAC::ADD &&
51 (MI->getOperand(2).getImm() == AddOffset ||
52 MI->getOperand(2).getImm() == -AddOffset);
53}
54
55static bool isPreIncrementForm(const MCInst *MI, int AddOffset) {
56 unsigned AluCode = MI->getOperand(3).getImm();
57 return LPAC::isPreOp(AluCode) && usesGivenOffset(MI, AddOffset);
58}
59
60static bool isPostIncrementForm(const MCInst *MI, int AddOffset) {
61 unsigned AluCode = MI->getOperand(3).getImm();
62 return LPAC::isPostOp(AluCode) && usesGivenOffset(MI, AddOffset);
63}
64
66 if (MI->getOperand(2).getImm() < 0)
67 return "--";
68 return "++";
69}
70
71bool LanaiInstPrinter::printMemoryLoadIncrement(const MCInst *MI,
73 StringRef Opcode,
74 int AddOffset) {
75 if (isPreIncrementForm(MI, AddOffset)) {
76 OS << "\t" << Opcode << "\t[" << decIncOperator(MI) << "%"
77 << getRegisterName(MI->getOperand(1).getReg()) << "], %"
78 << getRegisterName(MI->getOperand(0).getReg());
79 return true;
80 }
81 if (isPostIncrementForm(MI, AddOffset)) {
82 OS << "\t" << Opcode << "\t[%"
83 << getRegisterName(MI->getOperand(1).getReg()) << decIncOperator(MI)
84 << "], %" << getRegisterName(MI->getOperand(0).getReg());
85 return true;
86 }
87 return false;
88}
89
90bool LanaiInstPrinter::printMemoryStoreIncrement(const MCInst *MI,
92 StringRef Opcode,
93 int AddOffset) {
94 if (isPreIncrementForm(MI, AddOffset)) {
95 OS << "\t" << Opcode << "\t%" << getRegisterName(MI->getOperand(0).getReg())
96 << ", [" << decIncOperator(MI) << "%"
97 << getRegisterName(MI->getOperand(1).getReg()) << "]";
98 return true;
99 }
100 if (isPostIncrementForm(MI, AddOffset)) {
101 OS << "\t" << Opcode << "\t%" << getRegisterName(MI->getOperand(0).getReg())
102 << ", [%" << getRegisterName(MI->getOperand(1).getReg())
103 << decIncOperator(MI) << "]";
104 return true;
105 }
106 return false;
107}
108
109bool LanaiInstPrinter::printAlias(const MCInst *MI, raw_ostream &OS) {
110 switch (MI->getOpcode()) {
111 case Lanai::LDW_RI:
112 // ld 4[*%rN], %rX => ld [++imm], %rX
113 // ld -4[*%rN], %rX => ld [--imm], %rX
114 // ld 4[%rN*], %rX => ld [imm++], %rX
115 // ld -4[%rN*], %rX => ld [imm--], %rX
116 return printMemoryLoadIncrement(MI, OS, "ld", 4);
117 case Lanai::LDHs_RI:
118 return printMemoryLoadIncrement(MI, OS, "ld.h", 2);
119 case Lanai::LDHz_RI:
120 return printMemoryLoadIncrement(MI, OS, "uld.h", 2);
121 case Lanai::LDBs_RI:
122 return printMemoryLoadIncrement(MI, OS, "ld.b", 1);
123 case Lanai::LDBz_RI:
124 return printMemoryLoadIncrement(MI, OS, "uld.b", 1);
125 case Lanai::SW_RI:
126 // st %rX, 4[*%rN] => st %rX, [++imm]
127 // st %rX, -4[*%rN] => st %rX, [--imm]
128 // st %rX, 4[%rN*] => st %rX, [imm++]
129 // st %rX, -4[%rN*] => st %rX, [imm--]
130 return printMemoryStoreIncrement(MI, OS, "st", 4);
131 case Lanai::STH_RI:
132 return printMemoryStoreIncrement(MI, OS, "st.h", 2);
133 case Lanai::STB_RI:
134 return printMemoryStoreIncrement(MI, OS, "st.b", 1);
135 default:
136 return false;
137 }
138}
139
141 StringRef Annotation,
142 const MCSubtargetInfo & /*STI*/,
143 raw_ostream &OS) {
144 if (!printAlias(MI, OS) && !printAliasInstr(MI, Address, OS))
146 printAnnotation(OS, Annotation);
147}
148
149void LanaiInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
150 raw_ostream &OS, const char *Modifier) {
151 assert((Modifier == nullptr || Modifier[0] == 0) && "No modifiers supported");
152 const MCOperand &Op = MI->getOperand(OpNo);
153 if (Op.isReg())
154 OS << "%" << getRegisterName(Op.getReg());
155 else if (Op.isImm())
156 OS << formatHex(Op.getImm());
157 else {
158 assert(Op.isExpr() && "Expected an expression");
159 Op.getExpr()->print(OS, &MAI);
160 }
161}
162
164 raw_ostream &OS) {
165 const MCOperand &Op = MI->getOperand(OpNo);
166 if (Op.isImm()) {
167 OS << '[' << formatHex(Op.getImm()) << ']';
168 } else {
169 // Symbolic operand will be lowered to immediate value by linker
170 assert(Op.isExpr() && "Expected an expression");
171 OS << '[';
172 Op.getExpr()->print(OS, &MAI);
173 OS << ']';
174 }
175}
176
178 raw_ostream &OS) {
179 const MCOperand &Op = MI->getOperand(OpNo);
180 if (Op.isImm()) {
181 OS << formatHex(Op.getImm() << 16);
182 } else {
183 // Symbolic operand will be lowered to immediate value by linker
184 assert(Op.isExpr() && "Expected an expression");
185 Op.getExpr()->print(OS, &MAI);
186 }
187}
188
190 raw_ostream &OS) {
191 const MCOperand &Op = MI->getOperand(OpNo);
192 if (Op.isImm()) {
193 OS << formatHex((Op.getImm() << 16) | 0xffff);
194 } else {
195 // Symbolic operand will be lowered to immediate value by linker
196 assert(Op.isExpr() && "Expected an expression");
197 Op.getExpr()->print(OS, &MAI);
198 }
199}
200
202 raw_ostream &OS) {
203 const MCOperand &Op = MI->getOperand(OpNo);
204 if (Op.isImm()) {
205 OS << formatHex(0xffff0000 | Op.getImm());
206 } else {
207 // Symbolic operand will be lowered to immediate value by linker
208 assert(Op.isExpr() && "Expected an expression");
209 Op.getExpr()->print(OS, &MAI);
210 }
211}
212
213static void printMemoryBaseRegister(raw_ostream &OS, const unsigned AluCode,
214 const MCOperand &RegOp) {
215 assert(RegOp.isReg() && "Register operand expected");
216 OS << "[";
217 if (LPAC::isPreOp(AluCode))
218 OS << "*";
220 if (LPAC::isPostOp(AluCode))
221 OS << "*";
222 OS << "]";
223}
224
225template <unsigned SizeInBits>
227 const MCOperand &OffsetOp,
228 raw_ostream &OS) {
229 assert((OffsetOp.isImm() || OffsetOp.isExpr()) && "Immediate expected");
230 if (OffsetOp.isImm()) {
231 assert(isInt<SizeInBits>(OffsetOp.getImm()) && "Constant value truncated");
232 OS << OffsetOp.getImm();
233 } else
234 OffsetOp.getExpr()->print(OS, &MAI);
235}
236
239 const char * /*Modifier*/) {
240 const MCOperand &RegOp = MI->getOperand(OpNo);
241 const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
242 const MCOperand &AluOp = MI->getOperand(OpNo + 2);
243 const unsigned AluCode = AluOp.getImm();
244
245 // Offset
246 printMemoryImmediateOffset<16>(MAI, OffsetOp, OS);
247
248 // Register
249 printMemoryBaseRegister(OS, AluCode, RegOp);
250}
251
254 const char * /*Modifier*/) {
255 const MCOperand &RegOp = MI->getOperand(OpNo);
256 const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
257 const MCOperand &AluOp = MI->getOperand(OpNo + 2);
258 const unsigned AluCode = AluOp.getImm();
259 assert(OffsetOp.isReg() && RegOp.isReg() && "Registers expected.");
260
261 // [ Base OP Offset ]
262 OS << "[";
263 if (LPAC::isPreOp(AluCode))
264 OS << "*";
265 OS << "%" << getRegisterName(RegOp.getReg());
266 if (LPAC::isPostOp(AluCode))
267 OS << "*";
268 OS << " " << LPAC::lanaiAluCodeToString(AluCode) << " ";
269 OS << "%" << getRegisterName(OffsetOp.getReg());
270 OS << "]";
271}
272
275 const char * /*Modifier*/) {
276 const MCOperand &RegOp = MI->getOperand(OpNo);
277 const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
278 const MCOperand &AluOp = MI->getOperand(OpNo + 2);
279 const unsigned AluCode = AluOp.getImm();
280
281 // Offset
282 printMemoryImmediateOffset<10>(MAI, OffsetOp, OS);
283
284 // Register
285 printMemoryBaseRegister(OS, AluCode, RegOp);
286}
287
289 raw_ostream &OS) {
291 static_cast<LPCC::CondCode>(MI->getOperand(OpNo).getImm());
292 // Handle the undefined value here for printing so we don't abort().
293 if (CC >= LPCC::UNKNOWN)
294 OS << "<und>";
295 else
296 OS << lanaiCondCodeToString(CC);
297}
298
300 raw_ostream &OS) {
302 static_cast<LPCC::CondCode>(MI->getOperand(OpNo).getImm());
303 // Handle the undefined value here for printing so we don't abort().
304 if (CC >= LPCC::UNKNOWN)
305 OS << "<und>";
306 else if (CC != LPCC::ICC_T)
307 OS << "." << lanaiCondCodeToString(CC);
308}
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)
void printRegName(raw_ostream &OS, MCRegister Reg) const override
Print the assembler register name.
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 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:41
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:51
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:36
int64_t getImm() const
Definition: MCInst.h:80
bool isImm() const
Definition: MCInst.h:62
unsigned getReg() const
Returns the register number.
Definition: MCInst.h:69
bool isReg() const
Definition: MCInst.h:61
const MCExpr * getExpr() const
Definition: MCInst.h:114
bool isExpr() const
Definition: MCInst.h:65
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:50
std::string lower() const
Definition: StringRef.cpp:111
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