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"
16 #include "MCTargetDesc/MipsBaseInfo.h"
17 #include "MCTargetDesc/MipsMCExpr.h"
18 #include "MipsAsmPrinter.h"
19 #include "llvm/CodeGen/MachineBasicBlock.h"
20 #include "llvm/CodeGen/MachineInstr.h"
21 #include "llvm/CodeGen/MachineOperand.h"
22 #include "llvm/MC/MCExpr.h"
23 #include "llvm/MC/MCInst.h"
24 #include "llvm/Support/ErrorHandling.h"
25 #include <cassert>
26 
27 using namespace llvm;
28 
MipsMCInstLower(MipsAsmPrinter & asmprinter)29 MipsMCInstLower::MipsMCInstLower(MipsAsmPrinter &asmprinter)
30   : AsmPrinter(asmprinter) {}
31 
Initialize(MCContext * C)32 void MipsMCInstLower::Initialize(MCContext *C) {
33   Ctx = C;
34 }
35 
LowerSymbolOperand(const MachineOperand & MO,MachineOperandType MOTy,unsigned Offset) const36 MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO,
37                                               MachineOperandType MOTy,
38                                               unsigned Offset) const {
39   MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None;
40   MipsMCExpr::MipsExprKind TargetKind = MipsMCExpr::MEK_None;
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;
52   case MipsII::MO_GOT_CALL:
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;
70   case MipsII::MO_DTPREL_HI:
71     TargetKind = MipsMCExpr::MEK_DTPREL_HI;
72     break;
73   case MipsII::MO_DTPREL_LO:
74     TargetKind = MipsMCExpr::MEK_DTPREL_LO;
75     break;
76   case MipsII::MO_GOTTPREL:
77     TargetKind = MipsMCExpr::MEK_GOTTPREL;
78     break;
79   case MipsII::MO_TPREL_HI:
80     TargetKind = MipsMCExpr::MEK_TPREL_HI;
81     break;
82   case MipsII::MO_TPREL_LO:
83     TargetKind = MipsMCExpr::MEK_TPREL_LO;
84     break;
85   case MipsII::MO_GPOFF_HI:
86     TargetKind = MipsMCExpr::MEK_HI;
87     IsGpOff = true;
88     break;
89   case MipsII::MO_GPOFF_LO:
90     TargetKind = MipsMCExpr::MEK_LO;
91     IsGpOff = true;
92     break;
93   case MipsII::MO_GOT_DISP:
94     TargetKind = MipsMCExpr::MEK_GOT_DISP;
95     break;
96   case MipsII::MO_GOT_HI16:
97     TargetKind = MipsMCExpr::MEK_GOT_HI16;
98     break;
99   case MipsII::MO_GOT_LO16:
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;
114   case MipsII::MO_CALL_HI16:
115     TargetKind = MipsMCExpr::MEK_CALL_HI16;
116     break;
117   case MipsII::MO_CALL_LO16:
118     TargetKind = MipsMCExpr::MEK_CALL_LO16;
119     break;
120   case MipsII::MO_JALR:
121     return MCOperand();
122   }
123 
124   switch (MOTy) {
125   case MachineOperand::MO_MachineBasicBlock:
126     Symbol = MO.getMBB()->getSymbol();
127     break;
128 
129   case MachineOperand::MO_GlobalAddress:
130     Symbol = AsmPrinter.getSymbol(MO.getGlobal());
131     Offset += MO.getOffset();
132     break;
133 
134   case MachineOperand::MO_BlockAddress:
135     Symbol = AsmPrinter.GetBlockAddressSymbol(MO.getBlockAddress());
136     Offset += MO.getOffset();
137     break;
138 
139   case MachineOperand::MO_ExternalSymbol:
140     Symbol = AsmPrinter.GetExternalSymbolSymbol(MO.getSymbolName());
141     Offset += MO.getOffset();
142     break;
143 
144   case MachineOperand::MO_MCSymbol:
145     Symbol = MO.getMCSymbol();
146     Offset += MO.getOffset();
147     break;
148 
149   case MachineOperand::MO_JumpTableIndex:
150     Symbol = AsmPrinter.GetJTISymbol(MO.getIndex());
151     break;
152 
153   case MachineOperand::MO_ConstantPoolIndex:
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 
LowerOperand(const MachineOperand & MO,unsigned offset) const180 MCOperand MipsMCInstLower::LowerOperand(const MachineOperand &MO,
181                                         unsigned offset) const {
182   MachineOperandType MOTy = MO.getType();
183 
184   switch (MOTy) {
185   default: llvm_unreachable("unknown operand type");
186   case MachineOperand::MO_Register:
187     // Ignore all implicit register operands.
188     if (MO.isImplicit()) break;
189     return MCOperand::createReg(MO.getReg());
190   case MachineOperand::MO_Immediate:
191     return MCOperand::createImm(MO.getImm() + offset);
192   case MachineOperand::MO_MachineBasicBlock:
193   case MachineOperand::MO_GlobalAddress:
194   case MachineOperand::MO_ExternalSymbol:
195   case MachineOperand::MO_MCSymbol:
196   case MachineOperand::MO_JumpTableIndex:
197   case MachineOperand::MO_ConstantPoolIndex:
198   case MachineOperand::MO_BlockAddress:
199     return LowerSymbolOperand(MO, MOTy, offset);
200   case MachineOperand::MO_RegisterMask:
201     break;
202  }
203 
204   return MCOperand();
205 }
206 
createSub(MachineBasicBlock * BB1,MachineBasicBlock * BB2,MipsMCExpr::MipsExprKind Kind) const207 MCOperand MipsMCInstLower::createSub(MachineBasicBlock *BB1,
208                                      MachineBasicBlock *BB2,
209                                      MipsMCExpr::MipsExprKind Kind) const {
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::
lowerLongBranchLUi(const MachineInstr * MI,MCInst & OutMI) const218 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 
224   MipsMCExpr::MipsExprKind Kind;
225   unsigned TargetFlags = MI->getOperand(1).getTargetFlags();
226   switch (TargetFlags) {
227   case MipsII::MO_HIGHEST:
228     Kind = MipsMCExpr::MEK_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 =
245         MCSymbolRefExpr::create(MI->getOperand(1).getMBB()->getSymbol(), *Ctx);
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 
lowerLongBranchADDiu(const MachineInstr * MI,MCInst & OutMI,int Opcode) const255 void MipsMCInstLower::lowerLongBranchADDiu(const MachineInstr *MI,
256                                            MCInst &OutMI, int Opcode) const {
257   OutMI.setOpcode(Opcode);
258 
259   MipsMCExpr::MipsExprKind Kind;
260   unsigned TargetFlags = MI->getOperand(2).getTargetFlags();
261   switch (TargetFlags) {
262   case MipsII::MO_HIGHEST:
263     Kind = MipsMCExpr::MEK_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 =
287         MCSymbolRefExpr::create(MI->getOperand(2).getMBB()->getSymbol(), *Ctx);
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 
lowerLongBranch(const MachineInstr * MI,MCInst & OutMI) const297 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 
Lower(const MachineInstr * MI,MCInst & OutMI) const318 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 }
332