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(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 | |
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(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 | |
203 | MCOperand 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 | |
213 | void MipsMCInstLower:: |
214 | lowerLongBranchLUi(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 | |
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(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 | |
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, 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 | |
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(Op: MCOp); |
325 | } |
326 | } |
327 | |