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