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