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