]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/Target/Mips/MipsMCInstLower.cpp
Merge ^/head r327886 through r327930.
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / Target / Mips / MipsMCInstLower.cpp
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
29 MipsMCInstLower::MipsMCInstLower(MipsAsmPrinter &asmprinter)
30   : AsmPrinter(asmprinter) {}
31
32 void MipsMCInstLower::Initialize(MCContext *C) {
33   Ctx = C;
34 }
35
36 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
178 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
205 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::
216 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   // Create %hi($tgt-$baltgt).
223   OutMI.addOperand(createSub(MI->getOperand(1).getMBB(),
224                              MI->getOperand(2).getMBB(),
225                              MipsMCExpr::MEK_HI));
226 }
227
228 void MipsMCInstLower::lowerLongBranchADDiu(
229     const MachineInstr *MI, MCInst &OutMI, int Opcode,
230     MipsMCExpr::MipsExprKind Kind) const {
231   OutMI.setOpcode(Opcode);
232
233   // Lower two register operands.
234   for (unsigned I = 0, E = 2; I != E; ++I) {
235     const MachineOperand &MO = MI->getOperand(I);
236     OutMI.addOperand(LowerOperand(MO));
237   }
238
239   // Create %lo($tgt-$baltgt) or %hi($tgt-$baltgt).
240   OutMI.addOperand(createSub(MI->getOperand(2).getMBB(),
241                              MI->getOperand(3).getMBB(), Kind));
242 }
243
244 bool MipsMCInstLower::lowerLongBranch(const MachineInstr *MI,
245                                       MCInst &OutMI) const {
246   switch (MI->getOpcode()) {
247   default:
248     return false;
249   case Mips::LONG_BRANCH_LUi:
250     lowerLongBranchLUi(MI, OutMI);
251     return true;
252   case Mips::LONG_BRANCH_ADDiu:
253     lowerLongBranchADDiu(MI, OutMI, Mips::ADDiu, MipsMCExpr::MEK_LO);
254     return true;
255   case Mips::LONG_BRANCH_DADDiu:
256     unsigned TargetFlags = MI->getOperand(2).getTargetFlags();
257     if (TargetFlags == MipsII::MO_ABS_HI)
258       lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu, MipsMCExpr::MEK_HI);
259     else if (TargetFlags == MipsII::MO_ABS_LO)
260       lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu, MipsMCExpr::MEK_LO);
261     else
262       report_fatal_error("Unexpected flags for LONG_BRANCH_DADDiu");
263     return true;
264   }
265 }
266
267 void MipsMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
268   if (lowerLongBranch(MI, OutMI))
269     return;
270
271   OutMI.setOpcode(MI->getOpcode());
272
273   for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
274     const MachineOperand &MO = MI->getOperand(i);
275     MCOperand MCOp = LowerOperand(MO);
276
277     if (MCOp.isValid())
278       OutMI.addOperand(MCOp);
279   }
280 }