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
25using namespace llvm;
26
27MipsMCInstLower::MipsMCInstLower(MipsAsmPrinter &asmprinter)
28 : AsmPrinter(asmprinter) {}
29
30void MipsMCInstLower::Initialize(MCContext *C) {
31 Ctx = C;
32}
33
34MCOperand 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(GV: MO.getGlobal());
129 Offset += MO.getOffset();
130 break;
131
132 case MachineOperand::MO_BlockAddress:
133 Symbol = AsmPrinter.GetBlockAddressSymbol(BA: MO.getBlockAddress());
134 Offset += MO.getOffset();
135 break;
136
137 case MachineOperand::MO_ExternalSymbol:
138 Symbol = AsmPrinter.GetExternalSymbolSymbol(Sym: 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(JTID: MO.getIndex());
149 break;
150
151 case MachineOperand::MO_ConstantPoolIndex:
152 Symbol = AsmPrinter.GetCPISymbol(CPID: 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&: *Ctx);
161
162 if (Offset) {
163 // Note: Offset can also be negative
164 Expr = MCBinaryExpr::createAdd(LHS: Expr, RHS: MCConstantExpr::create(Value: Offset, Ctx&: *Ctx),
165 Ctx&: *Ctx);
166 }
167
168 if (IsGpOff)
169 Expr = MipsMCExpr::createGpOff(Kind: TargetKind, Expr, Ctx&: *Ctx);
170 else if (TargetKind != MipsMCExpr::MEK_None)
171 Expr = MipsMCExpr::create(Kind: TargetKind, Expr, Ctx&: *Ctx);
172
173 return MCOperand::createExpr(Val: Expr);
174}
175
176MCOperand 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(Reg: MO.getReg());
186 case MachineOperand::MO_Immediate:
187 return MCOperand::createImm(Val: 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: offset);
196 case MachineOperand::MO_RegisterMask:
197 break;
198 }
199
200 return MCOperand();
201}
202
203MCOperand MipsMCInstLower::createSub(MachineBasicBlock *BB1,
204 MachineBasicBlock *BB2,
205 MipsMCExpr::MipsExprKind Kind) const {
206 const MCSymbolRefExpr *Sym1 = MCSymbolRefExpr::create(Symbol: BB1->getSymbol(), Ctx&: *Ctx);
207 const MCSymbolRefExpr *Sym2 = MCSymbolRefExpr::create(Symbol: BB2->getSymbol(), Ctx&: *Ctx);
208 const MCBinaryExpr *Sub = MCBinaryExpr::createSub(LHS: Sym1, RHS: Sym2, Ctx&: *Ctx);
209
210 return MCOperand::createExpr(Val: MipsMCExpr::create(Kind, Expr: Sub, Ctx&: *Ctx));
211}
212
213void MipsMCInstLower::
214lowerLongBranchLUi(const MachineInstr *MI, MCInst &OutMI) const {
215 OutMI.setOpcode(Mips::LUi);
216
217 // Lower register operand.
218 OutMI.addOperand(Op: LowerOperand(MO: MI->getOperand(i: 0)));
219
220 MipsMCExpr::MipsExprKind Kind;
221 unsigned TargetFlags = MI->getOperand(i: 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(reason: "Unexpected flags for lowerLongBranchLUi");
237 }
238
239 if (MI->getNumOperands() == 2) {
240 const MCExpr *Expr =
241 MCSymbolRefExpr::create(Symbol: MI->getOperand(i: 1).getMBB()->getSymbol(), Ctx&: *Ctx);
242 const MipsMCExpr *MipsExpr = MipsMCExpr::create(Kind, Expr, Ctx&: *Ctx);
243 OutMI.addOperand(Op: MCOperand::createExpr(Val: MipsExpr));
244 } else if (MI->getNumOperands() == 3) {
245 // Create %hi($tgt-$baltgt).
246 OutMI.addOperand(Op: createSub(BB1: MI->getOperand(i: 1).getMBB(),
247 BB2: MI->getOperand(i: 2).getMBB(), Kind));
248 }
249}
250
251void 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(i: 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(reason: "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: I);
277 OutMI.addOperand(Op: LowerOperand(MO));
278 }
279
280 if (MI->getNumOperands() == 3) {
281 // Lower register operand.
282 const MCExpr *Expr =
283 MCSymbolRefExpr::create(Symbol: MI->getOperand(i: 2).getMBB()->getSymbol(), Ctx&: *Ctx);
284 const MipsMCExpr *MipsExpr = MipsMCExpr::create(Kind, Expr, Ctx&: *Ctx);
285 OutMI.addOperand(Op: MCOperand::createExpr(Val: MipsExpr));
286 } else if (MI->getNumOperands() == 4) {
287 // Create %lo($tgt-$baltgt) or %hi($tgt-$baltgt).
288 OutMI.addOperand(Op: createSub(BB1: MI->getOperand(i: 2).getMBB(),
289 BB2: MI->getOperand(i: 3).getMBB(), Kind));
290 }
291}
292
293bool 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, Opcode: Mips::ADDiu);
306 return true;
307 case Mips::LONG_BRANCH_DADDiu:
308 case Mips::LONG_BRANCH_DADDiu2Op:
309 lowerLongBranchADDiu(MI, OutMI, Opcode: Mips::DADDiu);
310 return true;
311 }
312}
313
314void 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(Op: MCOp);
325 }
326}
327