LLVM  9.0.0svn
MipsMCInstLower.cpp
Go to the documentation of this file.
1 //===- MipsMCInstLower.cpp - Convert Mips MachineInstr to MCInst ----------===//
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 file contains code to lower Mips MachineInstrs to their corresponding
10 // MCInst records.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "MipsMCInstLower.h"
17 #include "MipsAsmPrinter.h"
21 #include "llvm/MC/MCExpr.h"
22 #include "llvm/MC/MCInst.h"
24 #include <cassert>
25 
26 using namespace llvm;
27 
29  : AsmPrinter(asmprinter) {}
30 
32  Ctx = C;
33 }
34 
35 MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO,
36  MachineOperandType MOTy,
37  unsigned Offset) const {
40  bool IsGpOff = false;
41  const MCSymbol *Symbol;
42 
43  switch(MO.getTargetFlags()) {
44  default:
45  llvm_unreachable("Invalid target flag!");
46  case MipsII::MO_NO_FLAG:
47  break;
48  case MipsII::MO_GPREL:
49  TargetKind = MipsMCExpr::MEK_GPREL;
50  break;
52  TargetKind = MipsMCExpr::MEK_GOT_CALL;
53  break;
54  case MipsII::MO_GOT:
55  TargetKind = MipsMCExpr::MEK_GOT;
56  break;
57  case MipsII::MO_ABS_HI:
58  TargetKind = MipsMCExpr::MEK_HI;
59  break;
60  case MipsII::MO_ABS_LO:
61  TargetKind = MipsMCExpr::MEK_LO;
62  break;
63  case MipsII::MO_TLSGD:
64  TargetKind = MipsMCExpr::MEK_TLSGD;
65  break;
66  case MipsII::MO_TLSLDM:
67  TargetKind = MipsMCExpr::MEK_TLSLDM;
68  break;
70  TargetKind = MipsMCExpr::MEK_DTPREL_HI;
71  break;
73  TargetKind = MipsMCExpr::MEK_DTPREL_LO;
74  break;
76  TargetKind = MipsMCExpr::MEK_GOTTPREL;
77  break;
79  TargetKind = MipsMCExpr::MEK_TPREL_HI;
80  break;
82  TargetKind = MipsMCExpr::MEK_TPREL_LO;
83  break;
85  TargetKind = MipsMCExpr::MEK_HI;
86  IsGpOff = true;
87  break;
89  TargetKind = MipsMCExpr::MEK_LO;
90  IsGpOff = true;
91  break;
93  TargetKind = MipsMCExpr::MEK_GOT_DISP;
94  break;
96  TargetKind = MipsMCExpr::MEK_GOT_HI16;
97  break;
99  TargetKind = MipsMCExpr::MEK_GOT_LO16;
100  break;
101  case MipsII::MO_GOT_PAGE:
102  TargetKind = MipsMCExpr::MEK_GOT_PAGE;
103  break;
104  case MipsII::MO_GOT_OFST:
105  TargetKind = MipsMCExpr::MEK_GOT_OFST;
106  break;
107  case MipsII::MO_HIGHER:
108  TargetKind = MipsMCExpr::MEK_HIGHER;
109  break;
110  case MipsII::MO_HIGHEST:
111  TargetKind = MipsMCExpr::MEK_HIGHEST;
112  break;
114  TargetKind = MipsMCExpr::MEK_CALL_HI16;
115  break;
117  TargetKind = MipsMCExpr::MEK_CALL_LO16;
118  break;
119  case MipsII::MO_JALR:
120  return MCOperand();
121  }
122 
123  switch (MOTy) {
125  Symbol = MO.getMBB()->getSymbol();
126  break;
127 
129  Symbol = AsmPrinter.getSymbol(MO.getGlobal());
130  Offset += MO.getOffset();
131  break;
132 
135  Offset += MO.getOffset();
136  break;
137 
140  Offset += MO.getOffset();
141  break;
142 
144  Symbol = MO.getMCSymbol();
145  Offset += MO.getOffset();
146  break;
147 
149  Symbol = AsmPrinter.GetJTISymbol(MO.getIndex());
150  break;
151 
153  Symbol = AsmPrinter.GetCPISymbol(MO.getIndex());
154  Offset += MO.getOffset();
155  break;
156 
157  default:
158  llvm_unreachable("<unknown operand type>");
159  }
160 
161  const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, Kind, *Ctx);
162 
163  if (Offset) {
164  // Assume offset is never negative.
165  assert(Offset > 0);
166 
167  Expr = MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(Offset, *Ctx),
168  *Ctx);
169  }
170 
171  if (IsGpOff)
172  Expr = MipsMCExpr::createGpOff(TargetKind, Expr, *Ctx);
173  else if (TargetKind != MipsMCExpr::MEK_None)
174  Expr = MipsMCExpr::create(TargetKind, Expr, *Ctx);
175 
176  return MCOperand::createExpr(Expr);
177 }
178 
180  unsigned offset) const {
181  MachineOperandType MOTy = MO.getType();
182 
183  switch (MOTy) {
184  default: llvm_unreachable("unknown operand type");
186  // Ignore all implicit register operands.
187  if (MO.isImplicit()) break;
188  return MCOperand::createReg(MO.getReg());
190  return MCOperand::createImm(MO.getImm() + offset);
198  return LowerSymbolOperand(MO, MOTy, offset);
200  break;
201  }
202 
203  return MCOperand();
204 }
205 
206 MCOperand MipsMCInstLower::createSub(MachineBasicBlock *BB1,
207  MachineBasicBlock *BB2,
209  const MCSymbolRefExpr *Sym1 = MCSymbolRefExpr::create(BB1->getSymbol(), *Ctx);
210  const MCSymbolRefExpr *Sym2 = MCSymbolRefExpr::create(BB2->getSymbol(), *Ctx);
211  const MCBinaryExpr *Sub = MCBinaryExpr::createSub(Sym1, Sym2, *Ctx);
212 
213  return MCOperand::createExpr(MipsMCExpr::create(Kind, Sub, *Ctx));
214 }
215 
216 void MipsMCInstLower::
217 lowerLongBranchLUi(const MachineInstr *MI, MCInst &OutMI) const {
218  OutMI.setOpcode(Mips::LUi);
219 
220  // Lower register operand.
221  OutMI.addOperand(LowerOperand(MI->getOperand(0)));
222 
224  unsigned TargetFlags = MI->getOperand(1).getTargetFlags();
225  switch (TargetFlags) {
226  case MipsII::MO_HIGHEST:
228  break;
229  case MipsII::MO_HIGHER:
230  Kind = MipsMCExpr::MEK_HIGHER;
231  break;
232  case MipsII::MO_ABS_HI:
233  Kind = MipsMCExpr::MEK_HI;
234  break;
235  case MipsII::MO_ABS_LO:
236  Kind = MipsMCExpr::MEK_LO;
237  break;
238  default:
239  report_fatal_error("Unexpected flags for lowerLongBranchLUi");
240  }
241 
242  if (MI->getNumOperands() == 2) {
243  const MCExpr *Expr =
245  const MipsMCExpr *MipsExpr = MipsMCExpr::create(Kind, Expr, *Ctx);
246  OutMI.addOperand(MCOperand::createExpr(MipsExpr));
247  } else if (MI->getNumOperands() == 3) {
248  // Create %hi($tgt-$baltgt).
249  OutMI.addOperand(createSub(MI->getOperand(1).getMBB(),
250  MI->getOperand(2).getMBB(), Kind));
251  }
252 }
253 
254 void MipsMCInstLower::lowerLongBranchADDiu(const MachineInstr *MI,
255  MCInst &OutMI, int Opcode) const {
256  OutMI.setOpcode(Opcode);
257 
259  unsigned TargetFlags = MI->getOperand(2).getTargetFlags();
260  switch (TargetFlags) {
261  case MipsII::MO_HIGHEST:
263  break;
264  case MipsII::MO_HIGHER:
265  Kind = MipsMCExpr::MEK_HIGHER;
266  break;
267  case MipsII::MO_ABS_HI:
268  Kind = MipsMCExpr::MEK_HI;
269  break;
270  case MipsII::MO_ABS_LO:
271  Kind = MipsMCExpr::MEK_LO;
272  break;
273  default:
274  report_fatal_error("Unexpected flags for lowerLongBranchADDiu");
275  }
276 
277  // Lower two register operands.
278  for (unsigned I = 0, E = 2; I != E; ++I) {
279  const MachineOperand &MO = MI->getOperand(I);
280  OutMI.addOperand(LowerOperand(MO));
281  }
282 
283  if (MI->getNumOperands() == 3) {
284  // Lower register operand.
285  const MCExpr *Expr =
287  const MipsMCExpr *MipsExpr = MipsMCExpr::create(Kind, Expr, *Ctx);
288  OutMI.addOperand(MCOperand::createExpr(MipsExpr));
289  } else if (MI->getNumOperands() == 4) {
290  // Create %lo($tgt-$baltgt) or %hi($tgt-$baltgt).
291  OutMI.addOperand(createSub(MI->getOperand(2).getMBB(),
292  MI->getOperand(3).getMBB(), Kind));
293  }
294 }
295 
296 bool MipsMCInstLower::lowerLongBranch(const MachineInstr *MI,
297  MCInst &OutMI) const {
298  switch (MI->getOpcode()) {
299  default:
300  return false;
301  case Mips::LONG_BRANCH_LUi:
302  case Mips::LONG_BRANCH_LUi2Op:
303  case Mips::LONG_BRANCH_LUi2Op_64:
304  lowerLongBranchLUi(MI, OutMI);
305  return true;
306  case Mips::LONG_BRANCH_ADDiu:
307  case Mips::LONG_BRANCH_ADDiu2Op:
308  lowerLongBranchADDiu(MI, OutMI, Mips::ADDiu);
309  return true;
310  case Mips::LONG_BRANCH_DADDiu:
311  case Mips::LONG_BRANCH_DADDiu2Op:
312  lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu);
313  return true;
314  }
315 }
316 
317 void MipsMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
318  if (lowerLongBranch(MI, OutMI))
319  return;
320 
321  OutMI.setOpcode(MI->getOpcode());
322 
323  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
324  const MachineOperand &MO = MI->getOperand(i);
325  MCOperand MCOp = LowerOperand(MO);
326 
327  if (MCOp.isValid())
328  OutMI.addOperand(MCOp);
329  }
330 }
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:321
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:139
This class represents lattice values for constants.
Definition: AllocatorList.h:23
MO_TLSLDM - Represents the offset into the global offset table at which.
Definition: MipsBaseInfo.h:62
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
MO_HIGHER/HIGHEST - Represents the highest or higher half word of a 64-bit symbol address...
Definition: MipsBaseInfo.h:84
static MCOperand createExpr(const MCExpr *Val)
Definition: MCInst.h:136
MO_GOT_HI16/LO16, MO_CALL_HI16/LO16 - Relocations used for large GOTs.
Definition: MipsBaseInfo.h:88
MO_TLSGD - Represents the offset into the global offset table at which.
Definition: MipsBaseInfo.h:57
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:115
unsigned getNumOperands() const
Retuns the total number of operands.
Definition: MachineInstr.h:411
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:35
Name of external global symbol.
Represent a reference to a symbol from inside an expression.
Definition: MCExpr.h:165
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:408
const char * getSymbolName() const
MO_ABS_HI/LO - Represents the hi or low part of an absolute symbol address.
Definition: MipsBaseInfo.h:51
Context object for machine code objects.
Definition: MCContext.h:62
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:544
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:459
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:158
MO_GPREL - Represents the offset from the current gp value to be used for the relocatable object file...
Definition: MipsBaseInfo.h:47
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:43
static const MipsMCExpr * createGpOff(MipsExprKind Kind, const MCExpr *Expr, MCContext &Ctx)
Definition: MipsMCExpr.cpp:32
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:78
void Lower(const MachineInstr *MI, MCInst &OutMI) const
Address of a basic block.
Binary assembler expressions.
Definition: MCExpr.h:415
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:68
MO_GOT - Represents the offset into the global offset table at which the address the relocation entry...
Definition: MipsBaseInfo.h:37
void setOpcode(unsigned Op)
Definition: MCInst.h:170
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:441
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:27
MO_TPREL_HI/LO - Represents the hi and low part of the offset from.
Definition: MipsBaseInfo.h:72
Representation of each machine instruction.
Definition: MachineInstr.h:63
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
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
MCSymbol * getMCSymbol() const
IRTranslator LLVM IR MI
void addOperand(const MCOperand &Op)
Definition: MCInst.h:183
bool isValid() const
Definition: MCInst.h:56
Address of indexed Constant in Constant Pool.
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:413
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:34
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
static MCOperand createImm(int64_t Val)
Definition: MCInst.h:122
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx)
Definition: MCExpr.cpp:163
bool isImplicit() const
Helper operand used to generate R_MIPS_JALR.
Definition: MipsBaseInfo.h:94