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   }
121 
122   switch (MOTy) {
123   case MachineOperand::MO_MachineBasicBlock:
124     Symbol = MO.getMBB()->getSymbol();
125     break;
126 
127   case MachineOperand::MO_GlobalAddress:
128     Symbol = AsmPrinter.getSymbol(MO.getGlobal());
129     Offset += MO.getOffset();
130     break;
131 
132   case MachineOperand::MO_BlockAddress:
133     Symbol = AsmPrinter.GetBlockAddressSymbol(MO.getBlockAddress());
134     Offset += MO.getOffset();
135     break;
136 
137   case MachineOperand::MO_ExternalSymbol:
138     Symbol = AsmPrinter.GetExternalSymbolSymbol(MO.getSymbolName());
139     Offset += MO.getOffset();
140     break;
141 
142   case MachineOperand::MO_MCSymbol:
143     Symbol = MO.getMCSymbol();
144     Offset += MO.getOffset();
145     break;
146 
147   case MachineOperand::MO_JumpTableIndex:
148     Symbol = AsmPrinter.GetJTISymbol(MO.getIndex());
149     break;
150 
151   case MachineOperand::MO_ConstantPoolIndex:
152     Symbol = AsmPrinter.GetCPISymbol(MO.getIndex());
153     Offset += MO.getOffset();
154     break;
155 
156   default:
157     llvm_unreachable("<unknown operand type>");
158   }
159 
160   const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, Kind, *Ctx);
161 
162   if (Offset) {
163     // Assume offset is never negative.
164     assert(Offset > 0);
165 
166     Expr = MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(Offset, *Ctx),
167                                    *Ctx);
168   }
169 
170   if (IsGpOff)
171     Expr = MipsMCExpr::createGpOff(TargetKind, Expr, *Ctx);
172   else if (TargetKind != MipsMCExpr::MEK_None)
173     Expr = MipsMCExpr::create(TargetKind, Expr, *Ctx);
174 
175   return MCOperand::createExpr(Expr);
176 }
177 
LowerOperand(const MachineOperand & MO,unsigned offset) const178 MCOperand MipsMCInstLower::LowerOperand(const MachineOperand &MO,
179                                         unsigned offset) const {
180   MachineOperandType MOTy = MO.getType();
181 
182   switch (MOTy) {
183   default: llvm_unreachable("unknown operand type");
184   case MachineOperand::MO_Register:
185     // Ignore all implicit register operands.
186     if (MO.isImplicit()) break;
187     return MCOperand::createReg(MO.getReg());
188   case MachineOperand::MO_Immediate:
189     return MCOperand::createImm(MO.getImm() + offset);
190   case MachineOperand::MO_MachineBasicBlock:
191   case MachineOperand::MO_GlobalAddress:
192   case MachineOperand::MO_ExternalSymbol:
193   case MachineOperand::MO_MCSymbol:
194   case MachineOperand::MO_JumpTableIndex:
195   case MachineOperand::MO_ConstantPoolIndex:
196   case MachineOperand::MO_BlockAddress:
197     return LowerSymbolOperand(MO, MOTy, offset);
198   case MachineOperand::MO_RegisterMask:
199     break;
200  }
201 
202   return MCOperand();
203 }
204 
createSub(MachineBasicBlock * BB1,MachineBasicBlock * BB2,MipsMCExpr::MipsExprKind Kind) const205 MCOperand MipsMCInstLower::createSub(MachineBasicBlock *BB1,
206                                      MachineBasicBlock *BB2,
207                                      MipsMCExpr::MipsExprKind Kind) const {
208   const MCSymbolRefExpr *Sym1 = MCSymbolRefExpr::create(BB1->getSymbol(), *Ctx);
209   const MCSymbolRefExpr *Sym2 = MCSymbolRefExpr::create(BB2->getSymbol(), *Ctx);
210   const MCBinaryExpr *Sub = MCBinaryExpr::createSub(Sym1, Sym2, *Ctx);
211 
212   return MCOperand::createExpr(MipsMCExpr::create(Kind, Sub, *Ctx));
213 }
214 
215 void MipsMCInstLower::
lowerLongBranchLUi(const MachineInstr * MI,MCInst & OutMI) const216 lowerLongBranchLUi(const MachineInstr *MI, MCInst &OutMI) const {
217   OutMI.setOpcode(Mips::LUi);
218 
219   // Lower register operand.
220   OutMI.addOperand(LowerOperand(MI->getOperand(0)));
221 
222   MipsMCExpr::MipsExprKind Kind;
223   unsigned TargetFlags = MI->getOperand(1).getTargetFlags();
224   switch (TargetFlags) {
225   case MipsII::MO_HIGHEST:
226     Kind = MipsMCExpr::MEK_HIGHEST;
227     break;
228   case MipsII::MO_HIGHER:
229     Kind = MipsMCExpr::MEK_HIGHER;
230     break;
231   case MipsII::MO_ABS_HI:
232     Kind = MipsMCExpr::MEK_HI;
233     break;
234   case MipsII::MO_ABS_LO:
235     Kind = MipsMCExpr::MEK_LO;
236     break;
237   default:
238     report_fatal_error("Unexpected flags for lowerLongBranchLUi");
239   }
240 
241   if (MI->getNumOperands() == 2) {
242     const MCExpr *Expr =
243         MCSymbolRefExpr::create(MI->getOperand(1).getMBB()->getSymbol(), *Ctx);
244     const MipsMCExpr *MipsExpr = MipsMCExpr::create(Kind, Expr, *Ctx);
245     OutMI.addOperand(MCOperand::createExpr(MipsExpr));
246   } else if (MI->getNumOperands() == 3) {
247     // Create %hi($tgt-$baltgt).
248     OutMI.addOperand(createSub(MI->getOperand(1).getMBB(),
249                                MI->getOperand(2).getMBB(), Kind));
250   }
251 }
252 
lowerLongBranchADDiu(const MachineInstr * MI,MCInst & OutMI,int Opcode) const253 void MipsMCInstLower::lowerLongBranchADDiu(const MachineInstr *MI,
254                                            MCInst &OutMI, int Opcode) const {
255   OutMI.setOpcode(Opcode);
256 
257   MipsMCExpr::MipsExprKind Kind;
258   unsigned TargetFlags = MI->getOperand(2).getTargetFlags();
259   switch (TargetFlags) {
260   case MipsII::MO_HIGHEST:
261     Kind = MipsMCExpr::MEK_HIGHEST;
262     break;
263   case MipsII::MO_HIGHER:
264     Kind = MipsMCExpr::MEK_HIGHER;
265     break;
266   case MipsII::MO_ABS_HI:
267     Kind = MipsMCExpr::MEK_HI;
268     break;
269   case MipsII::MO_ABS_LO:
270     Kind = MipsMCExpr::MEK_LO;
271     break;
272   default:
273     report_fatal_error("Unexpected flags for lowerLongBranchADDiu");
274   }
275 
276   // Lower two register operands.
277   for (unsigned I = 0, E = 2; I != E; ++I) {
278     const MachineOperand &MO = MI->getOperand(I);
279     OutMI.addOperand(LowerOperand(MO));
280   }
281 
282   if (MI->getNumOperands() == 3) {
283     // Lower register operand.
284     const MCExpr *Expr =
285         MCSymbolRefExpr::create(MI->getOperand(2).getMBB()->getSymbol(), *Ctx);
286     const MipsMCExpr *MipsExpr = MipsMCExpr::create(Kind, Expr, *Ctx);
287     OutMI.addOperand(MCOperand::createExpr(MipsExpr));
288   } else if (MI->getNumOperands() == 4) {
289     // Create %lo($tgt-$baltgt) or %hi($tgt-$baltgt).
290     OutMI.addOperand(createSub(MI->getOperand(2).getMBB(),
291                                MI->getOperand(3).getMBB(), Kind));
292   }
293 }
294 
lowerLongBranch(const MachineInstr * MI,MCInst & OutMI) const295 bool MipsMCInstLower::lowerLongBranch(const MachineInstr *MI,
296                                       MCInst &OutMI) const {
297   switch (MI->getOpcode()) {
298   default:
299     return false;
300   case Mips::LONG_BRANCH_LUi:
301     lowerLongBranchLUi(MI, OutMI);
302     return true;
303   case Mips::LONG_BRANCH_ADDiu:
304     lowerLongBranchADDiu(MI, OutMI, Mips::ADDiu);
305     return true;
306   case Mips::LONG_BRANCH_DADDiu:
307     lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu);
308     return true;
309   }
310 }
311 
Lower(const MachineInstr * MI,MCInst & OutMI) const312 void MipsMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
313   if (lowerLongBranch(MI, OutMI))
314     return;
315 
316   OutMI.setOpcode(MI->getOpcode());
317 
318   for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
319     const MachineOperand &MO = MI->getOperand(i);
320     MCOperand MCOp = LowerOperand(MO);
321 
322     if (MCOp.isValid())
323       OutMI.addOperand(MCOp);
324   }
325 }
326