xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Mips/MipsMCInstLower.cpp (revision cab6a39d7b343596a5823e65c0f7b426551ec22d)
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                                               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 
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     // Note: Offset can also be negative
165     Expr = MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(Offset, *Ctx),
166                                    *Ctx);
167   }
168 
169   if (IsGpOff)
170     Expr = MipsMCExpr::createGpOff(TargetKind, Expr, *Ctx);
171   else if (TargetKind != MipsMCExpr::MEK_None)
172     Expr = MipsMCExpr::create(TargetKind, Expr, *Ctx);
173 
174   return MCOperand::createExpr(Expr);
175 }
176 
177 MCOperand MipsMCInstLower::LowerOperand(const MachineOperand &MO,
178                                         int64_t offset) const {
179   MachineOperandType MOTy = MO.getType();
180 
181   switch (MOTy) {
182   default: llvm_unreachable("unknown operand type");
183   case MachineOperand::MO_Register:
184     // Ignore all implicit register operands.
185     if (MO.isImplicit()) break;
186     return MCOperand::createReg(MO.getReg());
187   case MachineOperand::MO_Immediate:
188     return MCOperand::createImm(MO.getImm() + offset);
189   case MachineOperand::MO_MachineBasicBlock:
190   case MachineOperand::MO_GlobalAddress:
191   case MachineOperand::MO_ExternalSymbol:
192   case MachineOperand::MO_MCSymbol:
193   case MachineOperand::MO_JumpTableIndex:
194   case MachineOperand::MO_ConstantPoolIndex:
195   case MachineOperand::MO_BlockAddress:
196     return LowerSymbolOperand(MO, MOTy, offset);
197   case MachineOperand::MO_RegisterMask:
198     break;
199  }
200 
201   return MCOperand();
202 }
203 
204 MCOperand MipsMCInstLower::createSub(MachineBasicBlock *BB1,
205                                      MachineBasicBlock *BB2,
206                                      MipsMCExpr::MipsExprKind Kind) const {
207   const MCSymbolRefExpr *Sym1 = MCSymbolRefExpr::create(BB1->getSymbol(), *Ctx);
208   const MCSymbolRefExpr *Sym2 = MCSymbolRefExpr::create(BB2->getSymbol(), *Ctx);
209   const MCBinaryExpr *Sub = MCBinaryExpr::createSub(Sym1, Sym2, *Ctx);
210 
211   return MCOperand::createExpr(MipsMCExpr::create(Kind, Sub, *Ctx));
212 }
213 
214 void MipsMCInstLower::
215 lowerLongBranchLUi(const MachineInstr *MI, MCInst &OutMI) const {
216   OutMI.setOpcode(Mips::LUi);
217 
218   // Lower register operand.
219   OutMI.addOperand(LowerOperand(MI->getOperand(0)));
220 
221   MipsMCExpr::MipsExprKind Kind;
222   unsigned TargetFlags = MI->getOperand(1).getTargetFlags();
223   switch (TargetFlags) {
224   case MipsII::MO_HIGHEST:
225     Kind = MipsMCExpr::MEK_HIGHEST;
226     break;
227   case MipsII::MO_HIGHER:
228     Kind = MipsMCExpr::MEK_HIGHER;
229     break;
230   case MipsII::MO_ABS_HI:
231     Kind = MipsMCExpr::MEK_HI;
232     break;
233   case MipsII::MO_ABS_LO:
234     Kind = MipsMCExpr::MEK_LO;
235     break;
236   default:
237     report_fatal_error("Unexpected flags for lowerLongBranchLUi");
238   }
239 
240   if (MI->getNumOperands() == 2) {
241     const MCExpr *Expr =
242         MCSymbolRefExpr::create(MI->getOperand(1).getMBB()->getSymbol(), *Ctx);
243     const MipsMCExpr *MipsExpr = MipsMCExpr::create(Kind, Expr, *Ctx);
244     OutMI.addOperand(MCOperand::createExpr(MipsExpr));
245   } else if (MI->getNumOperands() == 3) {
246     // Create %hi($tgt-$baltgt).
247     OutMI.addOperand(createSub(MI->getOperand(1).getMBB(),
248                                MI->getOperand(2).getMBB(), Kind));
249   }
250 }
251 
252 void MipsMCInstLower::lowerLongBranchADDiu(const MachineInstr *MI,
253                                            MCInst &OutMI, int Opcode) const {
254   OutMI.setOpcode(Opcode);
255 
256   MipsMCExpr::MipsExprKind Kind;
257   unsigned TargetFlags = MI->getOperand(2).getTargetFlags();
258   switch (TargetFlags) {
259   case MipsII::MO_HIGHEST:
260     Kind = MipsMCExpr::MEK_HIGHEST;
261     break;
262   case MipsII::MO_HIGHER:
263     Kind = MipsMCExpr::MEK_HIGHER;
264     break;
265   case MipsII::MO_ABS_HI:
266     Kind = MipsMCExpr::MEK_HI;
267     break;
268   case MipsII::MO_ABS_LO:
269     Kind = MipsMCExpr::MEK_LO;
270     break;
271   default:
272     report_fatal_error("Unexpected flags for lowerLongBranchADDiu");
273   }
274 
275   // Lower two register operands.
276   for (unsigned I = 0, E = 2; I != E; ++I) {
277     const MachineOperand &MO = MI->getOperand(I);
278     OutMI.addOperand(LowerOperand(MO));
279   }
280 
281   if (MI->getNumOperands() == 3) {
282     // Lower register operand.
283     const MCExpr *Expr =
284         MCSymbolRefExpr::create(MI->getOperand(2).getMBB()->getSymbol(), *Ctx);
285     const MipsMCExpr *MipsExpr = MipsMCExpr::create(Kind, Expr, *Ctx);
286     OutMI.addOperand(MCOperand::createExpr(MipsExpr));
287   } else if (MI->getNumOperands() == 4) {
288     // Create %lo($tgt-$baltgt) or %hi($tgt-$baltgt).
289     OutMI.addOperand(createSub(MI->getOperand(2).getMBB(),
290                                MI->getOperand(3).getMBB(), Kind));
291   }
292 }
293 
294 bool MipsMCInstLower::lowerLongBranch(const MachineInstr *MI,
295                                       MCInst &OutMI) const {
296   switch (MI->getOpcode()) {
297   default:
298     return false;
299   case Mips::LONG_BRANCH_LUi:
300   case Mips::LONG_BRANCH_LUi2Op:
301   case Mips::LONG_BRANCH_LUi2Op_64:
302     lowerLongBranchLUi(MI, OutMI);
303     return true;
304   case Mips::LONG_BRANCH_ADDiu:
305   case Mips::LONG_BRANCH_ADDiu2Op:
306     lowerLongBranchADDiu(MI, OutMI, Mips::ADDiu);
307     return true;
308   case Mips::LONG_BRANCH_DADDiu:
309   case Mips::LONG_BRANCH_DADDiu2Op:
310     lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu);
311     return true;
312   }
313 }
314 
315 void MipsMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
316   if (lowerLongBranch(MI, OutMI))
317     return;
318 
319   OutMI.setOpcode(MI->getOpcode());
320 
321   for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
322     const MachineOperand &MO = MI->getOperand(i);
323     MCOperand MCOp = LowerOperand(MO);
324 
325     if (MCOp.isValid())
326       OutMI.addOperand(MCOp);
327   }
328 }
329