]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/llvm/lib/Target/Mips/MipsMCInstLower.cpp
MFC r355940:
[FreeBSD/FreeBSD.git] / contrib / llvm-project / llvm / lib / Target / Mips / MipsMCInstLower.cpp
1 //===- MipsMCInstLower.cpp - Convert Mips MachineInstr to MCInst ----------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains code to lower Mips MachineInstrs to their corresponding
10 // MCInst records.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "MipsMCInstLower.h"
15 #include "MCTargetDesc/MipsBaseInfo.h"
16 #include "MCTargetDesc/MipsMCExpr.h"
17 #include "MipsAsmPrinter.h"
18 #include "llvm/CodeGen/MachineBasicBlock.h"
19 #include "llvm/CodeGen/MachineInstr.h"
20 #include "llvm/CodeGen/MachineOperand.h"
21 #include "llvm/MC/MCExpr.h"
22 #include "llvm/MC/MCInst.h"
23 #include "llvm/Support/ErrorHandling.h"
24 #include <cassert>
25
26 using namespace llvm;
27
28 MipsMCInstLower::MipsMCInstLower(MipsAsmPrinter &asmprinter)
29   : AsmPrinter(asmprinter) {}
30
31 void MipsMCInstLower::Initialize(MCContext *C) {
32   Ctx = C;
33 }
34
35 MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO,
36                                               MachineOperandType MOTy,
37                                               unsigned Offset) const {
38   MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None;
39   MipsMCExpr::MipsExprKind TargetKind = MipsMCExpr::MEK_None;
40   bool IsGpOff = false;
41   const MCSymbol *Symbol;
42
43   switch(MO.getTargetFlags()) {
44   default:
45     llvm_unreachable("Invalid target flag!");
46   case MipsII::MO_NO_FLAG:
47     break;
48   case MipsII::MO_GPREL:
49     TargetKind = MipsMCExpr::MEK_GPREL;
50     break;
51   case MipsII::MO_GOT_CALL:
52     TargetKind = MipsMCExpr::MEK_GOT_CALL;
53     break;
54   case MipsII::MO_GOT:
55     TargetKind = MipsMCExpr::MEK_GOT;
56     break;
57   case MipsII::MO_ABS_HI:
58     TargetKind = MipsMCExpr::MEK_HI;
59     break;
60   case MipsII::MO_ABS_LO:
61     TargetKind = MipsMCExpr::MEK_LO;
62     break;
63   case MipsII::MO_TLSGD:
64     TargetKind = MipsMCExpr::MEK_TLSGD;
65     break;
66   case MipsII::MO_TLSLDM:
67     TargetKind = MipsMCExpr::MEK_TLSLDM;
68     break;
69   case MipsII::MO_DTPREL_HI:
70     TargetKind = MipsMCExpr::MEK_DTPREL_HI;
71     break;
72   case MipsII::MO_DTPREL_LO:
73     TargetKind = MipsMCExpr::MEK_DTPREL_LO;
74     break;
75   case MipsII::MO_GOTTPREL:
76     TargetKind = MipsMCExpr::MEK_GOTTPREL;
77     break;
78   case MipsII::MO_TPREL_HI:
79     TargetKind = MipsMCExpr::MEK_TPREL_HI;
80     break;
81   case MipsII::MO_TPREL_LO:
82     TargetKind = MipsMCExpr::MEK_TPREL_LO;
83     break;
84   case MipsII::MO_GPOFF_HI:
85     TargetKind = MipsMCExpr::MEK_HI;
86     IsGpOff = true;
87     break;
88   case MipsII::MO_GPOFF_LO:
89     TargetKind = MipsMCExpr::MEK_LO;
90     IsGpOff = true;
91     break;
92   case MipsII::MO_GOT_DISP:
93     TargetKind = MipsMCExpr::MEK_GOT_DISP;
94     break;
95   case MipsII::MO_GOT_HI16:
96     TargetKind = MipsMCExpr::MEK_GOT_HI16;
97     break;
98   case MipsII::MO_GOT_LO16:
99     TargetKind = MipsMCExpr::MEK_GOT_LO16;
100     break;
101   case MipsII::MO_GOT_PAGE:
102     TargetKind = MipsMCExpr::MEK_GOT_PAGE;
103     break;
104   case MipsII::MO_GOT_OFST:
105     TargetKind = MipsMCExpr::MEK_GOT_OFST;
106     break;
107   case MipsII::MO_HIGHER:
108     TargetKind = MipsMCExpr::MEK_HIGHER;
109     break;
110   case MipsII::MO_HIGHEST:
111     TargetKind = MipsMCExpr::MEK_HIGHEST;
112     break;
113   case MipsII::MO_CALL_HI16:
114     TargetKind = MipsMCExpr::MEK_CALL_HI16;
115     break;
116   case MipsII::MO_CALL_LO16:
117     TargetKind = MipsMCExpr::MEK_CALL_LO16;
118     break;
119   case MipsII::MO_JALR:
120     return MCOperand();
121   }
122
123   switch (MOTy) {
124   case MachineOperand::MO_MachineBasicBlock:
125     Symbol = MO.getMBB()->getSymbol();
126     break;
127
128   case MachineOperand::MO_GlobalAddress:
129     Symbol = AsmPrinter.getSymbol(MO.getGlobal());
130     Offset += MO.getOffset();
131     break;
132
133   case MachineOperand::MO_BlockAddress:
134     Symbol = AsmPrinter.GetBlockAddressSymbol(MO.getBlockAddress());
135     Offset += MO.getOffset();
136     break;
137
138   case MachineOperand::MO_ExternalSymbol:
139     Symbol = AsmPrinter.GetExternalSymbolSymbol(MO.getSymbolName());
140     Offset += MO.getOffset();
141     break;
142
143   case MachineOperand::MO_MCSymbol:
144     Symbol = MO.getMCSymbol();
145     Offset += MO.getOffset();
146     break;
147
148   case MachineOperand::MO_JumpTableIndex:
149     Symbol = AsmPrinter.GetJTISymbol(MO.getIndex());
150     break;
151
152   case MachineOperand::MO_ConstantPoolIndex:
153     Symbol = AsmPrinter.GetCPISymbol(MO.getIndex());
154     Offset += MO.getOffset();
155     break;
156
157   default:
158     llvm_unreachable("<unknown operand type>");
159   }
160
161   const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, Kind, *Ctx);
162
163   if (Offset) {
164     // Assume offset is never negative.
165     assert(Offset > 0);
166
167     Expr = MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(Offset, *Ctx),
168                                    *Ctx);
169   }
170
171   if (IsGpOff)
172     Expr = MipsMCExpr::createGpOff(TargetKind, Expr, *Ctx);
173   else if (TargetKind != MipsMCExpr::MEK_None)
174     Expr = MipsMCExpr::create(TargetKind, Expr, *Ctx);
175
176   return MCOperand::createExpr(Expr);
177 }
178
179 MCOperand MipsMCInstLower::LowerOperand(const MachineOperand &MO,
180                                         unsigned offset) const {
181   MachineOperandType MOTy = MO.getType();
182
183   switch (MOTy) {
184   default: llvm_unreachable("unknown operand type");
185   case MachineOperand::MO_Register:
186     // Ignore all implicit register operands.
187     if (MO.isImplicit()) break;
188     return MCOperand::createReg(MO.getReg());
189   case MachineOperand::MO_Immediate:
190     return MCOperand::createImm(MO.getImm() + offset);
191   case MachineOperand::MO_MachineBasicBlock:
192   case MachineOperand::MO_GlobalAddress:
193   case MachineOperand::MO_ExternalSymbol:
194   case MachineOperand::MO_MCSymbol:
195   case MachineOperand::MO_JumpTableIndex:
196   case MachineOperand::MO_ConstantPoolIndex:
197   case MachineOperand::MO_BlockAddress:
198     return LowerSymbolOperand(MO, MOTy, offset);
199   case MachineOperand::MO_RegisterMask:
200     break;
201  }
202
203   return MCOperand();
204 }
205
206 MCOperand MipsMCInstLower::createSub(MachineBasicBlock *BB1,
207                                      MachineBasicBlock *BB2,
208                                      MipsMCExpr::MipsExprKind Kind) const {
209   const MCSymbolRefExpr *Sym1 = MCSymbolRefExpr::create(BB1->getSymbol(), *Ctx);
210   const MCSymbolRefExpr *Sym2 = MCSymbolRefExpr::create(BB2->getSymbol(), *Ctx);
211   const MCBinaryExpr *Sub = MCBinaryExpr::createSub(Sym1, Sym2, *Ctx);
212
213   return MCOperand::createExpr(MipsMCExpr::create(Kind, Sub, *Ctx));
214 }
215
216 void MipsMCInstLower::
217 lowerLongBranchLUi(const MachineInstr *MI, MCInst &OutMI) const {
218   OutMI.setOpcode(Mips::LUi);
219
220   // Lower register operand.
221   OutMI.addOperand(LowerOperand(MI->getOperand(0)));
222
223   MipsMCExpr::MipsExprKind Kind;
224   unsigned TargetFlags = MI->getOperand(1).getTargetFlags();
225   switch (TargetFlags) {
226   case MipsII::MO_HIGHEST:
227     Kind = MipsMCExpr::MEK_HIGHEST;
228     break;
229   case MipsII::MO_HIGHER:
230     Kind = MipsMCExpr::MEK_HIGHER;
231     break;
232   case MipsII::MO_ABS_HI:
233     Kind = MipsMCExpr::MEK_HI;
234     break;
235   case MipsII::MO_ABS_LO:
236     Kind = MipsMCExpr::MEK_LO;
237     break;
238   default:
239     report_fatal_error("Unexpected flags for lowerLongBranchLUi");
240   }
241
242   if (MI->getNumOperands() == 2) {
243     const MCExpr *Expr =
244         MCSymbolRefExpr::create(MI->getOperand(1).getMBB()->getSymbol(), *Ctx);
245     const MipsMCExpr *MipsExpr = MipsMCExpr::create(Kind, Expr, *Ctx);
246     OutMI.addOperand(MCOperand::createExpr(MipsExpr));
247   } else if (MI->getNumOperands() == 3) {
248     // Create %hi($tgt-$baltgt).
249     OutMI.addOperand(createSub(MI->getOperand(1).getMBB(),
250                                MI->getOperand(2).getMBB(), Kind));
251   }
252 }
253
254 void MipsMCInstLower::lowerLongBranchADDiu(const MachineInstr *MI,
255                                            MCInst &OutMI, int Opcode) const {
256   OutMI.setOpcode(Opcode);
257
258   MipsMCExpr::MipsExprKind Kind;
259   unsigned TargetFlags = MI->getOperand(2).getTargetFlags();
260   switch (TargetFlags) {
261   case MipsII::MO_HIGHEST:
262     Kind = MipsMCExpr::MEK_HIGHEST;
263     break;
264   case MipsII::MO_HIGHER:
265     Kind = MipsMCExpr::MEK_HIGHER;
266     break;
267   case MipsII::MO_ABS_HI:
268     Kind = MipsMCExpr::MEK_HI;
269     break;
270   case MipsII::MO_ABS_LO:
271     Kind = MipsMCExpr::MEK_LO;
272     break;
273   default:
274     report_fatal_error("Unexpected flags for lowerLongBranchADDiu");
275   }
276
277   // Lower two register operands.
278   for (unsigned I = 0, E = 2; I != E; ++I) {
279     const MachineOperand &MO = MI->getOperand(I);
280     OutMI.addOperand(LowerOperand(MO));
281   }
282
283   if (MI->getNumOperands() == 3) {
284     // Lower register operand.
285     const MCExpr *Expr =
286         MCSymbolRefExpr::create(MI->getOperand(2).getMBB()->getSymbol(), *Ctx);
287     const MipsMCExpr *MipsExpr = MipsMCExpr::create(Kind, Expr, *Ctx);
288     OutMI.addOperand(MCOperand::createExpr(MipsExpr));
289   } else if (MI->getNumOperands() == 4) {
290     // Create %lo($tgt-$baltgt) or %hi($tgt-$baltgt).
291     OutMI.addOperand(createSub(MI->getOperand(2).getMBB(),
292                                MI->getOperand(3).getMBB(), Kind));
293   }
294 }
295
296 bool MipsMCInstLower::lowerLongBranch(const MachineInstr *MI,
297                                       MCInst &OutMI) const {
298   switch (MI->getOpcode()) {
299   default:
300     return false;
301   case Mips::LONG_BRANCH_LUi:
302   case Mips::LONG_BRANCH_LUi2Op:
303   case Mips::LONG_BRANCH_LUi2Op_64:
304     lowerLongBranchLUi(MI, OutMI);
305     return true;
306   case Mips::LONG_BRANCH_ADDiu:
307   case Mips::LONG_BRANCH_ADDiu2Op:
308     lowerLongBranchADDiu(MI, OutMI, Mips::ADDiu);
309     return true;
310   case Mips::LONG_BRANCH_DADDiu:
311   case Mips::LONG_BRANCH_DADDiu2Op:
312     lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu);
313     return true;
314   }
315 }
316
317 void MipsMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
318   if (lowerLongBranch(MI, OutMI))
319     return;
320
321   OutMI.setOpcode(MI->getOpcode());
322
323   for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
324     const MachineOperand &MO = MI->getOperand(i);
325     MCOperand MCOp = LowerOperand(MO);
326
327     if (MCOp.isValid())
328       OutMI.addOperand(MCOp);
329   }
330 }