xref: /freebsd/contrib/llvm-project/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp (revision e64bea71c21eb42e97aa615188ba91f6cce0d36d)
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/RISCVMCAsmInfo.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 
31 using namespace llvm;
32 
33 #define DEBUG_TYPE "mccodeemitter"
34 
35 STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
36 STATISTIC(MCNumFixups, "Number of MC fixups created");
37 
38 namespace {
39 class RISCVMCCodeEmitter : public MCCodeEmitter {
40   RISCVMCCodeEmitter(const RISCVMCCodeEmitter &) = delete;
41   void operator=(const RISCVMCCodeEmitter &) = delete;
42   MCContext &Ctx;
43   MCInstrInfo const &MCII;
44 
45 public:
RISCVMCCodeEmitter(MCContext & ctx,MCInstrInfo const & MCII)46   RISCVMCCodeEmitter(MCContext &ctx, MCInstrInfo const &MCII)
47       : Ctx(ctx), MCII(MCII) {}
48 
49   ~RISCVMCCodeEmitter() override = default;
50 
51   void encodeInstruction(const MCInst &MI, SmallVectorImpl<char> &CB,
52                          SmallVectorImpl<MCFixup> &Fixups,
53                          const MCSubtargetInfo &STI) const override;
54 
55   void expandFunctionCall(const MCInst &MI, SmallVectorImpl<char> &CB,
56                           SmallVectorImpl<MCFixup> &Fixups,
57                           const MCSubtargetInfo &STI) const;
58 
59   void expandTLSDESCCall(const MCInst &MI, SmallVectorImpl<char> &CB,
60                          SmallVectorImpl<MCFixup> &Fixups,
61                          const MCSubtargetInfo &STI) const;
62 
63   void expandAddTPRel(const MCInst &MI, SmallVectorImpl<char> &CB,
64                       SmallVectorImpl<MCFixup> &Fixups,
65                       const MCSubtargetInfo &STI) const;
66 
67   void expandLongCondBr(const MCInst &MI, SmallVectorImpl<char> &CB,
68                         SmallVectorImpl<MCFixup> &Fixups,
69                         const MCSubtargetInfo &STI) const;
70 
71   void expandQCLongCondBrImm(const MCInst &MI, SmallVectorImpl<char> &CB,
72                              SmallVectorImpl<MCFixup> &Fixups,
73                              const MCSubtargetInfo &STI, unsigned Size) const;
74 
75   /// TableGen'erated function for getting the binary encoding for an
76   /// instruction.
77   uint64_t getBinaryCodeForInstr(const MCInst &MI,
78                                  SmallVectorImpl<MCFixup> &Fixups,
79                                  const MCSubtargetInfo &STI) const;
80 
81   /// Return binary encoding of operand. If the machine operand requires
82   /// relocation, record the relocation and return zero.
83   uint64_t getMachineOpValue(const MCInst &MI, const MCOperand &MO,
84                              SmallVectorImpl<MCFixup> &Fixups,
85                              const MCSubtargetInfo &STI) const;
86 
87   uint64_t getImmOpValueMinus1(const MCInst &MI, unsigned OpNo,
88                                SmallVectorImpl<MCFixup> &Fixups,
89                                const MCSubtargetInfo &STI) const;
90 
91   uint64_t getImmOpValueSlist(const MCInst &MI, unsigned OpNo,
92                               SmallVectorImpl<MCFixup> &Fixups,
93                               const MCSubtargetInfo &STI) const;
94 
95   template <unsigned N>
96   unsigned getImmOpValueAsrN(const MCInst &MI, unsigned OpNo,
97                              SmallVectorImpl<MCFixup> &Fixups,
98                              const MCSubtargetInfo &STI) const;
99 
100   uint64_t getImmOpValue(const MCInst &MI, unsigned OpNo,
101                          SmallVectorImpl<MCFixup> &Fixups,
102                          const MCSubtargetInfo &STI) const;
103 
104   unsigned getVMaskReg(const MCInst &MI, unsigned OpNo,
105                        SmallVectorImpl<MCFixup> &Fixups,
106                        const MCSubtargetInfo &STI) const;
107 
108   unsigned getRlistOpValue(const MCInst &MI, unsigned OpNo,
109                            SmallVectorImpl<MCFixup> &Fixups,
110                            const MCSubtargetInfo &STI) const;
111 
112   unsigned getRlistS0OpValue(const MCInst &MI, unsigned OpNo,
113                              SmallVectorImpl<MCFixup> &Fixups,
114                              const MCSubtargetInfo &STI) const;
115 };
116 } // end anonymous namespace
117 
createRISCVMCCodeEmitter(const MCInstrInfo & MCII,MCContext & Ctx)118 MCCodeEmitter *llvm::createRISCVMCCodeEmitter(const MCInstrInfo &MCII,
119                                               MCContext &Ctx) {
120   return new RISCVMCCodeEmitter(Ctx, MCII);
121 }
122 
addFixup(SmallVectorImpl<MCFixup> & Fixups,uint32_t Offset,const MCExpr * Value,uint16_t Kind)123 static void addFixup(SmallVectorImpl<MCFixup> &Fixups, uint32_t Offset,
124                      const MCExpr *Value, uint16_t Kind) {
125   bool PCRel = false;
126   switch (Kind) {
127   case ELF::R_RISCV_CALL_PLT:
128   case RISCV::fixup_riscv_pcrel_hi20:
129   case RISCV::fixup_riscv_pcrel_lo12_i:
130   case RISCV::fixup_riscv_pcrel_lo12_s:
131   case RISCV::fixup_riscv_jal:
132   case RISCV::fixup_riscv_branch:
133   case RISCV::fixup_riscv_rvc_jump:
134   case RISCV::fixup_riscv_rvc_branch:
135   case RISCV::fixup_riscv_call:
136   case RISCV::fixup_riscv_call_plt:
137   case RISCV::fixup_riscv_qc_e_branch:
138   case RISCV::fixup_riscv_qc_e_call_plt:
139   case RISCV::fixup_riscv_nds_branch_10:
140     PCRel = true;
141   }
142   Fixups.push_back(MCFixup::create(Offset, Value, Kind, PCRel));
143 }
144 
145 // Expand PseudoCALL(Reg), PseudoTAIL and PseudoJump to AUIPC and JALR with
146 // relocation types. We expand those pseudo-instructions while encoding them,
147 // meaning AUIPC and JALR won't go through RISC-V MC to MC compressed
148 // instruction transformation. This is acceptable because AUIPC has no 16-bit
149 // form and C_JALR has no immediate operand field.  We let linker relaxation
150 // deal with it. When linker relaxation is enabled, AUIPC and JALR have a
151 // chance to relax to JAL.
152 // If the C extension is enabled, JAL has a chance relax to C_JAL.
expandFunctionCall(const MCInst & MI,SmallVectorImpl<char> & CB,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const153 void RISCVMCCodeEmitter::expandFunctionCall(const MCInst &MI,
154                                             SmallVectorImpl<char> &CB,
155                                             SmallVectorImpl<MCFixup> &Fixups,
156                                             const MCSubtargetInfo &STI) const {
157   MCInst TmpInst;
158   MCOperand Func;
159   MCRegister Ra;
160   if (MI.getOpcode() == RISCV::PseudoTAIL) {
161     Func = MI.getOperand(0);
162     Ra = RISCVII::getTailExpandUseRegNo(STI.getFeatureBits());
163   } else if (MI.getOpcode() == RISCV::PseudoCALLReg) {
164     Func = MI.getOperand(1);
165     Ra = MI.getOperand(0).getReg();
166   } else if (MI.getOpcode() == RISCV::PseudoCALL) {
167     Func = MI.getOperand(0);
168     Ra = RISCV::X1;
169   } else if (MI.getOpcode() == RISCV::PseudoJump) {
170     Func = MI.getOperand(1);
171     Ra = MI.getOperand(0).getReg();
172   }
173   uint32_t Binary;
174 
175   assert(Func.isExpr() && "Expected expression");
176 
177   const MCExpr *CallExpr = Func.getExpr();
178 
179   // Emit AUIPC Ra, Func with R_RISCV_CALL relocation type.
180   TmpInst = MCInstBuilder(RISCV::AUIPC).addReg(Ra).addExpr(CallExpr);
181   Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
182   support::endian::write(CB, Binary, llvm::endianness::little);
183 
184   if (MI.getOpcode() == RISCV::PseudoTAIL ||
185       MI.getOpcode() == RISCV::PseudoJump)
186     // Emit JALR X0, Ra, 0
187     TmpInst = MCInstBuilder(RISCV::JALR).addReg(RISCV::X0).addReg(Ra).addImm(0);
188   else
189     // Emit JALR Ra, Ra, 0
190     TmpInst = MCInstBuilder(RISCV::JALR).addReg(Ra).addReg(Ra).addImm(0);
191   Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
192   support::endian::write(CB, Binary, llvm::endianness::little);
193 }
194 
expandTLSDESCCall(const MCInst & MI,SmallVectorImpl<char> & CB,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const195 void RISCVMCCodeEmitter::expandTLSDESCCall(const MCInst &MI,
196                                            SmallVectorImpl<char> &CB,
197                                            SmallVectorImpl<MCFixup> &Fixups,
198                                            const MCSubtargetInfo &STI) const {
199   MCOperand SrcSymbol = MI.getOperand(3);
200   assert(SrcSymbol.isExpr() &&
201          "Expected expression as first input to TLSDESCCALL");
202   const auto *Expr = dyn_cast<MCSpecifierExpr>(SrcSymbol.getExpr());
203   MCRegister Link = MI.getOperand(0).getReg();
204   MCRegister Dest = MI.getOperand(1).getReg();
205   int64_t Imm = MI.getOperand(2).getImm();
206   addFixup(Fixups, 0, Expr, ELF::R_RISCV_TLSDESC_CALL);
207   MCInst Call =
208       MCInstBuilder(RISCV::JALR).addReg(Link).addReg(Dest).addImm(Imm);
209 
210   uint32_t Binary = getBinaryCodeForInstr(Call, Fixups, STI);
211   support::endian::write(CB, Binary, llvm::endianness::little);
212 }
213 
214 // Expand PseudoAddTPRel to a simple ADD with the correct relocation.
expandAddTPRel(const MCInst & MI,SmallVectorImpl<char> & CB,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const215 void RISCVMCCodeEmitter::expandAddTPRel(const MCInst &MI,
216                                         SmallVectorImpl<char> &CB,
217                                         SmallVectorImpl<MCFixup> &Fixups,
218                                         const MCSubtargetInfo &STI) const {
219   MCOperand DestReg = MI.getOperand(0);
220   MCOperand SrcReg = MI.getOperand(1);
221   MCOperand TPReg = MI.getOperand(2);
222   assert(TPReg.isReg() && TPReg.getReg() == RISCV::X4 &&
223          "Expected thread pointer as second input to TP-relative add");
224 
225   MCOperand SrcSymbol = MI.getOperand(3);
226   assert(SrcSymbol.isExpr() &&
227          "Expected expression as third input to TP-relative add");
228 
229   const auto *Expr = dyn_cast<MCSpecifierExpr>(SrcSymbol.getExpr());
230   assert(Expr && Expr->getSpecifier() == ELF::R_RISCV_TPREL_ADD &&
231          "Expected tprel_add relocation on TP-relative symbol");
232 
233   addFixup(Fixups, 0, Expr, ELF::R_RISCV_TPREL_ADD);
234   if (STI.hasFeature(RISCV::FeatureRelax))
235     Fixups.back().setLinkerRelaxable();
236 
237   // Emit a normal ADD instruction with the given operands.
238   MCInst TmpInst = MCInstBuilder(RISCV::ADD)
239                        .addOperand(DestReg)
240                        .addOperand(SrcReg)
241                        .addOperand(TPReg);
242   uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
243   support::endian::write(CB, Binary, llvm::endianness::little);
244 }
245 
getInvertedBranchOp(unsigned BrOp)246 static unsigned getInvertedBranchOp(unsigned BrOp) {
247   switch (BrOp) {
248   default:
249     llvm_unreachable("Unexpected branch opcode!");
250   case RISCV::PseudoLongBEQ:
251     return RISCV::BNE;
252   case RISCV::PseudoLongBNE:
253     return RISCV::BEQ;
254   case RISCV::PseudoLongBLT:
255     return RISCV::BGE;
256   case RISCV::PseudoLongBGE:
257     return RISCV::BLT;
258   case RISCV::PseudoLongBLTU:
259     return RISCV::BGEU;
260   case RISCV::PseudoLongBGEU:
261     return RISCV::BLTU;
262   case RISCV::PseudoLongQC_BEQI:
263     return RISCV::QC_BNEI;
264   case RISCV::PseudoLongQC_BNEI:
265     return RISCV::QC_BEQI;
266   case RISCV::PseudoLongQC_BLTI:
267     return RISCV::QC_BGEI;
268   case RISCV::PseudoLongQC_BGEI:
269     return RISCV::QC_BLTI;
270   case RISCV::PseudoLongQC_BLTUI:
271     return RISCV::QC_BGEUI;
272   case RISCV::PseudoLongQC_BGEUI:
273     return RISCV::QC_BLTUI;
274   case RISCV::PseudoLongQC_E_BEQI:
275     return RISCV::QC_E_BNEI;
276   case RISCV::PseudoLongQC_E_BNEI:
277     return RISCV::QC_E_BEQI;
278   case RISCV::PseudoLongQC_E_BLTI:
279     return RISCV::QC_E_BGEI;
280   case RISCV::PseudoLongQC_E_BGEI:
281     return RISCV::QC_E_BLTI;
282   case RISCV::PseudoLongQC_E_BLTUI:
283     return RISCV::QC_E_BGEUI;
284   case RISCV::PseudoLongQC_E_BGEUI:
285     return RISCV::QC_E_BLTUI;
286   }
287 }
288 
289 // Expand PseudoLongBxx to an inverted conditional branch and an unconditional
290 // jump.
expandLongCondBr(const MCInst & MI,SmallVectorImpl<char> & CB,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const291 void RISCVMCCodeEmitter::expandLongCondBr(const MCInst &MI,
292                                           SmallVectorImpl<char> &CB,
293                                           SmallVectorImpl<MCFixup> &Fixups,
294                                           const MCSubtargetInfo &STI) const {
295   MCRegister SrcReg1 = MI.getOperand(0).getReg();
296   MCRegister SrcReg2 = MI.getOperand(1).getReg();
297   MCOperand SrcSymbol = MI.getOperand(2);
298   unsigned Opcode = MI.getOpcode();
299   bool IsEqTest =
300       Opcode == RISCV::PseudoLongBNE || Opcode == RISCV::PseudoLongBEQ;
301 
302   bool UseCompressedBr = false;
303   if (IsEqTest && STI.hasFeature(RISCV::FeatureStdExtZca)) {
304     if (RISCV::X8 <= SrcReg1.id() && SrcReg1.id() <= RISCV::X15 &&
305         SrcReg2.id() == RISCV::X0) {
306       UseCompressedBr = true;
307     } else if (RISCV::X8 <= SrcReg2.id() && SrcReg2.id() <= RISCV::X15 &&
308                SrcReg1.id() == RISCV::X0) {
309       std::swap(SrcReg1, SrcReg2);
310       UseCompressedBr = true;
311     }
312   }
313 
314   uint32_t Offset;
315   if (UseCompressedBr) {
316     unsigned InvOpc =
317         Opcode == RISCV::PseudoLongBNE ? RISCV::C_BEQZ : RISCV::C_BNEZ;
318     MCInst TmpInst = MCInstBuilder(InvOpc).addReg(SrcReg1).addImm(6);
319     uint16_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
320     support::endian::write<uint16_t>(CB, Binary, llvm::endianness::little);
321     Offset = 2;
322   } else {
323     unsigned InvOpc = getInvertedBranchOp(Opcode);
324     MCInst TmpInst =
325         MCInstBuilder(InvOpc).addReg(SrcReg1).addReg(SrcReg2).addImm(8);
326     uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
327     support::endian::write(CB, Binary, llvm::endianness::little);
328     Offset = 4;
329   }
330 
331   // Save the number fixups.
332   size_t FixupStartIndex = Fixups.size();
333 
334   // Emit an unconditional jump to the destination.
335   MCInst TmpInst =
336       MCInstBuilder(RISCV::JAL).addReg(RISCV::X0).addOperand(SrcSymbol);
337   uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
338   support::endian::write(CB, Binary, llvm::endianness::little);
339 
340   // Drop any fixup added so we can add the correct one.
341   Fixups.resize(FixupStartIndex);
342 
343   if (SrcSymbol.isExpr())
344     addFixup(Fixups, Offset, SrcSymbol.getExpr(), RISCV::fixup_riscv_jal);
345 }
346 
347 // Expand PseudoLongQC_(E_)Bxxx to an inverted conditional branch and an
348 // unconditional jump.
expandQCLongCondBrImm(const MCInst & MI,SmallVectorImpl<char> & CB,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI,unsigned Size) const349 void RISCVMCCodeEmitter::expandQCLongCondBrImm(const MCInst &MI,
350                                                SmallVectorImpl<char> &CB,
351                                                SmallVectorImpl<MCFixup> &Fixups,
352                                                const MCSubtargetInfo &STI,
353                                                unsigned Size) const {
354   MCRegister SrcReg1 = MI.getOperand(0).getReg();
355   auto BrImm = MI.getOperand(1).getImm();
356   MCOperand SrcSymbol = MI.getOperand(2);
357   unsigned Opcode = MI.getOpcode();
358   uint32_t Offset;
359   unsigned InvOpc = getInvertedBranchOp(Opcode);
360   // Emit inverted conditional branch with offset:
361   // 8 (QC.BXXX(4) + JAL(4))
362   // or
363   // 10 (QC.E.BXXX(6) + JAL(4)).
364   if (Size == 4) {
365     MCInst TmpBr =
366         MCInstBuilder(InvOpc).addReg(SrcReg1).addImm(BrImm).addImm(8);
367     uint32_t BrBinary = getBinaryCodeForInstr(TmpBr, Fixups, STI);
368     support::endian::write(CB, BrBinary, llvm::endianness::little);
369   } else {
370     MCInst TmpBr =
371         MCInstBuilder(InvOpc).addReg(SrcReg1).addImm(BrImm).addImm(10);
372     uint64_t BrBinary =
373         getBinaryCodeForInstr(TmpBr, Fixups, STI) & 0xffff'ffff'ffffu;
374     SmallVector<char, 8> Encoding;
375     support::endian::write(Encoding, BrBinary, llvm::endianness::little);
376     assert(Encoding[6] == 0 && Encoding[7] == 0 &&
377            "Unexpected encoding for 48-bit instruction");
378     Encoding.truncate(6);
379     CB.append(Encoding);
380   }
381   Offset = Size;
382   // Save the number fixups.
383   size_t FixupStartIndex = Fixups.size();
384   // Emit an unconditional jump to the destination.
385   MCInst TmpJ =
386       MCInstBuilder(RISCV::JAL).addReg(RISCV::X0).addOperand(SrcSymbol);
387   uint32_t JBinary = getBinaryCodeForInstr(TmpJ, Fixups, STI);
388   support::endian::write(CB, JBinary, llvm::endianness::little);
389   // Drop any fixup added so we can add the correct one.
390   Fixups.resize(FixupStartIndex);
391   if (SrcSymbol.isExpr())
392     addFixup(Fixups, Offset, SrcSymbol.getExpr(), RISCV::fixup_riscv_jal);
393 }
394 
encodeInstruction(const MCInst & MI,SmallVectorImpl<char> & CB,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const395 void RISCVMCCodeEmitter::encodeInstruction(const MCInst &MI,
396                                            SmallVectorImpl<char> &CB,
397                                            SmallVectorImpl<MCFixup> &Fixups,
398                                            const MCSubtargetInfo &STI) const {
399   const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
400   // Get byte count of instruction.
401   unsigned Size = Desc.getSize();
402 
403   // RISCVInstrInfo::getInstSizeInBytes expects that the total size of the
404   // expanded instructions for each pseudo is correct in the Size field of the
405   // tablegen definition for the pseudo.
406   switch (MI.getOpcode()) {
407   default:
408     break;
409   case RISCV::PseudoCALLReg:
410   case RISCV::PseudoCALL:
411   case RISCV::PseudoTAIL:
412   case RISCV::PseudoJump:
413     expandFunctionCall(MI, CB, Fixups, STI);
414     MCNumEmitted += 2;
415     return;
416   case RISCV::PseudoAddTPRel:
417     expandAddTPRel(MI, CB, Fixups, STI);
418     MCNumEmitted += 1;
419     return;
420   case RISCV::PseudoLongBEQ:
421   case RISCV::PseudoLongBNE:
422   case RISCV::PseudoLongBLT:
423   case RISCV::PseudoLongBGE:
424   case RISCV::PseudoLongBLTU:
425   case RISCV::PseudoLongBGEU:
426     expandLongCondBr(MI, CB, Fixups, STI);
427     MCNumEmitted += 2;
428     return;
429   case RISCV::PseudoLongQC_BEQI:
430   case RISCV::PseudoLongQC_BNEI:
431   case RISCV::PseudoLongQC_BLTI:
432   case RISCV::PseudoLongQC_BGEI:
433   case RISCV::PseudoLongQC_BLTUI:
434   case RISCV::PseudoLongQC_BGEUI:
435     expandQCLongCondBrImm(MI, CB, Fixups, STI, 4);
436     MCNumEmitted += 2;
437     return;
438   case RISCV::PseudoLongQC_E_BEQI:
439   case RISCV::PseudoLongQC_E_BNEI:
440   case RISCV::PseudoLongQC_E_BLTI:
441   case RISCV::PseudoLongQC_E_BGEI:
442   case RISCV::PseudoLongQC_E_BLTUI:
443   case RISCV::PseudoLongQC_E_BGEUI:
444     expandQCLongCondBrImm(MI, CB, Fixups, STI, 6);
445     MCNumEmitted += 2;
446     return;
447   case RISCV::PseudoTLSDESCCall:
448     expandTLSDESCCall(MI, CB, Fixups, STI);
449     MCNumEmitted += 1;
450     return;
451   }
452 
453   switch (Size) {
454   default:
455     llvm_unreachable("Unhandled encodeInstruction length!");
456   case 2: {
457     uint16_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
458     support::endian::write<uint16_t>(CB, Bits, llvm::endianness::little);
459     break;
460   }
461   case 4: {
462     uint32_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
463     support::endian::write(CB, Bits, llvm::endianness::little);
464     break;
465   }
466   case 6: {
467     uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI) & 0xffff'ffff'ffffu;
468     SmallVector<char, 8> Encoding;
469     support::endian::write(Encoding, Bits, llvm::endianness::little);
470     assert(Encoding[6] == 0 && Encoding[7] == 0 &&
471            "Unexpected encoding for 48-bit instruction");
472     Encoding.truncate(6);
473     CB.append(Encoding);
474     break;
475   }
476   case 8: {
477     uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
478     support::endian::write(CB, Bits, llvm::endianness::little);
479     break;
480   }
481   }
482 
483   ++MCNumEmitted; // Keep track of the # of mi's emitted.
484 }
485 
486 uint64_t
getMachineOpValue(const MCInst & MI,const MCOperand & MO,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const487 RISCVMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
488                                       SmallVectorImpl<MCFixup> &Fixups,
489                                       const MCSubtargetInfo &STI) const {
490 
491   if (MO.isReg())
492     return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
493 
494   if (MO.isImm())
495     return MO.getImm();
496 
497   llvm_unreachable("Unhandled expression!");
498   return 0;
499 }
500 
501 uint64_t
getImmOpValueMinus1(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const502 RISCVMCCodeEmitter::getImmOpValueMinus1(const MCInst &MI, unsigned OpNo,
503                                         SmallVectorImpl<MCFixup> &Fixups,
504                                         const MCSubtargetInfo &STI) const {
505   const MCOperand &MO = MI.getOperand(OpNo);
506 
507   if (MO.isImm()) {
508     uint64_t Res = MO.getImm();
509     return (Res - 1);
510   }
511 
512   llvm_unreachable("Unhandled expression!");
513   return 0;
514 }
515 
516 uint64_t
getImmOpValueSlist(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const517 RISCVMCCodeEmitter::getImmOpValueSlist(const MCInst &MI, unsigned OpNo,
518                                        SmallVectorImpl<MCFixup> &Fixups,
519                                        const MCSubtargetInfo &STI) const {
520   const MCOperand &MO = MI.getOperand(OpNo);
521   assert(MO.isImm() && "Slist operand must be immediate");
522 
523   uint64_t Res = MO.getImm();
524   switch (Res) {
525   case 0:
526     return 0;
527   case 1:
528     return 1;
529   case 2:
530     return 2;
531   case 4:
532     return 3;
533   case 8:
534     return 4;
535   case 16:
536     return 5;
537   case 15:
538     return 6;
539   case 31:
540     return 7;
541   default:
542     llvm_unreachable("Unhandled Slist value!");
543   }
544 }
545 
546 template <unsigned N>
547 unsigned
getImmOpValueAsrN(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const548 RISCVMCCodeEmitter::getImmOpValueAsrN(const MCInst &MI, unsigned OpNo,
549                                       SmallVectorImpl<MCFixup> &Fixups,
550                                       const MCSubtargetInfo &STI) const {
551   const MCOperand &MO = MI.getOperand(OpNo);
552 
553   if (MO.isImm()) {
554     uint64_t Res = MO.getImm();
555     assert((Res & ((1 << N) - 1)) == 0 && "LSB is non-zero");
556     return Res >> N;
557   }
558 
559   return getImmOpValue(MI, OpNo, Fixups, STI);
560 }
561 
getImmOpValue(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const562 uint64_t RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo,
563                                            SmallVectorImpl<MCFixup> &Fixups,
564                                            const MCSubtargetInfo &STI) const {
565   bool EnableRelax = STI.hasFeature(RISCV::FeatureRelax);
566   const MCOperand &MO = MI.getOperand(OpNo);
567 
568   MCInstrDesc const &Desc = MCII.get(MI.getOpcode());
569   unsigned MIFrm = RISCVII::getFormat(Desc.TSFlags);
570 
571   // If the destination is an immediate, there is nothing to do.
572   if (MO.isImm())
573     return MO.getImm();
574 
575   assert(MO.isExpr() &&
576          "getImmOpValue expects only expressions or immediates");
577   const MCExpr *Expr = MO.getExpr();
578   MCExpr::ExprKind Kind = Expr->getKind();
579 
580   // `RelaxCandidate` must be set to `true` in two cases:
581   // - The fixup's relocation gets a R_RISCV_RELAX relocation
582   // - The underlying instruction may be relaxed to an instruction that gets a
583   //   `R_RISCV_RELAX` relocation.
584   //
585   // The actual emission of `R_RISCV_RELAX` will be handled in
586   // `RISCVAsmBackend::applyFixup`.
587   bool RelaxCandidate = false;
588   auto AsmRelaxToLinkerRelaxableWithFeature = [&](unsigned Feature) -> void {
589     if (!STI.hasFeature(RISCV::FeatureExactAssembly) && STI.hasFeature(Feature))
590       RelaxCandidate = true;
591   };
592 
593   unsigned FixupKind = RISCV::fixup_riscv_invalid;
594   if (Kind == MCExpr::Specifier) {
595     const auto *RVExpr = cast<MCSpecifierExpr>(Expr);
596     FixupKind = RVExpr->getSpecifier();
597     switch (RVExpr->getSpecifier()) {
598     default:
599       assert(FixupKind && FixupKind < FirstTargetFixupKind &&
600              "invalid specifier");
601       break;
602     case ELF::R_RISCV_TPREL_ADD:
603       // tprel_add is only used to indicate that a relocation should be emitted
604       // for an add instruction used in TP-relative addressing. It should not be
605       // expanded as if representing an actual instruction operand and so to
606       // encounter it here is an error.
607       llvm_unreachable(
608           "ELF::R_RISCV_TPREL_ADD should not represent an instruction operand");
609     case RISCV::S_LO:
610       if (MIFrm == RISCVII::InstFormatI)
611         FixupKind = RISCV::fixup_riscv_lo12_i;
612       else if (MIFrm == RISCVII::InstFormatS)
613         FixupKind = RISCV::fixup_riscv_lo12_s;
614       else
615         llvm_unreachable("VK_LO used with unexpected instruction format");
616       RelaxCandidate = true;
617       break;
618     case ELF::R_RISCV_HI20:
619       FixupKind = RISCV::fixup_riscv_hi20;
620       RelaxCandidate = true;
621       break;
622     case RISCV::S_PCREL_LO:
623       if (MIFrm == RISCVII::InstFormatI)
624         FixupKind = RISCV::fixup_riscv_pcrel_lo12_i;
625       else if (MIFrm == RISCVII::InstFormatS)
626         FixupKind = RISCV::fixup_riscv_pcrel_lo12_s;
627       else
628         llvm_unreachable("VK_PCREL_LO used with unexpected instruction format");
629       RelaxCandidate = true;
630       break;
631     case ELF::R_RISCV_PCREL_HI20:
632       FixupKind = RISCV::fixup_riscv_pcrel_hi20;
633       RelaxCandidate = true;
634       break;
635     case RISCV::S_TPREL_LO:
636       if (MIFrm == RISCVII::InstFormatI)
637         FixupKind = ELF::R_RISCV_TPREL_LO12_I;
638       else if (MIFrm == RISCVII::InstFormatS)
639         FixupKind = ELF::R_RISCV_TPREL_LO12_S;
640       else
641         llvm_unreachable("VK_TPREL_LO used with unexpected instruction format");
642       RelaxCandidate = true;
643       break;
644     case ELF::R_RISCV_TPREL_HI20:
645       RelaxCandidate = true;
646       break;
647     case ELF::R_RISCV_CALL_PLT:
648       FixupKind = RISCV::fixup_riscv_call_plt;
649       RelaxCandidate = true;
650       break;
651     case RISCV::S_QC_ABS20:
652       FixupKind = RISCV::fixup_riscv_qc_abs20_u;
653       RelaxCandidate = true;
654       break;
655     }
656   } else if (Kind == MCExpr::SymbolRef || Kind == MCExpr::Binary) {
657     // FIXME: Sub kind binary exprs have chance of underflow.
658     if (MIFrm == RISCVII::InstFormatJ) {
659       FixupKind = RISCV::fixup_riscv_jal;
660       AsmRelaxToLinkerRelaxableWithFeature(RISCV::FeatureVendorXqcilb);
661     } else if (MIFrm == RISCVII::InstFormatB) {
662       FixupKind = RISCV::fixup_riscv_branch;
663       // This might be assembler relaxed to `b<cc>; jal` but we cannot relax
664       // the `jal` again in the assembler.
665     } else if (MIFrm == RISCVII::InstFormatCJ) {
666       FixupKind = RISCV::fixup_riscv_rvc_jump;
667       AsmRelaxToLinkerRelaxableWithFeature(RISCV::FeatureVendorXqcilb);
668     } else if (MIFrm == RISCVII::InstFormatCB) {
669       FixupKind = RISCV::fixup_riscv_rvc_branch;
670       // This might be assembler relaxed to `b<cc>; jal` but we cannot relax
671       // the `jal` again in the assembler.
672     } else if (MIFrm == RISCVII::InstFormatCI) {
673       FixupKind = RISCV::fixup_riscv_rvc_imm;
674     } else if (MIFrm == RISCVII::InstFormatI) {
675       FixupKind = RISCV::fixup_riscv_12_i;
676     } else if (MIFrm == RISCVII::InstFormatQC_EB) {
677       FixupKind = RISCV::fixup_riscv_qc_e_branch;
678       // This might be assembler relaxed to `qc.e.b<cc>; jal` but we cannot
679       // relax the `jal` again in the assembler.
680     } else if (MIFrm == RISCVII::InstFormatQC_EAI) {
681       FixupKind = RISCV::fixup_riscv_qc_e_32;
682       RelaxCandidate = true;
683     } else if (MIFrm == RISCVII::InstFormatQC_EJ) {
684       FixupKind = RISCV::fixup_riscv_qc_e_call_plt;
685       RelaxCandidate = true;
686     } else if (MIFrm == RISCVII::InstFormatNDS_BRANCH_10) {
687       FixupKind = RISCV::fixup_riscv_nds_branch_10;
688     }
689   }
690 
691   assert(FixupKind != RISCV::fixup_riscv_invalid && "Unhandled expression!");
692 
693   addFixup(Fixups, 0, Expr, FixupKind);
694   // If linker relaxation is enabled and supported by this relocation, set a bit
695   // so that the assembler knows the size of the instruction is not fixed/known,
696   // and the relocation will need a R_RISCV_RELAX relocation.
697   if (EnableRelax && RelaxCandidate)
698     Fixups.back().setLinkerRelaxable();
699   ++MCNumFixups;
700 
701   return 0;
702 }
703 
getVMaskReg(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const704 unsigned RISCVMCCodeEmitter::getVMaskReg(const MCInst &MI, unsigned OpNo,
705                                          SmallVectorImpl<MCFixup> &Fixups,
706                                          const MCSubtargetInfo &STI) const {
707   MCOperand MO = MI.getOperand(OpNo);
708   assert(MO.isReg() && "Expected a register.");
709 
710   switch (MO.getReg()) {
711   default:
712     llvm_unreachable("Invalid mask register.");
713   case RISCV::V0:
714     return 0;
715   case RISCV::NoRegister:
716     return 1;
717   }
718 }
719 
getRlistOpValue(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const720 unsigned RISCVMCCodeEmitter::getRlistOpValue(const MCInst &MI, unsigned OpNo,
721                                              SmallVectorImpl<MCFixup> &Fixups,
722                                              const MCSubtargetInfo &STI) const {
723   const MCOperand &MO = MI.getOperand(OpNo);
724   assert(MO.isImm() && "Rlist operand must be immediate");
725   auto Imm = MO.getImm();
726   assert(Imm >= 4 && "EABI is currently not implemented");
727   return Imm;
728 }
729 unsigned
getRlistS0OpValue(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const730 RISCVMCCodeEmitter::getRlistS0OpValue(const MCInst &MI, unsigned OpNo,
731                                       SmallVectorImpl<MCFixup> &Fixups,
732                                       const MCSubtargetInfo &STI) const {
733   const MCOperand &MO = MI.getOperand(OpNo);
734   assert(MO.isImm() && "Rlist operand must be immediate");
735   auto Imm = MO.getImm();
736   assert(Imm >= 4 && "EABI is currently not implemented");
737   assert(Imm != RISCVZC::RA && "Rlist operand must include s0");
738   return Imm;
739 }
740 
741 #include "RISCVGenMCCodeEmitter.inc"
742