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 if (MIFrm == RISCVII::InstFormatI) 165 FixupKind = RISCV::fixup_riscv_lo12_i; 166 else if (MIFrm == RISCVII::InstFormatS) 167 FixupKind = RISCV::fixup_riscv_lo12_s; 168 else 169 llvm_unreachable("VK_RISCV_LO used with unexpected instruction format"); 170 break; 171 case RISCVMCExpr::VK_RISCV_HI: 172 FixupKind = RISCV::fixup_riscv_hi20; 173 break; 174 case RISCVMCExpr::VK_RISCV_PCREL_LO: 175 if (MIFrm == RISCVII::InstFormatI) 176 FixupKind = RISCV::fixup_riscv_pcrel_lo12_i; 177 else if (MIFrm == RISCVII::InstFormatS) 178 FixupKind = RISCV::fixup_riscv_pcrel_lo12_s; 179 else 180 llvm_unreachable( 181 "VK_RISCV_PCREL_LO used with unexpected instruction format"); 182 break; 183 case RISCVMCExpr::VK_RISCV_PCREL_HI: 184 FixupKind = RISCV::fixup_riscv_pcrel_hi20; 185 break; 186 } 187 } else if (Kind == MCExpr::SymbolRef && 188 cast<MCSymbolRefExpr>(Expr)->getKind() == MCSymbolRefExpr::VK_None) { 189 if (Desc.getOpcode() == RISCV::JAL) { 190 FixupKind = RISCV::fixup_riscv_jal; 191 } else if (MIFrm == RISCVII::InstFormatB) { 192 FixupKind = RISCV::fixup_riscv_branch; 193 } else if (MIFrm == RISCVII::InstFormatCJ) { 194 FixupKind = RISCV::fixup_riscv_rvc_jump; 195 } else if (MIFrm == RISCVII::InstFormatCB) { 196 FixupKind = RISCV::fixup_riscv_rvc_branch; 197 } 198 } 199 200 assert(FixupKind != RISCV::fixup_riscv_invalid && "Unhandled expression!"); 201 202 Fixups.push_back( 203 MCFixup::create(0, Expr, MCFixupKind(FixupKind), MI.getLoc())); 204 ++MCNumFixups; 205 206 return 0; 207 } 208 209 #include "RISCVGenMCCodeEmitter.inc" 210