LLVM  8.0.1
MipsMCInstLower.cpp
Go to the documentation of this file.
1 //===- MipsMCInstLower.cpp - Convert Mips MachineInstr to MCInst ----------===//
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 file contains code to lower Mips MachineInstrs to their corresponding
11 // MCInst records.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "MipsMCInstLower.h"
18 #include "MipsAsmPrinter.h"
22 #include "llvm/MC/MCExpr.h"
23 #include "llvm/MC/MCInst.h"
25 #include <cassert>
26 
27 using namespace llvm;
28 
30  : AsmPrinter(asmprinter) {}
31 
33  Ctx = C;
34 }
35 
36 MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO,
37  MachineOperandType MOTy,
38  unsigned Offset) const {
41  bool IsGpOff = false;
42  const MCSymbol *Symbol;
43 
44  switch(MO.getTargetFlags()) {
45  default:
46  llvm_unreachable("Invalid target flag!");
47  case MipsII::MO_NO_FLAG:
48  break;
49  case MipsII::MO_GPREL:
50  TargetKind = MipsMCExpr::MEK_GPREL;
51  break;
53  TargetKind = MipsMCExpr::MEK_GOT_CALL;
54  break;
55  case MipsII::MO_GOT:
56  TargetKind = MipsMCExpr::MEK_GOT;
57  break;
58  case MipsII::MO_ABS_HI:
59  TargetKind = MipsMCExpr::MEK_HI;
60  break;
61  case MipsII::MO_ABS_LO:
62  TargetKind = MipsMCExpr::MEK_LO;
63  break;
64  case MipsII::MO_TLSGD:
65  TargetKind = MipsMCExpr::MEK_TLSGD;
66  break;
67  case MipsII::MO_TLSLDM:
68  TargetKind = MipsMCExpr::MEK_TLSLDM;
69  break;
71  TargetKind = MipsMCExpr::MEK_DTPREL_HI;
72  break;
74  TargetKind = MipsMCExpr::MEK_DTPREL_LO;
75  break;
77  TargetKind = MipsMCExpr::MEK_GOTTPREL;
78  break;
80  TargetKind = MipsMCExpr::MEK_TPREL_HI;
81  break;
83  TargetKind = MipsMCExpr::MEK_TPREL_LO;
84  break;
86  TargetKind = MipsMCExpr::MEK_HI;
87  IsGpOff = true;
88  break;
90  TargetKind = MipsMCExpr::MEK_LO;
91  IsGpOff = true;
92  break;
94  TargetKind = MipsMCExpr::MEK_GOT_DISP;
95  break;
97  TargetKind = MipsMCExpr::MEK_GOT_HI16;
98  break;
100  TargetKind = MipsMCExpr::MEK_GOT_LO16;
101  break;
102  case MipsII::MO_GOT_PAGE:
103  TargetKind = MipsMCExpr::MEK_GOT_PAGE;
104  break;
105  case MipsII::MO_GOT_OFST:
106  TargetKind = MipsMCExpr::MEK_GOT_OFST;
107  break;
108  case MipsII::MO_HIGHER:
109  TargetKind = MipsMCExpr::MEK_HIGHER;
110  break;
111  case MipsII::MO_HIGHEST:
112  TargetKind = MipsMCExpr::MEK_HIGHEST;
113  break;
115  TargetKind = MipsMCExpr::MEK_CALL_HI16;
116  break;
118  TargetKind = MipsMCExpr::MEK_CALL_LO16;
119  break;
120  case MipsII::MO_JALR:
121  return MCOperand();
122  }
123 
124  switch (MOTy) {
126  Symbol = MO.getMBB()->getSymbol();
127  break;
128 
130  Symbol = AsmPrinter.getSymbol(MO.getGlobal());
131  Offset += MO.getOffset();
132  break;
133 
136  Offset += MO.getOffset();
137  break;
138 
141  Offset += MO.getOffset();
142  break;
143 
145  Symbol = MO.getMCSymbol();
146  Offset += MO.getOffset();
147  break;
148 
150  Symbol = AsmPrinter.GetJTISymbol(MO.getIndex());
151  break;
152 
154  Symbol = AsmPrinter.GetCPISymbol(MO.getIndex());
155  Offset += MO.getOffset();
156  break;
157 
158  default:
159  llvm_unreachable("<unknown operand type>");
160  }
161 
162  const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, Kind, *Ctx);
163 
164  if (Offset) {
165  // Assume offset is never negative.
166  assert(Offset > 0);
167 
168  Expr = MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(Offset, *Ctx),
169  *Ctx);
170  }
171 
172  if (IsGpOff)
173  Expr = MipsMCExpr::createGpOff(TargetKind, Expr, *Ctx);
174  else if (TargetKind != MipsMCExpr::MEK_None)
175  Expr = MipsMCExpr::create(TargetKind, Expr, *Ctx);
176 
177  return MCOperand::createExpr(Expr);
178 }
179 
181  unsigned offset) const {
182  MachineOperandType MOTy = MO.getType();
183 
184  switch (MOTy) {
185  default: llvm_unreachable("unknown operand type");
187  // Ignore all implicit register operands.
188  if (MO.isImplicit()) break;
189  return MCOperand::createReg(MO.getReg());
191  return MCOperand::createImm(MO.getImm() + offset);
199  return LowerSymbolOperand(MO, MOTy, offset);
201  break;
202  }
203 
204  return MCOperand();
205 }
206 
207 MCOperand MipsMCInstLower::createSub(MachineBasicBlock *BB1,
208  MachineBasicBlock *BB2,
210  const MCSymbolRefExpr *Sym1 = MCSymbolRefExpr::create(BB1->getSymbol(), *Ctx);
211  const MCSymbolRefExpr *Sym2 = MCSymbolRefExpr::create(BB2->getSymbol(), *Ctx);
212  const MCBinaryExpr *Sub = MCBinaryExpr::createSub(Sym1, Sym2, *Ctx);
213 
214  return MCOperand::createExpr(MipsMCExpr::create(Kind, Sub, *Ctx));
215 }
216 
217 void MipsMCInstLower::
218 lowerLongBranchLUi(const MachineInstr *MI, MCInst &OutMI) const {
219  OutMI.setOpcode(Mips::LUi);
220 
221  // Lower register operand.
222  OutMI.addOperand(LowerOperand(MI->getOperand(0)));
223 
225  unsigned TargetFlags = MI->getOperand(1).getTargetFlags();
226  switch (TargetFlags) {
227  case MipsII::MO_HIGHEST:
229  break;
230  case MipsII::MO_HIGHER:
231  Kind = MipsMCExpr::MEK_HIGHER;
232  break;
233  case MipsII::MO_ABS_HI:
234  Kind = MipsMCExpr::MEK_HI;
235  break;
236  case MipsII::MO_ABS_LO:
237  Kind = MipsMCExpr::MEK_LO;
238  break;
239  default:
240  report_fatal_error("Unexpected flags for lowerLongBranchLUi");
241  }
242 
243  if (MI->getNumOperands() == 2) {
244  const MCExpr *Expr =
246  const MipsMCExpr *MipsExpr = MipsMCExpr::create(Kind, Expr, *Ctx);
247  OutMI.addOperand(MCOperand::createExpr(MipsExpr));
248  } else if (MI->getNumOperands() == 3) {
249  // Create %hi($tgt-$baltgt).
250  OutMI.addOperand(createSub(MI->getOperand(1).getMBB(),
251  MI->getOperand(2).getMBB(), Kind));
252  }
253 }
254 
255 void MipsMCInstLower::lowerLongBranchADDiu(const MachineInstr *MI,
256  MCInst &OutMI, int Opcode) const {
257  OutMI.setOpcode(Opcode);
258 
260  unsigned TargetFlags = MI->getOperand(2).getTargetFlags();
261  switch (TargetFlags) {
262  case MipsII::MO_HIGHEST:
264  break;
265  case MipsII::MO_HIGHER:
266  Kind = MipsMCExpr::MEK_HIGHER;
267  break;
268  case MipsII::MO_ABS_HI:
269  Kind = MipsMCExpr::MEK_HI;
270  break;
271  case MipsII::MO_ABS_LO:
272  Kind = MipsMCExpr::MEK_LO;
273  break;
274  default:
275  report_fatal_error("Unexpected flags for lowerLongBranchADDiu");
276  }
277 
278  // Lower two register operands.
279  for (unsigned I = 0, E = 2; I != E; ++I) {
280  const MachineOperand &MO = MI->getOperand(I);
281  OutMI.addOperand(LowerOperand(MO));
282  }
283 
284  if (MI->getNumOperands() == 3) {
285  // Lower register operand.
286  const MCExpr *Expr =
288  const MipsMCExpr *MipsExpr = MipsMCExpr::create(Kind, Expr, *Ctx);
289  OutMI.addOperand(MCOperand::createExpr(MipsExpr));
290  } else if (MI->getNumOperands() == 4) {
291  // Create %lo($tgt-$baltgt) or %hi($tgt-$baltgt).
292  OutMI.addOperand(createSub(MI->getOperand(2).getMBB(),
293  MI->getOperand(3).getMBB(), Kind));
294  }
295 }
296 
297 bool MipsMCInstLower::lowerLongBranch(const MachineInstr *MI,
298  MCInst &OutMI) const {
299  switch (MI->getOpcode()) {
300  default:
301  return false;
302  case Mips::LONG_BRANCH_LUi:
303  case Mips::LONG_BRANCH_LUi2Op:
304  case Mips::LONG_BRANCH_LUi2Op_64:
305  lowerLongBranchLUi(MI, OutMI);
306  return true;
307  case Mips::LONG_BRANCH_ADDiu:
308  case Mips::LONG_BRANCH_ADDiu2Op:
309  lowerLongBranchADDiu(MI, OutMI, Mips::ADDiu);
310  return true;
311  case Mips::LONG_BRANCH_DADDiu:
312  case Mips::LONG_BRANCH_DADDiu2Op:
313  lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu);
314  return true;
315  }
316 }
317 
318 void MipsMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
319  if (lowerLongBranch(MI, OutMI))
320  return;
321 
322  OutMI.setOpcode(MI->getOpcode());
323 
324  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
325  const MachineOperand &MO = MI->getOperand(i);
326  MCOperand MCOp = LowerOperand(MO);
327 
328  if (MCOp.isValid())
329  OutMI.addOperand(MCOp);
330  }
331 }
unsigned getTargetFlags() const
uint64_t CallInst * C
MachineBasicBlock * getMBB() const
MCSymbol * GetExternalSymbolSymbol(StringRef Sym) const
Return the MCSymbol for the specified ExternalSymbol.
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
Definition: MCExpr.h:323
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:140
This class represents lattice values for constants.
Definition: AllocatorList.h:24
MO_TLSLDM - Represents the offset into the global offset table at which.
Definition: MipsBaseInfo.h:63
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:42
MO_HIGHER/HIGHEST - Represents the highest or higher half word of a 64-bit symbol address...
Definition: MipsBaseInfo.h:85
static MCOperand createExpr(const MCExpr *Val)
Definition: MCInst.h:137
MO_GOT_HI16/LO16, MO_CALL_HI16/LO16 - Relocations used for large GOTs.
Definition: MipsBaseInfo.h:89
MO_TLSGD - Represents the offset into the global offset table at which.
Definition: MipsBaseInfo.h:58
unsigned getReg() const
getReg - Returns the register number.
Address of indexed Jump Table for switch.
MachineBasicBlock reference.
void Initialize(MCContext *C)
Mask of preserved registers.
static MCOperand createReg(unsigned Reg)
Definition: MCInst.h:116
unsigned getNumOperands() const
Retuns the total number of operands.
Definition: MachineInstr.h:412
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:36
Name of external global symbol.
Represent a reference to a symbol from inside an expression.
Definition: MCExpr.h:166
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:409
const char * getSymbolName() const
MO_ABS_HI/LO - Represents the hi or low part of an absolute symbol address.
Definition: MipsBaseInfo.h:52
Context object for machine code objects.
Definition: MCContext.h:63
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:546
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:461
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:161
MO_GPREL - Represents the offset from the current gp value to be used for the relocatable object file...
Definition: MipsBaseInfo.h:48
Address of a global value.
MO_GOT_CALL - Represents the offset into the global offset table at which the address of a call site ...
Definition: MipsBaseInfo.h:44
static const MipsMCExpr * createGpOff(MipsExprKind Kind, const MCExpr *Expr, MCContext &Ctx)
Definition: MipsMCExpr.cpp:33
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
const GlobalValue * getGlobal() const
This class is intended to be used as a driving class for all asm writers.
Definition: AsmPrinter.h:79
void Lower(const MachineInstr *MI, MCInst &OutMI) const
Address of a basic block.
Binary assembler expressions.
Definition: MCExpr.h:417
virtual MCSymbol * GetCPISymbol(unsigned CPID) const
Return the symbol for the specified constant pool entry.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
MO_GOTTPREL - Represents the offset from the thread pointer (Initial.
Definition: MipsBaseInfo.h:69
MO_GOT - Represents the offset into the global offset table at which the address the relocation entry...
Definition: MipsBaseInfo.h:38
void setOpcode(unsigned Op)
Definition: MCInst.h:173
MCSymbol * GetBlockAddressSymbol(const BlockAddress *BA) const
Return the MCSymbol used to satisfy BlockAddress uses of the specified basic block.
MCSymbol * getSymbol(const GlobalValue *GV) const
Definition: AsmPrinter.cpp:430
MachineOperand class - Representation of each machine instruction operand.
MipsMCInstLower(MipsAsmPrinter &asmprinter)
int64_t getImm() const
MCSymbol reference (for debug/eh info)
static const MipsMCExpr * create(MipsExprKind Kind, const MCExpr *Expr, MCContext &Ctx)
Definition: MipsMCExpr.cpp:28
MO_TPREL_HI/LO - Represents the hi and low part of the offset from.
Definition: MipsBaseInfo.h:73
Representation of each machine instruction.
Definition: MachineInstr.h:64
MCSymbol * GetJTISymbol(unsigned JTID, bool isLinkerPrivate=false) const
Return the symbol for the specified jump table entry.
int64_t getOffset() const
Return the offset from the symbol in this operand.
const BlockAddress * getBlockAddress() const
MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
#define I(x, y, z)
Definition: MD5.cpp:58
MCOperand LowerOperand(const MachineOperand &MO, unsigned offset=0) const
const unsigned Kind
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
MCSymbol * getMCSymbol() const
IRTranslator LLVM IR MI
void addOperand(const MCOperand &Op)
Definition: MCInst.h:186
bool isValid() const
Definition: MCInst.h:57
Address of indexed Constant in Constant Pool.
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:414
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:35
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
static MCOperand createImm(int64_t Val)
Definition: MCInst.h:123
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx)
Definition: MCExpr.cpp:164
bool isImplicit() const
Helper operand used to generate R_MIPS_JALR.
Definition: MipsBaseInfo.h:95