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 to AUIPC and JALR with relocation types. 89 // We expand PseudoCALL while encoding, meaning AUIPC and JALR won't go through 90 // RISCV MC to MC compressed instruction transformation. This is acceptable 91 // because AUIPC has no 16-bit form and C_JALR have no immediate operand field. 92 // We let linker relaxation deal with it. When linker relaxation enabled, 93 // AUIPC and JALR have chance relax to JAL. If C extension is enabled, 94 // 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 = 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::Writer<support::little>(OS).write(Binary); 117 118 // Emit JALR Ra, Ra, 0 119 TmpInst = MCInstBuilder(RISCV::JALR).addReg(Ra).addReg(Ra).addImm(0); 120 Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); 121 support::endian::Writer<support::little>(OS).write(Binary); 122 } 123 124 void RISCVMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, 125 SmallVectorImpl<MCFixup> &Fixups, 126 const MCSubtargetInfo &STI) const { 127 const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); 128 // Get byte count of instruction. 129 unsigned Size = Desc.getSize(); 130 131 if (MI.getOpcode() == RISCV::PseudoCALL) { 132 expandFunctionCall(MI, OS, Fixups, STI); 133 MCNumEmitted += 2; 134 return; 135 } 136 137 switch (Size) { 138 default: 139 llvm_unreachable("Unhandled encodeInstruction length!"); 140 case 2: { 141 uint16_t Bits = getBinaryCodeForInstr(MI, Fixups, STI); 142 support::endian::Writer<support::little>(OS).write<uint16_t>(Bits); 143 break; 144 } 145 case 4: { 146 uint32_t Bits = getBinaryCodeForInstr(MI, Fixups, STI); 147 support::endian::Writer<support::little>(OS).write(Bits); 148 break; 149 } 150 } 151 152 ++MCNumEmitted; // Keep track of the # of mi's emitted. 153 } 154 155 unsigned 156 RISCVMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO, 157 SmallVectorImpl<MCFixup> &Fixups, 158 const MCSubtargetInfo &STI) const { 159 160 if (MO.isReg()) 161 return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); 162 163 if (MO.isImm()) 164 return static_cast<unsigned>(MO.getImm()); 165 166 llvm_unreachable("Unhandled expression!"); 167 return 0; 168 } 169 170 unsigned 171 RISCVMCCodeEmitter::getImmOpValueAsr1(const MCInst &MI, unsigned OpNo, 172 SmallVectorImpl<MCFixup> &Fixups, 173 const MCSubtargetInfo &STI) const { 174 const MCOperand &MO = MI.getOperand(OpNo); 175 176 if (MO.isImm()) { 177 unsigned Res = MO.getImm(); 178 assert((Res & 1) == 0 && "LSB is non-zero"); 179 return Res >> 1; 180 } 181 182 return getImmOpValue(MI, OpNo, Fixups, STI); 183 } 184 185 unsigned RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo, 186 SmallVectorImpl<MCFixup> &Fixups, 187 const MCSubtargetInfo &STI) const { 188 189 const MCOperand &MO = MI.getOperand(OpNo); 190 191 MCInstrDesc const &Desc = MCII.get(MI.getOpcode()); 192 unsigned MIFrm = Desc.TSFlags & RISCVII::InstFormatMask; 193 194 // If the destination is an immediate, there is nothing to do 195 if (MO.isImm()) 196 return MO.getImm(); 197 198 assert(MO.isExpr() && 199 "getImmOpValue expects only expressions or immediates"); 200 const MCExpr *Expr = MO.getExpr(); 201 MCExpr::ExprKind Kind = Expr->getKind(); 202 RISCV::Fixups FixupKind = RISCV::fixup_riscv_invalid; 203 if (Kind == MCExpr::Target) { 204 const RISCVMCExpr *RVExpr = cast<RISCVMCExpr>(Expr); 205 206 switch (RVExpr->getKind()) { 207 case RISCVMCExpr::VK_RISCV_None: 208 case RISCVMCExpr::VK_RISCV_Invalid: 209 llvm_unreachable("Unhandled fixup kind!"); 210 case RISCVMCExpr::VK_RISCV_LO: 211 if (MIFrm == RISCVII::InstFormatI) 212 FixupKind = RISCV::fixup_riscv_lo12_i; 213 else if (MIFrm == RISCVII::InstFormatS) 214 FixupKind = RISCV::fixup_riscv_lo12_s; 215 else 216 llvm_unreachable("VK_RISCV_LO used with unexpected instruction format"); 217 break; 218 case RISCVMCExpr::VK_RISCV_HI: 219 FixupKind = RISCV::fixup_riscv_hi20; 220 break; 221 case RISCVMCExpr::VK_RISCV_PCREL_LO: 222 if (MIFrm == RISCVII::InstFormatI) 223 FixupKind = RISCV::fixup_riscv_pcrel_lo12_i; 224 else if (MIFrm == RISCVII::InstFormatS) 225 FixupKind = RISCV::fixup_riscv_pcrel_lo12_s; 226 else 227 llvm_unreachable( 228 "VK_RISCV_PCREL_LO used with unexpected instruction format"); 229 break; 230 case RISCVMCExpr::VK_RISCV_PCREL_HI: 231 FixupKind = RISCV::fixup_riscv_pcrel_hi20; 232 break; 233 case RISCVMCExpr::VK_RISCV_CALL: 234 FixupKind = RISCV::fixup_riscv_call; 235 break; 236 } 237 } else if (Kind == MCExpr::SymbolRef && 238 cast<MCSymbolRefExpr>(Expr)->getKind() == MCSymbolRefExpr::VK_None) { 239 if (Desc.getOpcode() == RISCV::JAL) { 240 FixupKind = RISCV::fixup_riscv_jal; 241 } else if (MIFrm == RISCVII::InstFormatB) { 242 FixupKind = RISCV::fixup_riscv_branch; 243 } else if (MIFrm == RISCVII::InstFormatCJ) { 244 FixupKind = RISCV::fixup_riscv_rvc_jump; 245 } else if (MIFrm == RISCVII::InstFormatCB) { 246 FixupKind = RISCV::fixup_riscv_rvc_branch; 247 } 248 } 249 250 assert(FixupKind != RISCV::fixup_riscv_invalid && "Unhandled expression!"); 251 252 Fixups.push_back( 253 MCFixup::create(0, Expr, MCFixupKind(FixupKind), MI.getLoc())); 254 ++MCNumFixups; 255 256 return 0; 257 } 258 259 #include "RISCVGenMCCodeEmitter.inc" 260