/src/llvm-project/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===-- RISCVMCCodeEmitter.cpp - Convert RISC-V code to machine code ------===// |
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 implements the RISCVMCCodeEmitter class. |
10 | | // |
11 | | //===----------------------------------------------------------------------===// |
12 | | |
13 | | #include "MCTargetDesc/RISCVBaseInfo.h" |
14 | | #include "MCTargetDesc/RISCVFixupKinds.h" |
15 | | #include "MCTargetDesc/RISCVMCExpr.h" |
16 | | #include "MCTargetDesc/RISCVMCTargetDesc.h" |
17 | | #include "llvm/ADT/Statistic.h" |
18 | | #include "llvm/MC/MCAsmInfo.h" |
19 | | #include "llvm/MC/MCCodeEmitter.h" |
20 | | #include "llvm/MC/MCContext.h" |
21 | | #include "llvm/MC/MCExpr.h" |
22 | | #include "llvm/MC/MCInst.h" |
23 | | #include "llvm/MC/MCInstBuilder.h" |
24 | | #include "llvm/MC/MCInstrInfo.h" |
25 | | #include "llvm/MC/MCRegisterInfo.h" |
26 | | #include "llvm/MC/MCSubtargetInfo.h" |
27 | | #include "llvm/MC/MCSymbol.h" |
28 | | #include "llvm/Support/Casting.h" |
29 | | #include "llvm/Support/EndianStream.h" |
30 | | #include "llvm/Support/raw_ostream.h" |
31 | | |
32 | | using namespace llvm; |
33 | | |
34 | | #define DEBUG_TYPE "mccodeemitter" |
35 | | |
36 | | STATISTIC(MCNumEmitted, "Number of MC instructions emitted"); |
37 | | STATISTIC(MCNumFixups, "Number of MC fixups created"); |
38 | | |
39 | | namespace { |
40 | | class RISCVMCCodeEmitter : public MCCodeEmitter { |
41 | | RISCVMCCodeEmitter(const RISCVMCCodeEmitter &) = delete; |
42 | | void operator=(const RISCVMCCodeEmitter &) = delete; |
43 | | MCContext &Ctx; |
44 | | MCInstrInfo const &MCII; |
45 | | |
46 | | public: |
47 | | RISCVMCCodeEmitter(MCContext &ctx, MCInstrInfo const &MCII) |
48 | 0 | : Ctx(ctx), MCII(MCII) {} |
49 | | |
50 | | ~RISCVMCCodeEmitter() override = default; |
51 | | |
52 | | void encodeInstruction(const MCInst &MI, SmallVectorImpl<char> &CB, |
53 | | SmallVectorImpl<MCFixup> &Fixups, |
54 | | const MCSubtargetInfo &STI) const override; |
55 | | |
56 | | void expandFunctionCall(const MCInst &MI, SmallVectorImpl<char> &CB, |
57 | | SmallVectorImpl<MCFixup> &Fixups, |
58 | | const MCSubtargetInfo &STI) const; |
59 | | |
60 | | void expandAddTPRel(const MCInst &MI, SmallVectorImpl<char> &CB, |
61 | | SmallVectorImpl<MCFixup> &Fixups, |
62 | | const MCSubtargetInfo &STI) const; |
63 | | |
64 | | void expandLongCondBr(const MCInst &MI, SmallVectorImpl<char> &CB, |
65 | | SmallVectorImpl<MCFixup> &Fixups, |
66 | | const MCSubtargetInfo &STI) const; |
67 | | |
68 | | /// TableGen'erated function for getting the binary encoding for an |
69 | | /// instruction. |
70 | | uint64_t getBinaryCodeForInstr(const MCInst &MI, |
71 | | SmallVectorImpl<MCFixup> &Fixups, |
72 | | const MCSubtargetInfo &STI) const; |
73 | | |
74 | | /// Return binary encoding of operand. If the machine operand requires |
75 | | /// relocation, record the relocation and return zero. |
76 | | unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO, |
77 | | SmallVectorImpl<MCFixup> &Fixups, |
78 | | const MCSubtargetInfo &STI) const; |
79 | | |
80 | | unsigned getImmOpValueAsr1(const MCInst &MI, unsigned OpNo, |
81 | | SmallVectorImpl<MCFixup> &Fixups, |
82 | | const MCSubtargetInfo &STI) const; |
83 | | |
84 | | unsigned getImmOpValue(const MCInst &MI, unsigned OpNo, |
85 | | SmallVectorImpl<MCFixup> &Fixups, |
86 | | const MCSubtargetInfo &STI) const; |
87 | | |
88 | | unsigned getVMaskReg(const MCInst &MI, unsigned OpNo, |
89 | | SmallVectorImpl<MCFixup> &Fixups, |
90 | | const MCSubtargetInfo &STI) const; |
91 | | |
92 | | unsigned getRlistOpValue(const MCInst &MI, unsigned OpNo, |
93 | | SmallVectorImpl<MCFixup> &Fixups, |
94 | | const MCSubtargetInfo &STI) const; |
95 | | |
96 | | unsigned getRegReg(const MCInst &MI, unsigned OpNo, |
97 | | SmallVectorImpl<MCFixup> &Fixups, |
98 | | const MCSubtargetInfo &STI) const; |
99 | | }; |
100 | | } // end anonymous namespace |
101 | | |
102 | | MCCodeEmitter *llvm::createRISCVMCCodeEmitter(const MCInstrInfo &MCII, |
103 | 0 | MCContext &Ctx) { |
104 | 0 | return new RISCVMCCodeEmitter(Ctx, MCII); |
105 | 0 | } |
106 | | |
107 | | // Expand PseudoCALL(Reg), PseudoTAIL and PseudoJump to AUIPC and JALR with |
108 | | // relocation types. We expand those pseudo-instructions while encoding them, |
109 | | // meaning AUIPC and JALR won't go through RISC-V MC to MC compressed |
110 | | // instruction transformation. This is acceptable because AUIPC has no 16-bit |
111 | | // form and C_JALR has no immediate operand field. We let linker relaxation |
112 | | // deal with it. When linker relaxation is enabled, AUIPC and JALR have a |
113 | | // chance to relax to JAL. |
114 | | // If the C extension is enabled, JAL has a chance relax to C_JAL. |
115 | | void RISCVMCCodeEmitter::expandFunctionCall(const MCInst &MI, |
116 | | SmallVectorImpl<char> &CB, |
117 | | SmallVectorImpl<MCFixup> &Fixups, |
118 | 0 | const MCSubtargetInfo &STI) const { |
119 | 0 | MCInst TmpInst; |
120 | 0 | MCOperand Func; |
121 | 0 | MCRegister Ra; |
122 | 0 | if (MI.getOpcode() == RISCV::PseudoTAIL) { |
123 | 0 | Func = MI.getOperand(0); |
124 | 0 | Ra = RISCV::X6; |
125 | 0 | } else if (MI.getOpcode() == RISCV::PseudoCALLReg) { |
126 | 0 | Func = MI.getOperand(1); |
127 | 0 | Ra = MI.getOperand(0).getReg(); |
128 | 0 | } else if (MI.getOpcode() == RISCV::PseudoCALL) { |
129 | 0 | Func = MI.getOperand(0); |
130 | 0 | Ra = RISCV::X1; |
131 | 0 | } else if (MI.getOpcode() == RISCV::PseudoJump) { |
132 | 0 | Func = MI.getOperand(1); |
133 | 0 | Ra = MI.getOperand(0).getReg(); |
134 | 0 | } |
135 | 0 | uint32_t Binary; |
136 | |
|
137 | 0 | assert(Func.isExpr() && "Expected expression"); |
138 | | |
139 | 0 | const MCExpr *CallExpr = Func.getExpr(); |
140 | | |
141 | | // Emit AUIPC Ra, Func with R_RISCV_CALL relocation type. |
142 | 0 | TmpInst = MCInstBuilder(RISCV::AUIPC).addReg(Ra).addExpr(CallExpr); |
143 | 0 | Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); |
144 | 0 | support::endian::write(CB, Binary, llvm::endianness::little); |
145 | |
|
146 | 0 | if (MI.getOpcode() == RISCV::PseudoTAIL || |
147 | 0 | MI.getOpcode() == RISCV::PseudoJump) |
148 | | // Emit JALR X0, Ra, 0 |
149 | 0 | TmpInst = MCInstBuilder(RISCV::JALR).addReg(RISCV::X0).addReg(Ra).addImm(0); |
150 | 0 | else |
151 | | // Emit JALR Ra, Ra, 0 |
152 | 0 | TmpInst = MCInstBuilder(RISCV::JALR).addReg(Ra).addReg(Ra).addImm(0); |
153 | 0 | Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); |
154 | 0 | support::endian::write(CB, Binary, llvm::endianness::little); |
155 | 0 | } |
156 | | |
157 | | // Expand PseudoAddTPRel to a simple ADD with the correct relocation. |
158 | | void RISCVMCCodeEmitter::expandAddTPRel(const MCInst &MI, |
159 | | SmallVectorImpl<char> &CB, |
160 | | SmallVectorImpl<MCFixup> &Fixups, |
161 | 0 | const MCSubtargetInfo &STI) const { |
162 | 0 | MCOperand DestReg = MI.getOperand(0); |
163 | 0 | MCOperand SrcReg = MI.getOperand(1); |
164 | 0 | MCOperand TPReg = MI.getOperand(2); |
165 | 0 | assert(TPReg.isReg() && TPReg.getReg() == RISCV::X4 && |
166 | 0 | "Expected thread pointer as second input to TP-relative add"); |
167 | | |
168 | 0 | MCOperand SrcSymbol = MI.getOperand(3); |
169 | 0 | assert(SrcSymbol.isExpr() && |
170 | 0 | "Expected expression as third input to TP-relative add"); |
171 | | |
172 | 0 | const RISCVMCExpr *Expr = dyn_cast<RISCVMCExpr>(SrcSymbol.getExpr()); |
173 | 0 | assert(Expr && Expr->getKind() == RISCVMCExpr::VK_RISCV_TPREL_ADD && |
174 | 0 | "Expected tprel_add relocation on TP-relative symbol"); |
175 | | |
176 | | // Emit the correct tprel_add relocation for the symbol. |
177 | 0 | Fixups.push_back(MCFixup::create( |
178 | 0 | 0, Expr, MCFixupKind(RISCV::fixup_riscv_tprel_add), MI.getLoc())); |
179 | | |
180 | | // Emit fixup_riscv_relax for tprel_add where the relax feature is enabled. |
181 | 0 | if (STI.hasFeature(RISCV::FeatureRelax)) { |
182 | 0 | const MCConstantExpr *Dummy = MCConstantExpr::create(0, Ctx); |
183 | 0 | Fixups.push_back(MCFixup::create( |
184 | 0 | 0, Dummy, MCFixupKind(RISCV::fixup_riscv_relax), MI.getLoc())); |
185 | 0 | } |
186 | | |
187 | | // Emit a normal ADD instruction with the given operands. |
188 | 0 | MCInst TmpInst = MCInstBuilder(RISCV::ADD) |
189 | 0 | .addOperand(DestReg) |
190 | 0 | .addOperand(SrcReg) |
191 | 0 | .addOperand(TPReg); |
192 | 0 | uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); |
193 | 0 | support::endian::write(CB, Binary, llvm::endianness::little); |
194 | 0 | } |
195 | | |
196 | 0 | static unsigned getInvertedBranchOp(unsigned BrOp) { |
197 | 0 | switch (BrOp) { |
198 | 0 | default: |
199 | 0 | llvm_unreachable("Unexpected branch opcode!"); |
200 | 0 | case RISCV::PseudoLongBEQ: |
201 | 0 | return RISCV::BNE; |
202 | 0 | case RISCV::PseudoLongBNE: |
203 | 0 | return RISCV::BEQ; |
204 | 0 | case RISCV::PseudoLongBLT: |
205 | 0 | return RISCV::BGE; |
206 | 0 | case RISCV::PseudoLongBGE: |
207 | 0 | return RISCV::BLT; |
208 | 0 | case RISCV::PseudoLongBLTU: |
209 | 0 | return RISCV::BGEU; |
210 | 0 | case RISCV::PseudoLongBGEU: |
211 | 0 | return RISCV::BLTU; |
212 | 0 | } |
213 | 0 | } |
214 | | |
215 | | // Expand PseudoLongBxx to an inverted conditional branch and an unconditional |
216 | | // jump. |
217 | | void RISCVMCCodeEmitter::expandLongCondBr(const MCInst &MI, |
218 | | SmallVectorImpl<char> &CB, |
219 | | SmallVectorImpl<MCFixup> &Fixups, |
220 | 0 | const MCSubtargetInfo &STI) const { |
221 | 0 | MCRegister SrcReg1 = MI.getOperand(0).getReg(); |
222 | 0 | MCRegister SrcReg2 = MI.getOperand(1).getReg(); |
223 | 0 | MCOperand SrcSymbol = MI.getOperand(2); |
224 | 0 | unsigned Opcode = MI.getOpcode(); |
225 | 0 | bool IsEqTest = |
226 | 0 | Opcode == RISCV::PseudoLongBNE || Opcode == RISCV::PseudoLongBEQ; |
227 | |
|
228 | 0 | bool UseCompressedBr = false; |
229 | 0 | if (IsEqTest && (STI.hasFeature(RISCV::FeatureStdExtC) || |
230 | 0 | STI.hasFeature(RISCV::FeatureStdExtZca))) { |
231 | 0 | if (RISCV::X8 <= SrcReg1.id() && SrcReg1.id() <= RISCV::X15 && |
232 | 0 | SrcReg2.id() == RISCV::X0) { |
233 | 0 | UseCompressedBr = true; |
234 | 0 | } else if (RISCV::X8 <= SrcReg2.id() && SrcReg2.id() <= RISCV::X15 && |
235 | 0 | SrcReg1.id() == RISCV::X0) { |
236 | 0 | std::swap(SrcReg1, SrcReg2); |
237 | 0 | UseCompressedBr = true; |
238 | 0 | } |
239 | 0 | } |
240 | |
|
241 | 0 | uint32_t Offset; |
242 | 0 | if (UseCompressedBr) { |
243 | 0 | unsigned InvOpc = |
244 | 0 | Opcode == RISCV::PseudoLongBNE ? RISCV::C_BEQZ : RISCV::C_BNEZ; |
245 | 0 | MCInst TmpInst = MCInstBuilder(InvOpc).addReg(SrcReg1).addImm(6); |
246 | 0 | uint16_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); |
247 | 0 | support::endian::write<uint16_t>(CB, Binary, llvm::endianness::little); |
248 | 0 | Offset = 2; |
249 | 0 | } else { |
250 | 0 | unsigned InvOpc = getInvertedBranchOp(Opcode); |
251 | 0 | MCInst TmpInst = |
252 | 0 | MCInstBuilder(InvOpc).addReg(SrcReg1).addReg(SrcReg2).addImm(8); |
253 | 0 | uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); |
254 | 0 | support::endian::write(CB, Binary, llvm::endianness::little); |
255 | 0 | Offset = 4; |
256 | 0 | } |
257 | | |
258 | | // Emit an unconditional jump to the destination. |
259 | 0 | MCInst TmpInst = |
260 | 0 | MCInstBuilder(RISCV::JAL).addReg(RISCV::X0).addOperand(SrcSymbol); |
261 | 0 | uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); |
262 | 0 | support::endian::write(CB, Binary, llvm::endianness::little); |
263 | |
|
264 | 0 | Fixups.clear(); |
265 | 0 | if (SrcSymbol.isExpr()) { |
266 | 0 | Fixups.push_back(MCFixup::create(Offset, SrcSymbol.getExpr(), |
267 | 0 | MCFixupKind(RISCV::fixup_riscv_jal), |
268 | 0 | MI.getLoc())); |
269 | 0 | } |
270 | 0 | } |
271 | | |
272 | | void RISCVMCCodeEmitter::encodeInstruction(const MCInst &MI, |
273 | | SmallVectorImpl<char> &CB, |
274 | | SmallVectorImpl<MCFixup> &Fixups, |
275 | 0 | const MCSubtargetInfo &STI) const { |
276 | 0 | const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); |
277 | | // Get byte count of instruction. |
278 | 0 | unsigned Size = Desc.getSize(); |
279 | | |
280 | | // RISCVInstrInfo::getInstSizeInBytes expects that the total size of the |
281 | | // expanded instructions for each pseudo is correct in the Size field of the |
282 | | // tablegen definition for the pseudo. |
283 | 0 | switch (MI.getOpcode()) { |
284 | 0 | default: |
285 | 0 | break; |
286 | 0 | case RISCV::PseudoCALLReg: |
287 | 0 | case RISCV::PseudoCALL: |
288 | 0 | case RISCV::PseudoTAIL: |
289 | 0 | case RISCV::PseudoJump: |
290 | 0 | expandFunctionCall(MI, CB, Fixups, STI); |
291 | 0 | MCNumEmitted += 2; |
292 | 0 | return; |
293 | 0 | case RISCV::PseudoAddTPRel: |
294 | 0 | expandAddTPRel(MI, CB, Fixups, STI); |
295 | 0 | MCNumEmitted += 1; |
296 | 0 | return; |
297 | 0 | case RISCV::PseudoLongBEQ: |
298 | 0 | case RISCV::PseudoLongBNE: |
299 | 0 | case RISCV::PseudoLongBLT: |
300 | 0 | case RISCV::PseudoLongBGE: |
301 | 0 | case RISCV::PseudoLongBLTU: |
302 | 0 | case RISCV::PseudoLongBGEU: |
303 | 0 | expandLongCondBr(MI, CB, Fixups, STI); |
304 | 0 | MCNumEmitted += 2; |
305 | 0 | return; |
306 | 0 | } |
307 | | |
308 | 0 | switch (Size) { |
309 | 0 | default: |
310 | 0 | llvm_unreachable("Unhandled encodeInstruction length!"); |
311 | 0 | case 2: { |
312 | 0 | uint16_t Bits = getBinaryCodeForInstr(MI, Fixups, STI); |
313 | 0 | support::endian::write<uint16_t>(CB, Bits, llvm::endianness::little); |
314 | 0 | break; |
315 | 0 | } |
316 | 0 | case 4: { |
317 | 0 | uint32_t Bits = getBinaryCodeForInstr(MI, Fixups, STI); |
318 | 0 | support::endian::write(CB, Bits, llvm::endianness::little); |
319 | 0 | break; |
320 | 0 | } |
321 | 0 | } |
322 | | |
323 | 0 | ++MCNumEmitted; // Keep track of the # of mi's emitted. |
324 | 0 | } |
325 | | |
326 | | unsigned |
327 | | RISCVMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO, |
328 | | SmallVectorImpl<MCFixup> &Fixups, |
329 | 0 | const MCSubtargetInfo &STI) const { |
330 | |
|
331 | 0 | if (MO.isReg()) |
332 | 0 | return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); |
333 | | |
334 | 0 | if (MO.isImm()) |
335 | 0 | return static_cast<unsigned>(MO.getImm()); |
336 | | |
337 | 0 | llvm_unreachable("Unhandled expression!"); |
338 | 0 | return 0; |
339 | 0 | } |
340 | | |
341 | | unsigned |
342 | | RISCVMCCodeEmitter::getImmOpValueAsr1(const MCInst &MI, unsigned OpNo, |
343 | | SmallVectorImpl<MCFixup> &Fixups, |
344 | 0 | const MCSubtargetInfo &STI) const { |
345 | 0 | const MCOperand &MO = MI.getOperand(OpNo); |
346 | |
|
347 | 0 | if (MO.isImm()) { |
348 | 0 | unsigned Res = MO.getImm(); |
349 | 0 | assert((Res & 1) == 0 && "LSB is non-zero"); |
350 | 0 | return Res >> 1; |
351 | 0 | } |
352 | | |
353 | 0 | return getImmOpValue(MI, OpNo, Fixups, STI); |
354 | 0 | } |
355 | | |
356 | | unsigned RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo, |
357 | | SmallVectorImpl<MCFixup> &Fixups, |
358 | 0 | const MCSubtargetInfo &STI) const { |
359 | 0 | bool EnableRelax = STI.hasFeature(RISCV::FeatureRelax); |
360 | 0 | const MCOperand &MO = MI.getOperand(OpNo); |
361 | |
|
362 | 0 | MCInstrDesc const &Desc = MCII.get(MI.getOpcode()); |
363 | 0 | unsigned MIFrm = RISCVII::getFormat(Desc.TSFlags); |
364 | | |
365 | | // If the destination is an immediate, there is nothing to do. |
366 | 0 | if (MO.isImm()) |
367 | 0 | return MO.getImm(); |
368 | | |
369 | 0 | assert(MO.isExpr() && |
370 | 0 | "getImmOpValue expects only expressions or immediates"); |
371 | 0 | const MCExpr *Expr = MO.getExpr(); |
372 | 0 | MCExpr::ExprKind Kind = Expr->getKind(); |
373 | 0 | RISCV::Fixups FixupKind = RISCV::fixup_riscv_invalid; |
374 | 0 | bool RelaxCandidate = false; |
375 | 0 | if (Kind == MCExpr::Target) { |
376 | 0 | const RISCVMCExpr *RVExpr = cast<RISCVMCExpr>(Expr); |
377 | |
|
378 | 0 | switch (RVExpr->getKind()) { |
379 | 0 | case RISCVMCExpr::VK_RISCV_None: |
380 | 0 | case RISCVMCExpr::VK_RISCV_Invalid: |
381 | 0 | case RISCVMCExpr::VK_RISCV_32_PCREL: |
382 | 0 | llvm_unreachable("Unhandled fixup kind!"); |
383 | 0 | case RISCVMCExpr::VK_RISCV_TPREL_ADD: |
384 | | // tprel_add is only used to indicate that a relocation should be emitted |
385 | | // for an add instruction used in TP-relative addressing. It should not be |
386 | | // expanded as if representing an actual instruction operand and so to |
387 | | // encounter it here is an error. |
388 | 0 | llvm_unreachable( |
389 | 0 | "VK_RISCV_TPREL_ADD should not represent an instruction operand"); |
390 | 0 | case RISCVMCExpr::VK_RISCV_LO: |
391 | 0 | if (MIFrm == RISCVII::InstFormatI) |
392 | 0 | FixupKind = RISCV::fixup_riscv_lo12_i; |
393 | 0 | else if (MIFrm == RISCVII::InstFormatS) |
394 | 0 | FixupKind = RISCV::fixup_riscv_lo12_s; |
395 | 0 | else |
396 | 0 | llvm_unreachable("VK_RISCV_LO used with unexpected instruction format"); |
397 | 0 | RelaxCandidate = true; |
398 | 0 | break; |
399 | 0 | case RISCVMCExpr::VK_RISCV_HI: |
400 | 0 | FixupKind = RISCV::fixup_riscv_hi20; |
401 | 0 | RelaxCandidate = true; |
402 | 0 | break; |
403 | 0 | case RISCVMCExpr::VK_RISCV_PCREL_LO: |
404 | 0 | if (MIFrm == RISCVII::InstFormatI) |
405 | 0 | FixupKind = RISCV::fixup_riscv_pcrel_lo12_i; |
406 | 0 | else if (MIFrm == RISCVII::InstFormatS) |
407 | 0 | FixupKind = RISCV::fixup_riscv_pcrel_lo12_s; |
408 | 0 | else |
409 | 0 | llvm_unreachable( |
410 | 0 | "VK_RISCV_PCREL_LO used with unexpected instruction format"); |
411 | 0 | RelaxCandidate = true; |
412 | 0 | break; |
413 | 0 | case RISCVMCExpr::VK_RISCV_PCREL_HI: |
414 | 0 | FixupKind = RISCV::fixup_riscv_pcrel_hi20; |
415 | 0 | RelaxCandidate = true; |
416 | 0 | break; |
417 | 0 | case RISCVMCExpr::VK_RISCV_GOT_HI: |
418 | 0 | FixupKind = RISCV::fixup_riscv_got_hi20; |
419 | 0 | break; |
420 | 0 | case RISCVMCExpr::VK_RISCV_TPREL_LO: |
421 | 0 | if (MIFrm == RISCVII::InstFormatI) |
422 | 0 | FixupKind = RISCV::fixup_riscv_tprel_lo12_i; |
423 | 0 | else if (MIFrm == RISCVII::InstFormatS) |
424 | 0 | FixupKind = RISCV::fixup_riscv_tprel_lo12_s; |
425 | 0 | else |
426 | 0 | llvm_unreachable( |
427 | 0 | "VK_RISCV_TPREL_LO used with unexpected instruction format"); |
428 | 0 | RelaxCandidate = true; |
429 | 0 | break; |
430 | 0 | case RISCVMCExpr::VK_RISCV_TPREL_HI: |
431 | 0 | FixupKind = RISCV::fixup_riscv_tprel_hi20; |
432 | 0 | RelaxCandidate = true; |
433 | 0 | break; |
434 | 0 | case RISCVMCExpr::VK_RISCV_TLS_GOT_HI: |
435 | 0 | FixupKind = RISCV::fixup_riscv_tls_got_hi20; |
436 | 0 | break; |
437 | 0 | case RISCVMCExpr::VK_RISCV_TLS_GD_HI: |
438 | 0 | FixupKind = RISCV::fixup_riscv_tls_gd_hi20; |
439 | 0 | break; |
440 | 0 | case RISCVMCExpr::VK_RISCV_CALL: |
441 | 0 | FixupKind = RISCV::fixup_riscv_call; |
442 | 0 | RelaxCandidate = true; |
443 | 0 | break; |
444 | 0 | case RISCVMCExpr::VK_RISCV_CALL_PLT: |
445 | 0 | FixupKind = RISCV::fixup_riscv_call_plt; |
446 | 0 | RelaxCandidate = true; |
447 | 0 | break; |
448 | 0 | } |
449 | 0 | } else if ((Kind == MCExpr::SymbolRef && |
450 | 0 | cast<MCSymbolRefExpr>(Expr)->getKind() == |
451 | 0 | MCSymbolRefExpr::VK_None) || |
452 | 0 | Kind == MCExpr::Binary) { |
453 | | // FIXME: Sub kind binary exprs have chance of underflow. |
454 | 0 | if (MIFrm == RISCVII::InstFormatJ) { |
455 | 0 | FixupKind = RISCV::fixup_riscv_jal; |
456 | 0 | } else if (MIFrm == RISCVII::InstFormatB) { |
457 | 0 | FixupKind = RISCV::fixup_riscv_branch; |
458 | 0 | } else if (MIFrm == RISCVII::InstFormatCJ) { |
459 | 0 | FixupKind = RISCV::fixup_riscv_rvc_jump; |
460 | 0 | } else if (MIFrm == RISCVII::InstFormatCB) { |
461 | 0 | FixupKind = RISCV::fixup_riscv_rvc_branch; |
462 | 0 | } else if (MIFrm == RISCVII::InstFormatI) { |
463 | 0 | FixupKind = RISCV::fixup_riscv_12_i; |
464 | 0 | } |
465 | 0 | } |
466 | | |
467 | 0 | assert(FixupKind != RISCV::fixup_riscv_invalid && "Unhandled expression!"); |
468 | | |
469 | 0 | Fixups.push_back( |
470 | 0 | MCFixup::create(0, Expr, MCFixupKind(FixupKind), MI.getLoc())); |
471 | 0 | ++MCNumFixups; |
472 | | |
473 | | // Ensure an R_RISCV_RELAX relocation will be emitted if linker relaxation is |
474 | | // enabled and the current fixup will result in a relocation that may be |
475 | | // relaxed. |
476 | 0 | if (EnableRelax && RelaxCandidate) { |
477 | 0 | const MCConstantExpr *Dummy = MCConstantExpr::create(0, Ctx); |
478 | 0 | Fixups.push_back( |
479 | 0 | MCFixup::create(0, Dummy, MCFixupKind(RISCV::fixup_riscv_relax), |
480 | 0 | MI.getLoc())); |
481 | 0 | ++MCNumFixups; |
482 | 0 | } |
483 | |
|
484 | 0 | return 0; |
485 | 0 | } |
486 | | |
487 | | unsigned RISCVMCCodeEmitter::getVMaskReg(const MCInst &MI, unsigned OpNo, |
488 | | SmallVectorImpl<MCFixup> &Fixups, |
489 | 0 | const MCSubtargetInfo &STI) const { |
490 | 0 | MCOperand MO = MI.getOperand(OpNo); |
491 | 0 | assert(MO.isReg() && "Expected a register."); |
492 | | |
493 | 0 | switch (MO.getReg()) { |
494 | 0 | default: |
495 | 0 | llvm_unreachable("Invalid mask register."); |
496 | 0 | case RISCV::V0: |
497 | 0 | return 0; |
498 | 0 | case RISCV::NoRegister: |
499 | 0 | return 1; |
500 | 0 | } |
501 | 0 | } |
502 | | |
503 | | unsigned RISCVMCCodeEmitter::getRlistOpValue(const MCInst &MI, unsigned OpNo, |
504 | | SmallVectorImpl<MCFixup> &Fixups, |
505 | 0 | const MCSubtargetInfo &STI) const { |
506 | 0 | const MCOperand &MO = MI.getOperand(OpNo); |
507 | 0 | assert(MO.isImm() && "Rlist operand must be immediate"); |
508 | 0 | auto Imm = MO.getImm(); |
509 | 0 | assert(Imm >= 4 && "EABI is currently not implemented"); |
510 | 0 | return Imm; |
511 | 0 | } |
512 | | |
513 | | unsigned RISCVMCCodeEmitter::getRegReg(const MCInst &MI, unsigned OpNo, |
514 | | SmallVectorImpl<MCFixup> &Fixups, |
515 | 0 | const MCSubtargetInfo &STI) const { |
516 | 0 | const MCOperand &MO = MI.getOperand(OpNo); |
517 | 0 | const MCOperand &MO1 = MI.getOperand(OpNo + 1); |
518 | 0 | assert(MO.isReg() && MO1.isReg() && "Expected registers."); |
519 | | |
520 | 0 | unsigned Op = Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); |
521 | 0 | unsigned Op1 = Ctx.getRegisterInfo()->getEncodingValue(MO1.getReg()); |
522 | |
|
523 | 0 | return Op | Op1 << 5; |
524 | 0 | } |
525 | | |
526 | | #include "RISCVGenMCCodeEmitter.inc" |