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 const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); 87 // Get byte count of instruction. 88 unsigned Size = Desc.getSize(); 89 90 switch (Size) { 91 default: 92 llvm_unreachable("Unhandled encodeInstruction length!"); 93 case 2: { 94 uint16_t Bits = getBinaryCodeForInstr(MI, Fixups, STI); 95 support::endian::Writer<support::little>(OS).write<uint16_t>(Bits); 96 break; 97 } 98 case 4: { 99 uint32_t Bits = getBinaryCodeForInstr(MI, Fixups, STI); 100 support::endian::Writer<support::little>(OS).write(Bits); 101 break; 102 } 103 } 104 105 ++MCNumEmitted; // Keep track of the # of mi's emitted. 106 } 107 108 unsigned 109 RISCVMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO, 110 SmallVectorImpl<MCFixup> &Fixups, 111 const MCSubtargetInfo &STI) const { 112 113 if (MO.isReg()) 114 return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); 115 116 if (MO.isImm()) 117 return static_cast<unsigned>(MO.getImm()); 118 119 llvm_unreachable("Unhandled expression!"); 120 return 0; 121 } 122 123 unsigned 124 RISCVMCCodeEmitter::getImmOpValueAsr1(const MCInst &MI, unsigned OpNo, 125 SmallVectorImpl<MCFixup> &Fixups, 126 const MCSubtargetInfo &STI) const { 127 const MCOperand &MO = MI.getOperand(OpNo); 128 129 if (MO.isImm()) { 130 unsigned Res = MO.getImm(); 131 assert((Res & 1) == 0 && "LSB is non-zero"); 132 return Res >> 1; 133 } 134 135 return getImmOpValue(MI, OpNo, Fixups, STI); 136 } 137 138 unsigned RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo, 139 SmallVectorImpl<MCFixup> &Fixups, 140 const MCSubtargetInfo &STI) const { 141 142 const MCOperand &MO = MI.getOperand(OpNo); 143 144 MCInstrDesc const &Desc = MCII.get(MI.getOpcode()); 145 unsigned MIFrm = Desc.TSFlags & RISCVII::InstFormatMask; 146 147 // If the destination is an immediate, there is nothing to do 148 if (MO.isImm()) 149 return MO.getImm(); 150 151 assert(MO.isExpr() && 152 "getImmOpValue expects only expressions or immediates"); 153 const MCExpr *Expr = MO.getExpr(); 154 MCExpr::ExprKind Kind = Expr->getKind(); 155 RISCV::Fixups FixupKind = RISCV::fixup_riscv_invalid; 156 if (Kind == MCExpr::Target) { 157 const RISCVMCExpr *RVExpr = cast<RISCVMCExpr>(Expr); 158 159 switch (RVExpr->getKind()) { 160 case RISCVMCExpr::VK_RISCV_None: 161 case RISCVMCExpr::VK_RISCV_Invalid: 162 llvm_unreachable("Unhandled fixup kind!"); 163 case RISCVMCExpr::VK_RISCV_LO: 164 FixupKind = MIFrm == RISCVII::InstFormatI ? RISCV::fixup_riscv_lo12_i 165 : RISCV::fixup_riscv_lo12_s; 166 break; 167 case RISCVMCExpr::VK_RISCV_HI: 168 FixupKind = RISCV::fixup_riscv_hi20; 169 break; 170 case RISCVMCExpr::VK_RISCV_PCREL_HI: 171 FixupKind = RISCV::fixup_riscv_pcrel_hi20; 172 break; 173 } 174 } else if (Kind == MCExpr::SymbolRef && 175 cast<MCSymbolRefExpr>(Expr)->getKind() == MCSymbolRefExpr::VK_None) { 176 if (Desc.getOpcode() == RISCV::JAL) { 177 FixupKind = RISCV::fixup_riscv_jal; 178 } else if (MIFrm == RISCVII::InstFormatB) { 179 FixupKind = RISCV::fixup_riscv_branch; 180 } else if (MIFrm == RISCVII::InstFormatCJ) { 181 FixupKind = RISCV::fixup_riscv_rvc_jump; 182 } else if (MIFrm == RISCVII::InstFormatCB) { 183 FixupKind = RISCV::fixup_riscv_rvc_branch; 184 } 185 } 186 187 assert(FixupKind != RISCV::fixup_riscv_invalid && "Unhandled expression!"); 188 189 Fixups.push_back( 190 MCFixup::create(0, Expr, MCFixupKind(FixupKind), MI.getLoc())); 191 ++MCNumFixups; 192 193 return 0; 194 } 195 196 #include "RISCVGenMCCodeEmitter.inc" 197