LLVM  8.0.1
LanaiInstPrinter.cpp
Go to the documentation of this file.
1 //===-- LanaiInstPrinter.cpp - Convert Lanai MCInst to asm syntax ---------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This class prints an Lanai MCInst to a .s file.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "LanaiInstPrinter.h"
15 #include "Lanai.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"
23 
24 using namespace llvm;
25 
26 #define DEBUG_TYPE "asm-printer"
27 
28 // Include the auto-generated portion of the assembly writer.
29 #define PRINT_ALIAS_INSTR
30 #include "LanaiGenAsmWriter.inc"
31 
32 void LanaiInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
33  OS << StringRef(getRegisterName(RegNo)).lower();
34 }
35 
37  StringRef Alias, unsigned OpNo0,
38  unsigned OpNo1) {
39  OS << "\t" << Alias << " ";
40  printOperand(MI, OpNo0, OS);
41  OS << ", ";
42  printOperand(MI, OpNo1, OS);
43  return true;
44 }
45 
46 static bool usesGivenOffset(const MCInst *MI, int AddOffset) {
47  unsigned AluCode = MI->getOperand(3).getImm();
48  return LPAC::encodeLanaiAluCode(AluCode) == LPAC::ADD &&
49  (MI->getOperand(2).getImm() == AddOffset ||
50  MI->getOperand(2).getImm() == -AddOffset);
51 }
52 
53 static bool isPreIncrementForm(const MCInst *MI, int AddOffset) {
54  unsigned AluCode = MI->getOperand(3).getImm();
55  return LPAC::isPreOp(AluCode) && usesGivenOffset(MI, AddOffset);
56 }
57 
58 static bool isPostIncrementForm(const MCInst *MI, int AddOffset) {
59  unsigned AluCode = MI->getOperand(3).getImm();
60  return LPAC::isPostOp(AluCode) && usesGivenOffset(MI, AddOffset);
61 }
62 
63 static StringRef decIncOperator(const MCInst *MI) {
64  if (MI->getOperand(2).getImm() < 0)
65  return "--";
66  return "++";
67 }
68 
69 bool LanaiInstPrinter::printMemoryLoadIncrement(const MCInst *MI,
70  raw_ostream &OS,
71  StringRef Opcode,
72  int AddOffset) {
73  if (isPreIncrementForm(MI, AddOffset)) {
74  OS << "\t" << Opcode << "\t[" << decIncOperator(MI) << "%"
75  << getRegisterName(MI->getOperand(1).getReg()) << "], %"
76  << getRegisterName(MI->getOperand(0).getReg());
77  return true;
78  }
79  if (isPostIncrementForm(MI, AddOffset)) {
80  OS << "\t" << Opcode << "\t[%"
82  << "], %" << getRegisterName(MI->getOperand(0).getReg());
83  return true;
84  }
85  return false;
86 }
87 
88 bool LanaiInstPrinter::printMemoryStoreIncrement(const MCInst *MI,
89  raw_ostream &OS,
90  StringRef Opcode,
91  int AddOffset) {
92  if (isPreIncrementForm(MI, AddOffset)) {
93  OS << "\t" << Opcode << "\t%" << getRegisterName(MI->getOperand(0).getReg())
94  << ", [" << decIncOperator(MI) << "%"
95  << getRegisterName(MI->getOperand(1).getReg()) << "]";
96  return true;
97  }
98  if (isPostIncrementForm(MI, AddOffset)) {
99  OS << "\t" << Opcode << "\t%" << getRegisterName(MI->getOperand(0).getReg())
100  << ", [%" << getRegisterName(MI->getOperand(1).getReg())
101  << decIncOperator(MI) << "]";
102  return true;
103  }
104  return false;
105 }
106 
107 bool LanaiInstPrinter::printAlias(const MCInst *MI, raw_ostream &OS) {
108  switch (MI->getOpcode()) {
109  case Lanai::LDW_RI:
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  // ld -4[%rN*], %rX => ld [imm--], %rX
114  return printMemoryLoadIncrement(MI, OS, "ld", 4);
115  case Lanai::LDHs_RI:
116  return printMemoryLoadIncrement(MI, OS, "ld.h", 2);
117  case Lanai::LDHz_RI:
118  return printMemoryLoadIncrement(MI, OS, "uld.h", 2);
119  case Lanai::LDBs_RI:
120  return printMemoryLoadIncrement(MI, OS, "ld.b", 1);
121  case Lanai::LDBz_RI:
122  return printMemoryLoadIncrement(MI, OS, "uld.b", 1);
123  case Lanai::SW_RI:
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  // st %rX, -4[%rN*] => st %rX, [imm--]
128  return printMemoryStoreIncrement(MI, OS, "st", 4);
129  case Lanai::STH_RI:
130  return printMemoryStoreIncrement(MI, OS, "st.h", 2);
131  case Lanai::STB_RI:
132  return printMemoryStoreIncrement(MI, OS, "st.b", 1);
133  default:
134  return false;
135  }
136 }
137 
139  StringRef Annotation,
140  const MCSubtargetInfo & /*STI*/) {
141  if (!printAlias(MI, OS) && !printAliasInstr(MI, OS))
142  printInstruction(MI, OS);
143  printAnnotation(OS, Annotation);
144 }
145 
146 void LanaiInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
147  raw_ostream &OS, const char *Modifier) {
148  assert((Modifier == 0 || 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 
160 void LanaiInstPrinter::printMemImmOperand(const MCInst *MI, unsigned OpNo,
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 
174 void LanaiInstPrinter::printHi16ImmOperand(const MCInst *MI, unsigned OpNo,
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 
186 void LanaiInstPrinter::printHi16AndImmOperand(const MCInst *MI, unsigned OpNo,
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 
198 void LanaiInstPrinter::printLo16AndImmOperand(const MCInst *MI, unsigned OpNo,
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 
210 static 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 << "*";
216  OS << "%" << LanaiInstPrinter::getRegisterName(RegOp.getReg());
217  if (LPAC::isPostOp(AluCode))
218  OS << "*";
219  OS << "]";
220 }
221 
222 template <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 
235  raw_ostream &OS,
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 
250  raw_ostream &OS,
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 
271  raw_ostream &OS,
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 
285 void LanaiInstPrinter::printCCOperand(const MCInst *MI, int OpNo,
286  raw_ostream &OS) {
287  LPCC::CondCode CC =
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 
296 void LanaiInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNo,
297  raw_ostream &OS) {
298  LPCC::CondCode CC =
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 }
void printMemSplsOperand(const MCInst *MI, int OpNo, raw_ostream &O, const char *Modifier=nullptr)
bool isImm() const
Definition: MCInst.h:59
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:24
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:77
bool isReg() const
Definition: MCInst.h:58
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:65
static bool usesGivenOffset(const MCInst *MI, int AddOffset)
const MCExpr * getExpr() const
Definition: MCInst.h:96
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:161
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:59
int64_t getImm() const
Definition: MCInst.h:76
void print(raw_ostream &OS, const MCAsmInfo *MAI, bool InParens=false) const
Definition: MCExpr.cpp:42
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:61
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:182
static bool isPreIncrementForm(const MCInst *MI, int AddOffset)
static bool isPostOp(unsigned AluOp)
Definition: LanaiAluCode.h:61
void printInstruction(const MCInst *MI, raw_ostream &O)
const MCAsmInfo & MAI
Definition: MCInstPrinter.h:46
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:49
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)
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:46
IRTranslator LLVM IR MI
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
unsigned getOpcode() const
Definition: MCInst.h:174
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:35
void printRegName(raw_ostream &OS, unsigned RegNo) const override
Print the assembler register name.
void printHi16AndImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O)