brintos

brintos / llvm-project-archived public Read only

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