LLVM  9.0.0svn
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 "Lanai.h"
16 #include "llvm/MC/MCAsmInfo.h"
17 #include "llvm/MC/MCExpr.h"
18 #include "llvm/MC/MCInst.h"
19 #include "llvm/MC/MCSymbol.h"
22 
23 using 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 
31 void LanaiInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
32  OS << StringRef(getRegisterName(RegNo)).lower();
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 
45 static 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 
52 static bool isPreIncrementForm(const MCInst *MI, int AddOffset) {
53  unsigned AluCode = MI->getOperand(3).getImm();
54  return LPAC::isPreOp(AluCode) && usesGivenOffset(MI, AddOffset);
55 }
56 
57 static bool isPostIncrementForm(const MCInst *MI, int AddOffset) {
58  unsigned AluCode = MI->getOperand(3).getImm();
59  return LPAC::isPostOp(AluCode) && usesGivenOffset(MI, AddOffset);
60 }
61 
62 static StringRef decIncOperator(const MCInst *MI) {
63  if (MI->getOperand(2).getImm() < 0)
64  return "--";
65  return "++";
66 }
67 
68 bool LanaiInstPrinter::printMemoryLoadIncrement(const MCInst *MI,
69  raw_ostream &OS,
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[%"
81  << "], %" << getRegisterName(MI->getOperand(0).getReg());
82  return true;
83  }
84  return false;
85 }
86 
87 bool LanaiInstPrinter::printMemoryStoreIncrement(const MCInst *MI,
88  raw_ostream &OS,
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 
106 bool 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  if (!printAlias(MI, OS) && !printAliasInstr(MI, OS))
141  printInstruction(MI, OS);
142  printAnnotation(OS, Annotation);
143 }
144 
145 void LanaiInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
146  raw_ostream &OS, const char *Modifier) {
147  assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported");
148  const MCOperand &Op = MI->getOperand(OpNo);
149  if (Op.isReg())
150  OS << "%" << getRegisterName(Op.getReg());
151  else if (Op.isImm())
152  OS << formatHex(Op.getImm());
153  else {
154  assert(Op.isExpr() && "Expected an expression");
155  Op.getExpr()->print(OS, &MAI);
156  }
157 }
158 
159 void LanaiInstPrinter::printMemImmOperand(const MCInst *MI, unsigned OpNo,
160  raw_ostream &OS) {
161  const MCOperand &Op = MI->getOperand(OpNo);
162  if (Op.isImm()) {
163  OS << '[' << formatHex(Op.getImm()) << ']';
164  } else {
165  // Symbolic operand will be lowered to immediate value by linker
166  assert(Op.isExpr() && "Expected an expression");
167  OS << '[';
168  Op.getExpr()->print(OS, &MAI);
169  OS << ']';
170  }
171 }
172 
173 void LanaiInstPrinter::printHi16ImmOperand(const MCInst *MI, unsigned OpNo,
174  raw_ostream &OS) {
175  const MCOperand &Op = MI->getOperand(OpNo);
176  if (Op.isImm()) {
177  OS << formatHex(Op.getImm() << 16);
178  } else {
179  // Symbolic operand will be lowered to immediate value by linker
180  assert(Op.isExpr() && "Expected an expression");
181  Op.getExpr()->print(OS, &MAI);
182  }
183 }
184 
185 void LanaiInstPrinter::printHi16AndImmOperand(const MCInst *MI, unsigned OpNo,
186  raw_ostream &OS) {
187  const MCOperand &Op = MI->getOperand(OpNo);
188  if (Op.isImm()) {
189  OS << formatHex((Op.getImm() << 16) | 0xffff);
190  } else {
191  // Symbolic operand will be lowered to immediate value by linker
192  assert(Op.isExpr() && "Expected an expression");
193  Op.getExpr()->print(OS, &MAI);
194  }
195 }
196 
197 void LanaiInstPrinter::printLo16AndImmOperand(const MCInst *MI, unsigned OpNo,
198  raw_ostream &OS) {
199  const MCOperand &Op = MI->getOperand(OpNo);
200  if (Op.isImm()) {
201  OS << formatHex(0xffff0000 | Op.getImm());
202  } else {
203  // Symbolic operand will be lowered to immediate value by linker
204  assert(Op.isExpr() && "Expected an expression");
205  Op.getExpr()->print(OS, &MAI);
206  }
207 }
208 
209 static void printMemoryBaseRegister(raw_ostream &OS, const unsigned AluCode,
210  const MCOperand &RegOp) {
211  assert(RegOp.isReg() && "Register operand expected");
212  OS << "[";
213  if (LPAC::isPreOp(AluCode))
214  OS << "*";
215  OS << "%" << LanaiInstPrinter::getRegisterName(RegOp.getReg());
216  if (LPAC::isPostOp(AluCode))
217  OS << "*";
218  OS << "]";
219 }
220 
221 template <unsigned SizeInBits>
223  const MCOperand &OffsetOp,
224  raw_ostream &OS) {
225  assert((OffsetOp.isImm() || OffsetOp.isExpr()) && "Immediate expected");
226  if (OffsetOp.isImm()) {
227  assert(isInt<SizeInBits>(OffsetOp.getImm()) && "Constant value truncated");
228  OS << OffsetOp.getImm();
229  } else
230  OffsetOp.getExpr()->print(OS, &MAI);
231 }
232 
234  raw_ostream &OS,
235  const char * /*Modifier*/) {
236  const MCOperand &RegOp = MI->getOperand(OpNo);
237  const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
238  const MCOperand &AluOp = MI->getOperand(OpNo + 2);
239  const unsigned AluCode = AluOp.getImm();
240 
241  // Offset
242  printMemoryImmediateOffset<16>(MAI, OffsetOp, OS);
243 
244  // Register
245  printMemoryBaseRegister(OS, AluCode, RegOp);
246 }
247 
249  raw_ostream &OS,
250  const char * /*Modifier*/) {
251  const MCOperand &RegOp = MI->getOperand(OpNo);
252  const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
253  const MCOperand &AluOp = MI->getOperand(OpNo + 2);
254  const unsigned AluCode = AluOp.getImm();
255  assert(OffsetOp.isReg() && RegOp.isReg() && "Registers expected.");
256 
257  // [ Base OP Offset ]
258  OS << "[";
259  if (LPAC::isPreOp(AluCode))
260  OS << "*";
261  OS << "%" << getRegisterName(RegOp.getReg());
262  if (LPAC::isPostOp(AluCode))
263  OS << "*";
264  OS << " " << LPAC::lanaiAluCodeToString(AluCode) << " ";
265  OS << "%" << getRegisterName(OffsetOp.getReg());
266  OS << "]";
267 }
268 
270  raw_ostream &OS,
271  const char * /*Modifier*/) {
272  const MCOperand &RegOp = MI->getOperand(OpNo);
273  const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
274  const MCOperand &AluOp = MI->getOperand(OpNo + 2);
275  const unsigned AluCode = AluOp.getImm();
276 
277  // Offset
278  printMemoryImmediateOffset<10>(MAI, OffsetOp, OS);
279 
280  // Register
281  printMemoryBaseRegister(OS, AluCode, RegOp);
282 }
283 
284 void LanaiInstPrinter::printCCOperand(const MCInst *MI, int OpNo,
285  raw_ostream &OS) {
286  LPCC::CondCode CC =
287  static_cast<LPCC::CondCode>(MI->getOperand(OpNo).getImm());
288  // Handle the undefined value here for printing so we don't abort().
289  if (CC >= LPCC::UNKNOWN)
290  OS << "<und>";
291  else
292  OS << lanaiCondCodeToString(CC);
293 }
294 
295 void LanaiInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNo,
296  raw_ostream &OS) {
297  LPCC::CondCode CC =
298  static_cast<LPCC::CondCode>(MI->getOperand(OpNo).getImm());
299  // Handle the undefined value here for printing so we don't abort().
300  if (CC >= LPCC::UNKNOWN)
301  OS << "<und>";
302  else if (CC != LPCC::ICC_T)
303  OS << "." << lanaiCondCodeToString(CC);
304 }
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)
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:55
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:41
void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot, const MCSubtargetInfo &STI) override
Print the specified MCInst to the specified raw_ostream.
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:179
static bool isPreIncrementForm(const MCInst *MI, int AddOffset)
static bool isPostOp(unsigned AluOp)
Definition: LanaiAluCode.h:60
void printInstruction(const MCInst *MI, raw_ostream &O)
const MCAsmInfo & MAI
Definition: MCInstPrinter.h:45
void printPredicateOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O)
format_object< int64_t > formatHex(int64_t Value) const
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:107
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)
bool printAliasInstr(const MCInst *MI, raw_ostream &OS)
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:45
IRTranslator LLVM IR MI
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
unsigned getOpcode() const
Definition: MCInst.h:171
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:34
void printRegName(raw_ostream &OS, unsigned RegNo) const override
Print the assembler register name.
void printHi16AndImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O)