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 
25 using namespace llvm;
26 
27 MipsMCInstLower::MipsMCInstLower(MipsAsmPrinter &asmprinter)
28   : AsmPrinter(asmprinter) {}
29 
30 void MipsMCInstLower::Initialize(MCContext *C) {
31   Ctx = C;
32 }
33 
34 MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO,
35                                               MachineOperandType MOTy,
36                                               int64_t Offset) const {
37   MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None;
38   MipsMCExpr::MipsExprKind TargetKind = MipsMCExpr::MEK_None;
39   bool IsGpOff = false;
40   const MCSymbol *Symbol;
41 
42   switch(MO.getTargetFlags()) {
43   default:
44     llvm_unreachable("Invalid target flag!");
45   case MipsII::MO_NO_FLAG:
46     break;
47   case MipsII::MO_GPREL:
48     TargetKind = MipsMCExpr::MEK_GPREL;
49     break;
50   case MipsII::MO_GOT_CALL:
51     TargetKind = MipsMCExpr::MEK_GOT_CALL;
52     break;
53   case MipsII::MO_GOT:
54     TargetKind = MipsMCExpr::MEK_GOT;
55     break;
56   case MipsII::MO_ABS_HI:
57     TargetKind = MipsMCExpr::MEK_HI;
58     break;
59   case MipsII::MO_ABS_LO:
60     TargetKind = MipsMCExpr::MEK_LO;
61     break;
62   case MipsII::MO_TLSGD:
63     TargetKind = MipsMCExpr::MEK_TLSGD;
64     break;
65   case MipsII::MO_TLSLDM:
66     TargetKind = MipsMCExpr::MEK_TLSLDM;
67     break;
68   case MipsII::MO_DTPREL_HI:
69     TargetKind = MipsMCExpr::MEK_DTPREL_HI;
70     break;
71   case MipsII::MO_DTPREL_LO:
72     TargetKind = MipsMCExpr::MEK_DTPREL_LO;
73     break;
74   case MipsII::MO_GOTTPREL:
75     TargetKind = MipsMCExpr::MEK_GOTTPREL;
76     break;
77   case MipsII::MO_TPREL_HI:
78     TargetKind = MipsMCExpr::MEK_TPREL_HI;
79     break;
80   case MipsII::MO_TPREL_LO:
81     TargetKind = MipsMCExpr::MEK_TPREL_LO;
82     break;
83   case MipsII::MO_GPOFF_HI:
84     TargetKind = MipsMCExpr::MEK_HI;
85     IsGpOff = true;
86     break;
87   case MipsII::MO_GPOFF_LO:
88     TargetKind = MipsMCExpr::MEK_LO;
89     IsGpOff = true;
90     break;
91   case MipsII::MO_GOT_DISP:
92     TargetKind = MipsMCExpr::MEK_GOT_DISP;
93     break;
94   case MipsII::MO_GOT_HI16:
95     TargetKind = MipsMCExpr::MEK_GOT_HI16;
96     break;
97   case MipsII::MO_GOT_LO16:
98     TargetKind = MipsMCExpr::MEK_GOT_LO16;
99     break;
100   case MipsII::MO_GOT_PAGE:
101     TargetKind = MipsMCExpr::MEK_GOT_PAGE;
102     break;
103   case MipsII::MO_GOT_OFST:
104     TargetKind = MipsMCExpr::MEK_GOT_OFST;
105     break;
106   case MipsII::MO_HIGHER:
107     TargetKind = MipsMCExpr::MEK_HIGHER;
108     break;
109   case MipsII::MO_HIGHEST:
110     TargetKind = MipsMCExpr::MEK_HIGHEST;
111     break;
112   case MipsII::MO_CALL_HI16:
113     TargetKind = MipsMCExpr::MEK_CALL_HI16;
114     break;
115   case MipsII::MO_CALL_LO16:
116     TargetKind = MipsMCExpr::MEK_CALL_LO16;
117     break;
118   case MipsII::MO_JALR:
119     return MCOperand();
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     // Note: Offset can also be negative
164     Expr = MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(Offset, *Ctx),
165                                    *Ctx);
166   }
167 
168   if (IsGpOff)
169     Expr = MipsMCExpr::createGpOff(TargetKind, Expr, *Ctx);
170   else if (TargetKind != MipsMCExpr::MEK_None)
171     Expr = MipsMCExpr::create(TargetKind, Expr, *Ctx);
172 
173   return MCOperand::createExpr(Expr);
174 }
175 
176 MCOperand MipsMCInstLower::LowerOperand(const MachineOperand &MO,
177                                         int64_t offset) const {
178   MachineOperandType MOTy = MO.getType();
179 
180   switch (MOTy) {
181   default: llvm_unreachable("unknown operand type");
182   case MachineOperand::MO_Register:
183     // Ignore all implicit register operands.
184     if (MO.isImplicit()) break;
185     return MCOperand::createReg(MO.getReg());
186   case MachineOperand::MO_Immediate:
187     return MCOperand::createImm(MO.getImm() + offset);
188   case MachineOperand::MO_MachineBasicBlock:
189   case MachineOperand::MO_GlobalAddress:
190   case MachineOperand::MO_ExternalSymbol:
191   case MachineOperand::MO_MCSymbol:
192   case MachineOperand::MO_JumpTableIndex:
193   case MachineOperand::MO_ConstantPoolIndex:
194   case MachineOperand::MO_BlockAddress:
195     return LowerSymbolOperand(MO, MOTy, offset);
196   case MachineOperand::MO_RegisterMask:
197     break;
198  }
199 
200   return MCOperand();
201 }
202 
203 MCOperand MipsMCInstLower::createSub(MachineBasicBlock *BB1,
204                                      MachineBasicBlock *BB2,
205                                      MipsMCExpr::MipsExprKind Kind) const {
206   const MCSymbolRefExpr *Sym1 = MCSymbolRefExpr::create(BB1->getSymbol(), *Ctx);
207   const MCSymbolRefExpr *Sym2 = MCSymbolRefExpr::create(BB2->getSymbol(), *Ctx);
208   const MCBinaryExpr *Sub = MCBinaryExpr::createSub(Sym1, Sym2, *Ctx);
209 
210   return MCOperand::createExpr(MipsMCExpr::create(Kind, Sub, *Ctx));
211 }
212 
213 void MipsMCInstLower::
214 lowerLongBranchLUi(const MachineInstr *MI, MCInst &OutMI) const {
215   OutMI.setOpcode(Mips::LUi);
216 
217   // Lower register operand.
218   OutMI.addOperand(LowerOperand(MI->getOperand(0)));
219 
220   MipsMCExpr::MipsExprKind Kind;
221   unsigned TargetFlags = MI->getOperand(1).getTargetFlags();
222   switch (TargetFlags) {
223   case MipsII::MO_HIGHEST:
224     Kind = MipsMCExpr::MEK_HIGHEST;
225     break;
226   case MipsII::MO_HIGHER:
227     Kind = MipsMCExpr::MEK_HIGHER;
228     break;
229   case MipsII::MO_ABS_HI:
230     Kind = MipsMCExpr::MEK_HI;
231     break;
232   case MipsII::MO_ABS_LO:
233     Kind = MipsMCExpr::MEK_LO;
234     break;
235   default:
236     report_fatal_error("Unexpected flags for lowerLongBranchLUi");
237   }
238 
239   if (MI->getNumOperands() == 2) {
240     const MCExpr *Expr =
241         MCSymbolRefExpr::create(MI->getOperand(1).getMBB()->getSymbol(), *Ctx);
242     const MipsMCExpr *MipsExpr = MipsMCExpr::create(Kind, Expr, *Ctx);
243     OutMI.addOperand(MCOperand::createExpr(MipsExpr));
244   } else if (MI->getNumOperands() == 3) {
245     // Create %hi($tgt-$baltgt).
246     OutMI.addOperand(createSub(MI->getOperand(1).getMBB(),
247                                MI->getOperand(2).getMBB(), Kind));
248   }
249 }
250 
251 void MipsMCInstLower::lowerLongBranchADDiu(const MachineInstr *MI,
252                                            MCInst &OutMI, int Opcode) const {
253   OutMI.setOpcode(Opcode);
254 
255   MipsMCExpr::MipsExprKind Kind;
256   unsigned TargetFlags = MI->getOperand(2).getTargetFlags();
257   switch (TargetFlags) {
258   case MipsII::MO_HIGHEST:
259     Kind = MipsMCExpr::MEK_HIGHEST;
260     break;
261   case MipsII::MO_HIGHER:
262     Kind = MipsMCExpr::MEK_HIGHER;
263     break;
264   case MipsII::MO_ABS_HI:
265     Kind = MipsMCExpr::MEK_HI;
266     break;
267   case MipsII::MO_ABS_LO:
268     Kind = MipsMCExpr::MEK_LO;
269     break;
270   default:
271     report_fatal_error("Unexpected flags for lowerLongBranchADDiu");
272   }
273 
274   // Lower two register operands.
275   for (unsigned I = 0, E = 2; I != E; ++I) {
276     const MachineOperand &MO = MI->getOperand(I);
277     OutMI.addOperand(LowerOperand(MO));
278   }
279 
280   if (MI->getNumOperands() == 3) {
281     // Lower register operand.
282     const MCExpr *Expr =
283         MCSymbolRefExpr::create(MI->getOperand(2).getMBB()->getSymbol(), *Ctx);
284     const MipsMCExpr *MipsExpr = MipsMCExpr::create(Kind, Expr, *Ctx);
285     OutMI.addOperand(MCOperand::createExpr(MipsExpr));
286   } else if (MI->getNumOperands() == 4) {
287     // Create %lo($tgt-$baltgt) or %hi($tgt-$baltgt).
288     OutMI.addOperand(createSub(MI->getOperand(2).getMBB(),
289                                MI->getOperand(3).getMBB(), Kind));
290   }
291 }
292 
293 bool MipsMCInstLower::lowerLongBranch(const MachineInstr *MI,
294                                       MCInst &OutMI) const {
295   switch (MI->getOpcode()) {
296   default:
297     return false;
298   case Mips::LONG_BRANCH_LUi:
299   case Mips::LONG_BRANCH_LUi2Op:
300   case Mips::LONG_BRANCH_LUi2Op_64:
301     lowerLongBranchLUi(MI, OutMI);
302     return true;
303   case Mips::LONG_BRANCH_ADDiu:
304   case Mips::LONG_BRANCH_ADDiu2Op:
305     lowerLongBranchADDiu(MI, OutMI, Mips::ADDiu);
306     return true;
307   case Mips::LONG_BRANCH_DADDiu:
308   case Mips::LONG_BRANCH_DADDiu2Op:
309     lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu);
310     return true;
311   }
312 }
313 
314 void MipsMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
315   if (lowerLongBranch(MI, OutMI))
316     return;
317 
318   OutMI.setOpcode(MI->getOpcode());
319 
320   for (const MachineOperand &MO : MI->operands()) {
321     MCOperand MCOp = LowerOperand(MO);
322 
323     if (MCOp.isValid())
324       OutMI.addOperand(MCOp);
325   }
326 }
327