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/MCInstrInfo.h" 25 #include "llvm/MC/MCRegisterInfo.h" 26 #include "llvm/MC/MCSymbol.h" 27 #include "llvm/Support/Casting.h" 28 #include "llvm/Support/EndianStream.h" 29 #include "llvm/Support/raw_ostream.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: 46 RISCVMCCodeEmitter(MCContext &ctx, MCInstrInfo const &MCII) 47 : Ctx(ctx), MCII(MCII) {} 48 49 ~RISCVMCCodeEmitter() override {} 50 51 void encodeInstruction(const MCInst &MI, raw_ostream &OS, 52 SmallVectorImpl<MCFixup> &Fixups, 53 const MCSubtargetInfo &STI) const override; 54 55 /// TableGen'erated function for getting the binary encoding for an 56 /// instruction. 57 uint64_t getBinaryCodeForInstr(const MCInst &MI, 58 SmallVectorImpl<MCFixup> &Fixups, 59 const MCSubtargetInfo &STI) const; 60 61 /// Return binary encoding of operand. If the machine operand requires 62 /// relocation, record the relocation and return zero. 63 unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO, 64 SmallVectorImpl<MCFixup> &Fixups, 65 const MCSubtargetInfo &STI) const; 66 67 unsigned getImmOpValueAsr1(const MCInst &MI, unsigned OpNo, 68 SmallVectorImpl<MCFixup> &Fixups, 69 const MCSubtargetInfo &STI) const; 70 71 unsigned getImmOpValue(const MCInst &MI, unsigned OpNo, 72 SmallVectorImpl<MCFixup> &Fixups, 73 const MCSubtargetInfo &STI) const; 74 }; 75 } // end anonymous namespace 76 77 MCCodeEmitter *llvm::createRISCVMCCodeEmitter(const MCInstrInfo &MCII, 78 const MCRegisterInfo &MRI, 79 MCContext &Ctx) { 80 return new RISCVMCCodeEmitter(Ctx, MCII); 81 } 82 83 void RISCVMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, 84 SmallVectorImpl<MCFixup> &Fixups, 85 const MCSubtargetInfo &STI) const { 86 // For now, we only support RISC-V instructions with 32-bit length 87 uint32_t Bits = getBinaryCodeForInstr(MI, Fixups, STI); 88 support::endian::Writer<support::little>(OS).write(Bits); 89 ++MCNumEmitted; // Keep track of the # of mi's emitted. 90 } 91 92 unsigned 93 RISCVMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO, 94 SmallVectorImpl<MCFixup> &Fixups, 95 const MCSubtargetInfo &STI) const { 96 97 if (MO.isReg()) 98 return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); 99 100 if (MO.isImm()) 101 return static_cast<unsigned>(MO.getImm()); 102 103 llvm_unreachable("Unhandled expression!"); 104 return 0; 105 } 106 107 unsigned 108 RISCVMCCodeEmitter::getImmOpValueAsr1(const MCInst &MI, unsigned OpNo, 109 SmallVectorImpl<MCFixup> &Fixups, 110 const MCSubtargetInfo &STI) const { 111 const MCOperand &MO = MI.getOperand(OpNo); 112 113 if (MO.isImm()) { 114 unsigned Res = MO.getImm(); 115 assert((Res & 1) == 0 && "LSB is non-zero"); 116 return Res >> 1; 117 } 118 119 return getImmOpValue(MI, OpNo, Fixups, STI); 120 } 121 122 unsigned RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo, 123 SmallVectorImpl<MCFixup> &Fixups, 124 const MCSubtargetInfo &STI) const { 125 126 const MCOperand &MO = MI.getOperand(OpNo); 127 128 MCInstrDesc const &Desc = MCII.get(MI.getOpcode()); 129 unsigned MIFrm = Desc.TSFlags & RISCVII::InstFormatMask; 130 131 // If the destination is an immediate, there is nothing to do 132 if (MO.isImm()) 133 return MO.getImm(); 134 135 assert(MO.isExpr() && 136 "getImmOpValue expects only expressions or immediates"); 137 const MCExpr *Expr = MO.getExpr(); 138 MCExpr::ExprKind Kind = Expr->getKind(); 139 RISCV::Fixups FixupKind = RISCV::fixup_riscv_invalid; 140 if (Kind == MCExpr::Target) { 141 const RISCVMCExpr *RVExpr = cast<RISCVMCExpr>(Expr); 142 143 switch (RVExpr->getKind()) { 144 case RISCVMCExpr::VK_RISCV_None: 145 case RISCVMCExpr::VK_RISCV_Invalid: 146 llvm_unreachable("Unhandled fixup kind!"); 147 case RISCVMCExpr::VK_RISCV_LO: 148 FixupKind = MIFrm == RISCVII::InstFormatI ? RISCV::fixup_riscv_lo12_i 149 : RISCV::fixup_riscv_lo12_s; 150 break; 151 case RISCVMCExpr::VK_RISCV_HI: 152 FixupKind = RISCV::fixup_riscv_hi20; 153 break; 154 case RISCVMCExpr::VK_RISCV_PCREL_HI: 155 FixupKind = RISCV::fixup_riscv_pcrel_hi20; 156 break; 157 } 158 } else if (Kind == MCExpr::SymbolRef && 159 cast<MCSymbolRefExpr>(Expr)->getKind() == MCSymbolRefExpr::VK_None) { 160 if (Desc.getOpcode() == RISCV::JAL) { 161 FixupKind = RISCV::fixup_riscv_jal; 162 } else if (MIFrm == RISCVII::InstFormatB) { 163 FixupKind = RISCV::fixup_riscv_branch; 164 } 165 } 166 167 assert(FixupKind != RISCV::fixup_riscv_invalid && "Unhandled expression!"); 168 169 Fixups.push_back( 170 MCFixup::create(0, Expr, MCFixupKind(FixupKind), MI.getLoc())); 171 ++MCNumFixups; 172 173 return 0; 174 } 175 176 #include "RISCVGenMCCodeEmitter.inc" 177