[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / lib / Target / Mips / MipsMCInstLower.cpp
blob66e04bda2af32396b99fe99e6d743300b91e52f4
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.
12 //===----------------------------------------------------------------------===//
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>
26 using namespace llvm;
28 MipsMCInstLower::MipsMCInstLower(MipsAsmPrinter &asmprinter)
29 : AsmPrinter(asmprinter) {}
31 void MipsMCInstLower::Initialize(MCContext *C) {
32 Ctx = C;
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;
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();
123 switch (MOTy) {
124 case MachineOperand::MO_MachineBasicBlock:
125 Symbol = MO.getMBB()->getSymbol();
126 break;
128 case MachineOperand::MO_GlobalAddress:
129 Symbol = AsmPrinter.getSymbol(MO.getGlobal());
130 Offset += MO.getOffset();
131 break;
133 case MachineOperand::MO_BlockAddress:
134 Symbol = AsmPrinter.GetBlockAddressSymbol(MO.getBlockAddress());
135 Offset += MO.getOffset();
136 break;
138 case MachineOperand::MO_ExternalSymbol:
139 Symbol = AsmPrinter.GetExternalSymbolSymbol(MO.getSymbolName());
140 Offset += MO.getOffset();
141 break;
143 case MachineOperand::MO_MCSymbol:
144 Symbol = MO.getMCSymbol();
145 Offset += MO.getOffset();
146 break;
148 case MachineOperand::MO_JumpTableIndex:
149 Symbol = AsmPrinter.GetJTISymbol(MO.getIndex());
150 break;
152 case MachineOperand::MO_ConstantPoolIndex:
153 Symbol = AsmPrinter.GetCPISymbol(MO.getIndex());
154 Offset += MO.getOffset();
155 break;
157 default:
158 llvm_unreachable("<unknown operand type>");
161 const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, Kind, *Ctx);
163 if (Offset) {
164 // Note: Offset can also be negative
165 Expr = MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(Offset, *Ctx),
166 *Ctx);
169 if (IsGpOff)
170 Expr = MipsMCExpr::createGpOff(TargetKind, Expr, *Ctx);
171 else if (TargetKind != MipsMCExpr::MEK_None)
172 Expr = MipsMCExpr::create(TargetKind, Expr, *Ctx);
174 return MCOperand::createExpr(Expr);
177 MCOperand MipsMCInstLower::LowerOperand(const MachineOperand &MO,
178 int64_t offset) const {
179 MachineOperandType MOTy = MO.getType();
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;
201 return MCOperand();
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);
211 return MCOperand::createExpr(MipsMCExpr::create(Kind, Sub, *Ctx));
214 void MipsMCInstLower::
215 lowerLongBranchLUi(const MachineInstr *MI, MCInst &OutMI) const {
216 OutMI.setOpcode(Mips::LUi);
218 // Lower register operand.
219 OutMI.addOperand(LowerOperand(MI->getOperand(0)));
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");
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));
252 void MipsMCInstLower::lowerLongBranchADDiu(const MachineInstr *MI,
253 MCInst &OutMI, int Opcode) const {
254 OutMI.setOpcode(Opcode);
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");
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));
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));
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;
315 void MipsMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
316 if (lowerLongBranch(MI, OutMI))
317 return;
319 OutMI.setOpcode(MI->getOpcode());
321 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
322 const MachineOperand &MO = MI->getOperand(i);
323 MCOperand MCOp = LowerOperand(MO);
325 if (MCOp.isValid())
326 OutMI.addOperand(MCOp);