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