Home | History | Annotate | Download | only in MCTargetDesc
      1 //===-- RISCVMCCodeEmitter.cpp - Convert RISCV code to machine code -------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file implements the RISCVMCCodeEmitter class.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "MCTargetDesc/RISCVBaseInfo.h"
     15 #include "MCTargetDesc/RISCVFixupKinds.h"
     16 #include "MCTargetDesc/RISCVMCExpr.h"
     17 #include "MCTargetDesc/RISCVMCTargetDesc.h"
     18 #include "llvm/ADT/Statistic.h"
     19 #include "llvm/MC/MCAsmInfo.h"
     20 #include "llvm/MC/MCCodeEmitter.h"
     21 #include "llvm/MC/MCContext.h"
     22 #include "llvm/MC/MCExpr.h"
     23 #include "llvm/MC/MCInst.h"
     24 #include "llvm/MC/MCInstBuilder.h"
     25 #include "llvm/MC/MCInstrInfo.h"
     26 #include "llvm/MC/MCRegisterInfo.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 {}
     51 
     52   void encodeInstruction(const MCInst &MI, raw_ostream &OS,
     53                          SmallVectorImpl<MCFixup> &Fixups,
     54                          const MCSubtargetInfo &STI) const override;
     55 
     56   void expandFunctionCall(const MCInst &MI, raw_ostream &OS,
     57                           SmallVectorImpl<MCFixup> &Fixups,
     58                           const MCSubtargetInfo &STI) const;
     59 
     60   /// TableGen'erated function for getting the binary encoding for an
     61   /// instruction.
     62   uint64_t getBinaryCodeForInstr(const MCInst &MI,
     63                                  SmallVectorImpl<MCFixup> &Fixups,
     64                                  const MCSubtargetInfo &STI) const;
     65 
     66   /// Return binary encoding of operand. If the machine operand requires
     67   /// relocation, record the relocation and return zero.
     68   unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
     69                              SmallVectorImpl<MCFixup> &Fixups,
     70                              const MCSubtargetInfo &STI) const;
     71 
     72   unsigned getImmOpValueAsr1(const MCInst &MI, unsigned OpNo,
     73                              SmallVectorImpl<MCFixup> &Fixups,
     74                              const MCSubtargetInfo &STI) const;
     75 
     76   unsigned getImmOpValue(const MCInst &MI, unsigned OpNo,
     77                          SmallVectorImpl<MCFixup> &Fixups,
     78                          const MCSubtargetInfo &STI) const;
     79 };
     80 } // end anonymous namespace
     81 
     82 MCCodeEmitter *llvm::createRISCVMCCodeEmitter(const MCInstrInfo &MCII,
     83                                               const MCRegisterInfo &MRI,
     84                                               MCContext &Ctx) {
     85   return new RISCVMCCodeEmitter(Ctx, MCII);
     86 }
     87 
     88 // Expand PseudoCALL and PseudoTAIL to AUIPC and JALR with relocation types.
     89 // We expand PseudoCALL and PseudoTAIL while encoding, meaning AUIPC and JALR
     90 // won't go through RISCV MC to MC compressed instruction transformation. This
     91 // is acceptable because AUIPC has no 16-bit form and C_JALR have no immediate
     92 // operand field.  We let linker relaxation deal with it. When linker
     93 // relaxation enabled, AUIPC and JALR have chance relax to JAL. If C extension
     94 // is enabled, JAL has chance relax to C_JAL.
     95 void RISCVMCCodeEmitter::expandFunctionCall(const MCInst &MI, raw_ostream &OS,
     96                                             SmallVectorImpl<MCFixup> &Fixups,
     97                                             const MCSubtargetInfo &STI) const {
     98   MCInst TmpInst;
     99   MCOperand Func = MI.getOperand(0);
    100   unsigned Ra = (MI.getOpcode() == RISCV::PseudoTAIL) ? RISCV::X6 : RISCV::X1;
    101   uint32_t Binary;
    102 
    103   assert(Func.isExpr() && "Expected expression");
    104 
    105   const MCExpr *Expr = Func.getExpr();
    106 
    107   // Create function call expression CallExpr for AUIPC.
    108   const MCExpr *CallExpr =
    109       RISCVMCExpr::create(Expr, RISCVMCExpr::VK_RISCV_CALL, Ctx);
    110 
    111   // Emit AUIPC Ra, Func with R_RISCV_CALL relocation type.
    112   TmpInst = MCInstBuilder(RISCV::AUIPC)
    113                 .addReg(Ra)
    114                 .addOperand(MCOperand::createExpr(CallExpr));
    115   Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
    116   support::endian::write(OS, Binary, support::little);
    117 
    118   if (MI.getOpcode() == RISCV::PseudoTAIL)
    119     // Emit JALR X0, X6, 0
    120     TmpInst = MCInstBuilder(RISCV::JALR).addReg(RISCV::X0).addReg(Ra).addImm(0);
    121   else
    122     // Emit JALR X1, X1, 0
    123     TmpInst = MCInstBuilder(RISCV::JALR).addReg(Ra).addReg(Ra).addImm(0);
    124   Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
    125   support::endian::write(OS, Binary, support::little);
    126 }
    127 
    128 void RISCVMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
    129                                            SmallVectorImpl<MCFixup> &Fixups,
    130                                            const MCSubtargetInfo &STI) const {
    131   const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
    132   // Get byte count of instruction.
    133   unsigned Size = Desc.getSize();
    134 
    135   if (MI.getOpcode() == RISCV::PseudoCALL ||
    136       MI.getOpcode() == RISCV::PseudoTAIL) {
    137     expandFunctionCall(MI, OS, Fixups, STI);
    138     MCNumEmitted += 2;
    139     return;
    140   }
    141 
    142   switch (Size) {
    143   default:
    144     llvm_unreachable("Unhandled encodeInstruction length!");
    145   case 2: {
    146     uint16_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
    147     support::endian::write<uint16_t>(OS, Bits, support::little);
    148     break;
    149   }
    150   case 4: {
    151     uint32_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
    152     support::endian::write(OS, Bits, support::little);
    153     break;
    154   }
    155   }
    156 
    157   ++MCNumEmitted; // Keep track of the # of mi's emitted.
    158 }
    159 
    160 unsigned
    161 RISCVMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
    162                                       SmallVectorImpl<MCFixup> &Fixups,
    163                                       const MCSubtargetInfo &STI) const {
    164 
    165   if (MO.isReg())
    166     return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
    167 
    168   if (MO.isImm())
    169     return static_cast<unsigned>(MO.getImm());
    170 
    171   llvm_unreachable("Unhandled expression!");
    172   return 0;
    173 }
    174 
    175 unsigned
    176 RISCVMCCodeEmitter::getImmOpValueAsr1(const MCInst &MI, unsigned OpNo,
    177                                       SmallVectorImpl<MCFixup> &Fixups,
    178                                       const MCSubtargetInfo &STI) const {
    179   const MCOperand &MO = MI.getOperand(OpNo);
    180 
    181   if (MO.isImm()) {
    182     unsigned Res = MO.getImm();
    183     assert((Res & 1) == 0 && "LSB is non-zero");
    184     return Res >> 1;
    185   }
    186 
    187   return getImmOpValue(MI, OpNo, Fixups, STI);
    188 }
    189 
    190 unsigned RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo,
    191                                            SmallVectorImpl<MCFixup> &Fixups,
    192                                            const MCSubtargetInfo &STI) const {
    193   bool EnableRelax = STI.getFeatureBits()[RISCV::FeatureRelax];
    194   const MCOperand &MO = MI.getOperand(OpNo);
    195 
    196   MCInstrDesc const &Desc = MCII.get(MI.getOpcode());
    197   unsigned MIFrm = Desc.TSFlags & RISCVII::InstFormatMask;
    198 
    199   // If the destination is an immediate, there is nothing to do
    200   if (MO.isImm())
    201     return MO.getImm();
    202 
    203   assert(MO.isExpr() &&
    204          "getImmOpValue expects only expressions or immediates");
    205   const MCExpr *Expr = MO.getExpr();
    206   MCExpr::ExprKind Kind = Expr->getKind();
    207   RISCV::Fixups FixupKind = RISCV::fixup_riscv_invalid;
    208   if (Kind == MCExpr::Target) {
    209     const RISCVMCExpr *RVExpr = cast<RISCVMCExpr>(Expr);
    210 
    211     switch (RVExpr->getKind()) {
    212     case RISCVMCExpr::VK_RISCV_None:
    213     case RISCVMCExpr::VK_RISCV_Invalid:
    214       llvm_unreachable("Unhandled fixup kind!");
    215     case RISCVMCExpr::VK_RISCV_LO:
    216       if (MIFrm == RISCVII::InstFormatI)
    217         FixupKind = RISCV::fixup_riscv_lo12_i;
    218       else if (MIFrm == RISCVII::InstFormatS)
    219         FixupKind = RISCV::fixup_riscv_lo12_s;
    220       else
    221         llvm_unreachable("VK_RISCV_LO used with unexpected instruction format");
    222       break;
    223     case RISCVMCExpr::VK_RISCV_HI:
    224       FixupKind = RISCV::fixup_riscv_hi20;
    225       break;
    226     case RISCVMCExpr::VK_RISCV_PCREL_LO:
    227       if (MIFrm == RISCVII::InstFormatI)
    228         FixupKind = RISCV::fixup_riscv_pcrel_lo12_i;
    229       else if (MIFrm == RISCVII::InstFormatS)
    230         FixupKind = RISCV::fixup_riscv_pcrel_lo12_s;
    231       else
    232         llvm_unreachable(
    233             "VK_RISCV_PCREL_LO used with unexpected instruction format");
    234       break;
    235     case RISCVMCExpr::VK_RISCV_PCREL_HI:
    236       FixupKind = RISCV::fixup_riscv_pcrel_hi20;
    237       break;
    238     case RISCVMCExpr::VK_RISCV_CALL:
    239       FixupKind = RISCV::fixup_riscv_call;
    240       break;
    241     }
    242   } else if (Kind == MCExpr::SymbolRef &&
    243              cast<MCSymbolRefExpr>(Expr)->getKind() == MCSymbolRefExpr::VK_None) {
    244     if (Desc.getOpcode() == RISCV::JAL) {
    245       FixupKind = RISCV::fixup_riscv_jal;
    246     } else if (MIFrm == RISCVII::InstFormatB) {
    247       FixupKind = RISCV::fixup_riscv_branch;
    248     } else if (MIFrm == RISCVII::InstFormatCJ) {
    249       FixupKind = RISCV::fixup_riscv_rvc_jump;
    250     } else if (MIFrm == RISCVII::InstFormatCB) {
    251       FixupKind = RISCV::fixup_riscv_rvc_branch;
    252     }
    253   }
    254 
    255   assert(FixupKind != RISCV::fixup_riscv_invalid && "Unhandled expression!");
    256 
    257   Fixups.push_back(
    258       MCFixup::create(0, Expr, MCFixupKind(FixupKind), MI.getLoc()));
    259   ++MCNumFixups;
    260 
    261   if (EnableRelax) {
    262     if (FixupKind == RISCV::fixup_riscv_call) {
    263       Fixups.push_back(
    264       MCFixup::create(0, Expr, MCFixupKind(RISCV::fixup_riscv_relax),
    265                       MI.getLoc()));
    266       ++MCNumFixups;
    267     }
    268   }
    269 
    270   return 0;
    271 }
    272 
    273 #include "RISCVGenMCCodeEmitter.inc"
    274