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