LLVM  12.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"
21 #include "llvm/MC/MCRegisterInfo.h"
22 #include "llvm/MC/MCSymbol.h"
25 
26 using 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 
34 void LanaiInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
35  OS << StringRef(getRegisterName(RegNo)).lower();
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 
48 static 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 
55 static bool isPreIncrementForm(const MCInst *MI, int AddOffset) {
56  unsigned AluCode = MI->getOperand(3).getImm();
57  return LPAC::isPreOp(AluCode) && usesGivenOffset(MI, AddOffset);
58 }
59 
60 static bool isPostIncrementForm(const MCInst *MI, int AddOffset) {
61  unsigned AluCode = MI->getOperand(3).getImm();
62  return LPAC::isPostOp(AluCode) && usesGivenOffset(MI, AddOffset);
63 }
64 
65 static StringRef decIncOperator(const MCInst *MI) {
66  if (MI->getOperand(2).getImm() < 0)
67  return "--";
68  return "++";
69 }
70 
71 bool LanaiInstPrinter::printMemoryLoadIncrement(const MCInst *MI,
72  raw_ostream &OS,
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[%"
84  << "], %" << getRegisterName(MI->getOperand(0).getReg());
85  return true;
86  }
87  return false;
88 }
89 
90 bool LanaiInstPrinter::printMemoryStoreIncrement(const MCInst *MI,
91  raw_ostream &OS,
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 
109 bool 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 
140 void LanaiInstPrinter::printInst(const MCInst *MI, uint64_t Address,
141  StringRef Annotation,
142  const MCSubtargetInfo & /*STI*/,
143  raw_ostream &OS) {
144  if (!printAlias(MI, OS) && !printAliasInstr(MI, Address, OS))
145  printInstruction(MI, Address, OS);
146  printAnnotation(OS, Annotation);
147 }
148 
149 void LanaiInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
150  raw_ostream &OS, const char *Modifier) {
151  assert((Modifier == 0 || 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 
163 void LanaiInstPrinter::printMemImmOperand(const MCInst *MI, unsigned OpNo,
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 
177 void LanaiInstPrinter::printHi16ImmOperand(const MCInst *MI, unsigned OpNo,
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 
189 void LanaiInstPrinter::printHi16AndImmOperand(const MCInst *MI, unsigned OpNo,
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 
201 void LanaiInstPrinter::printLo16AndImmOperand(const MCInst *MI, unsigned OpNo,
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 
213 static 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 << "*";
219  OS << "%" << LanaiInstPrinter::getRegisterName(RegOp.getReg());
220  if (LPAC::isPostOp(AluCode))
221  OS << "*";
222  OS << "]";
223 }
224 
225 template <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 
238  raw_ostream &OS,
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 
253  raw_ostream &OS,
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 
274  raw_ostream &OS,
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 
288 void LanaiInstPrinter::printCCOperand(const MCInst *MI, int OpNo,
289  raw_ostream &OS) {
290  LPCC::CondCode CC =
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 
299 void LanaiInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNo,
300  raw_ostream &OS) {
301  LPCC::CondCode CC =
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 }
void printMemSplsOperand(const MCInst *MI, int OpNo, raw_ostream &O, const char *Modifier=nullptr)
bool isImm() const
Definition: MCInst.h:58
void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O, const char *Modifier=nullptr)
static void printMemoryImmediateOffset(const MCAsmInfo &MAI, const MCOperand &OffsetOp, raw_ostream &OS)
This class represents lattice values for constants.
Definition: AllocatorList.h:23
static StringRef lanaiCondCodeToString(LPCC::CondCode CC)
Definition: LanaiCondCode.h:34
static StringRef decIncOperator(const MCInst *MI)
static const char * lanaiAluCodeToString(unsigned AluOp)
Definition: LanaiAluCode.h:76
bool isReg() const
Definition: MCInst.h:57
void printCCOperand(const MCInst *MI, int OpNo, raw_ostream &O)
void printLo16AndImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O)
unsigned getReg() const
Returns the register number.
Definition: MCInst.h:64
static bool usesGivenOffset(const MCInst *MI, int AddOffset)
bool printAliasInstr(const MCInst *MI, uint64_t Address, raw_ostream &OS)
const MCExpr * getExpr() const
Definition: MCInst.h:95
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:158
void printHi16ImmOperand(const MCInst *MI, unsigned OpNo, 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
static bool isPreOp(unsigned AluOp)
Definition: LanaiAluCode.h:58
int64_t getImm() const
Definition: MCInst.h:75
void print(raw_ostream &OS, const MCAsmInfo *MAI, bool InParens=false) const
Definition: MCExpr.cpp:42
bool isExpr() const
Definition: MCInst.h:60
void printMemRiOperand(const MCInst *MI, int OpNo, raw_ostream &O, const char *Modifier=nullptr)
void printMemRrOperand(const MCInst *MI, int OpNo, raw_ostream &O, const char *Modifier=nullptr)
void printMemImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O)
static void printMemoryBaseRegister(raw_ostream &OS, const unsigned AluCode, const MCOperand &RegOp)
static const char * getRegisterName(unsigned RegNo)
const MCOperand & getOperand(unsigned i) const
Definition: MCInst.h:180
static bool isPreIncrementForm(const MCInst *MI, int AddOffset)
static bool isPostOp(unsigned AluOp)
Definition: LanaiAluCode.h:60
const MCAsmInfo & MAI
Definition: MCInstPrinter.h:48
void printPredicateOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O)
format_object< int64_t > formatHex(int64_t Value) const
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.
Generic base class for all target subtargets.
static unsigned encodeLanaiAluCode(unsigned AluOp)
Definition: LanaiAluCode.h:48
LLVM_NODISCARD std::string lower() const
Definition: StringRef.cpp:108
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
void printAnnotation(raw_ostream &OS, StringRef Annot)
Utility function for printing annotations.
static bool isPostIncrementForm(const MCInst *MI, int AddOffset)
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:46
IRTranslator LLVM IR MI
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
unsigned getOpcode() const
Definition: MCInst.h:172
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:34
void printInstruction(const MCInst *MI, uint64_t Address, raw_ostream &O)
void printRegName(raw_ostream &OS, unsigned RegNo) const override
Print the assembler register name.
void printHi16AndImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O)