760 lines · cpp
1//===-- RISCVMCCodeEmitter.cpp - Convert RISC-V code to machine code ------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements the RISCVMCCodeEmitter class.10//11//===----------------------------------------------------------------------===//12 13#include "MCTargetDesc/RISCVBaseInfo.h"14#include "MCTargetDesc/RISCVFixupKinds.h"15#include "MCTargetDesc/RISCVMCAsmInfo.h"16#include "MCTargetDesc/RISCVMCTargetDesc.h"17#include "llvm/ADT/Statistic.h"18#include "llvm/MC/MCAsmInfo.h"19#include "llvm/MC/MCCodeEmitter.h"20#include "llvm/MC/MCContext.h"21#include "llvm/MC/MCExpr.h"22#include "llvm/MC/MCInst.h"23#include "llvm/MC/MCInstBuilder.h"24#include "llvm/MC/MCInstrInfo.h"25#include "llvm/MC/MCRegisterInfo.h"26#include "llvm/MC/MCSubtargetInfo.h"27#include "llvm/MC/MCSymbol.h"28#include "llvm/Support/Casting.h"29#include "llvm/Support/EndianStream.h"30 31using namespace llvm;32 33#define DEBUG_TYPE "mccodeemitter"34 35STATISTIC(MCNumEmitted, "Number of MC instructions emitted");36STATISTIC(MCNumFixups, "Number of MC fixups created");37 38namespace {39class RISCVMCCodeEmitter : public MCCodeEmitter {40 RISCVMCCodeEmitter(const RISCVMCCodeEmitter &) = delete;41 void operator=(const RISCVMCCodeEmitter &) = delete;42 MCContext &Ctx;43 MCInstrInfo const &MCII;44 45public:46 RISCVMCCodeEmitter(MCContext &ctx, MCInstrInfo const &MCII)47 : Ctx(ctx), MCII(MCII) {}48 49 ~RISCVMCCodeEmitter() override = default;50 51 void encodeInstruction(const MCInst &MI, SmallVectorImpl<char> &CB,52 SmallVectorImpl<MCFixup> &Fixups,53 const MCSubtargetInfo &STI) const override;54 55 void expandFunctionCall(const MCInst &MI, SmallVectorImpl<char> &CB,56 SmallVectorImpl<MCFixup> &Fixups,57 const MCSubtargetInfo &STI) const;58 59 void expandTLSDESCCall(const MCInst &MI, SmallVectorImpl<char> &CB,60 SmallVectorImpl<MCFixup> &Fixups,61 const MCSubtargetInfo &STI) const;62 63 void expandAddTPRel(const MCInst &MI, SmallVectorImpl<char> &CB,64 SmallVectorImpl<MCFixup> &Fixups,65 const MCSubtargetInfo &STI) const;66 67 void expandLongCondBr(const MCInst &MI, SmallVectorImpl<char> &CB,68 SmallVectorImpl<MCFixup> &Fixups,69 const MCSubtargetInfo &STI) const;70 71 void expandQCLongCondBrImm(const MCInst &MI, SmallVectorImpl<char> &CB,72 SmallVectorImpl<MCFixup> &Fixups,73 const MCSubtargetInfo &STI, unsigned Size) const;74 75 /// TableGen'erated function for getting the binary encoding for an76 /// instruction.77 uint64_t getBinaryCodeForInstr(const MCInst &MI,78 SmallVectorImpl<MCFixup> &Fixups,79 const MCSubtargetInfo &STI) const;80 81 /// Return binary encoding of operand. If the machine operand requires82 /// relocation, record the relocation and return zero.83 uint64_t getMachineOpValue(const MCInst &MI, const MCOperand &MO,84 SmallVectorImpl<MCFixup> &Fixups,85 const MCSubtargetInfo &STI) const;86 87 uint64_t getImmOpValueMinus1(const MCInst &MI, unsigned OpNo,88 SmallVectorImpl<MCFixup> &Fixups,89 const MCSubtargetInfo &STI) const;90 91 uint64_t getImmOpValueSlist(const MCInst &MI, unsigned OpNo,92 SmallVectorImpl<MCFixup> &Fixups,93 const MCSubtargetInfo &STI) const;94 95 template <unsigned N>96 unsigned getImmOpValueAsrN(const MCInst &MI, unsigned OpNo,97 SmallVectorImpl<MCFixup> &Fixups,98 const MCSubtargetInfo &STI) const;99 100 uint64_t getImmOpValueZibi(const MCInst &MI, unsigned OpNo,101 SmallVectorImpl<MCFixup> &Fixups,102 const MCSubtargetInfo &STI) const;103 104 uint64_t getImmOpValue(const MCInst &MI, unsigned OpNo,105 SmallVectorImpl<MCFixup> &Fixups,106 const MCSubtargetInfo &STI) const;107 108 unsigned getVMaskReg(const MCInst &MI, unsigned OpNo,109 SmallVectorImpl<MCFixup> &Fixups,110 const MCSubtargetInfo &STI) const;111 112 unsigned getRlistOpValue(const MCInst &MI, unsigned OpNo,113 SmallVectorImpl<MCFixup> &Fixups,114 const MCSubtargetInfo &STI) const;115 116 unsigned getRlistS0OpValue(const MCInst &MI, unsigned OpNo,117 SmallVectorImpl<MCFixup> &Fixups,118 const MCSubtargetInfo &STI) const;119};120} // end anonymous namespace121 122MCCodeEmitter *llvm::createRISCVMCCodeEmitter(const MCInstrInfo &MCII,123 MCContext &Ctx) {124 return new RISCVMCCodeEmitter(Ctx, MCII);125}126 127static void addFixup(SmallVectorImpl<MCFixup> &Fixups, uint32_t Offset,128 const MCExpr *Value, uint16_t Kind) {129 bool PCRel = false;130 switch (Kind) {131 case ELF::R_RISCV_CALL_PLT:132 case RISCV::fixup_riscv_pcrel_hi20:133 case RISCV::fixup_riscv_pcrel_lo12_i:134 case RISCV::fixup_riscv_pcrel_lo12_s:135 case RISCV::fixup_riscv_jal:136 case RISCV::fixup_riscv_branch:137 case RISCV::fixup_riscv_rvc_jump:138 case RISCV::fixup_riscv_rvc_branch:139 case RISCV::fixup_riscv_call:140 case RISCV::fixup_riscv_call_plt:141 case RISCV::fixup_riscv_qc_e_branch:142 case RISCV::fixup_riscv_qc_e_call_plt:143 case RISCV::fixup_riscv_nds_branch_10:144 PCRel = true;145 }146 Fixups.push_back(MCFixup::create(Offset, Value, Kind, PCRel));147}148 149// Expand PseudoCALL(Reg), PseudoTAIL and PseudoJump to AUIPC and JALR with150// relocation types. We expand those pseudo-instructions while encoding them,151// meaning AUIPC and JALR won't go through RISC-V MC to MC compressed152// instruction transformation. This is acceptable because AUIPC has no 16-bit153// form and C_JALR has no immediate operand field. We let linker relaxation154// deal with it. When linker relaxation is enabled, AUIPC and JALR have a155// chance to relax to JAL.156// If the C extension is enabled, JAL has a chance relax to C_JAL.157void RISCVMCCodeEmitter::expandFunctionCall(const MCInst &MI,158 SmallVectorImpl<char> &CB,159 SmallVectorImpl<MCFixup> &Fixups,160 const MCSubtargetInfo &STI) const {161 MCInst TmpInst;162 MCOperand Func;163 MCRegister Ra;164 if (MI.getOpcode() == RISCV::PseudoTAIL) {165 Func = MI.getOperand(0);166 Ra = RISCVII::getTailExpandUseRegNo(STI.getFeatureBits());167 } else if (MI.getOpcode() == RISCV::PseudoCALLReg) {168 Func = MI.getOperand(1);169 Ra = MI.getOperand(0).getReg();170 } else if (MI.getOpcode() == RISCV::PseudoCALL) {171 Func = MI.getOperand(0);172 Ra = RISCV::X1;173 } else if (MI.getOpcode() == RISCV::PseudoJump) {174 Func = MI.getOperand(1);175 Ra = MI.getOperand(0).getReg();176 }177 uint32_t Binary;178 179 assert(Func.isExpr() && "Expected expression");180 181 const MCExpr *CallExpr = Func.getExpr();182 183 // Emit AUIPC Ra, Func with R_RISCV_CALL relocation type.184 TmpInst = MCInstBuilder(RISCV::AUIPC).addReg(Ra).addExpr(CallExpr);185 Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);186 support::endian::write(CB, Binary, llvm::endianness::little);187 188 if (MI.getOpcode() == RISCV::PseudoTAIL ||189 MI.getOpcode() == RISCV::PseudoJump)190 // Emit JALR X0, Ra, 0191 TmpInst = MCInstBuilder(RISCV::JALR).addReg(RISCV::X0).addReg(Ra).addImm(0);192 else193 // Emit JALR Ra, Ra, 0194 TmpInst = MCInstBuilder(RISCV::JALR).addReg(Ra).addReg(Ra).addImm(0);195 Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);196 support::endian::write(CB, Binary, llvm::endianness::little);197}198 199void RISCVMCCodeEmitter::expandTLSDESCCall(const MCInst &MI,200 SmallVectorImpl<char> &CB,201 SmallVectorImpl<MCFixup> &Fixups,202 const MCSubtargetInfo &STI) const {203 MCOperand SrcSymbol = MI.getOperand(3);204 assert(SrcSymbol.isExpr() &&205 "Expected expression as first input to TLSDESCCALL");206 const auto *Expr = dyn_cast<MCSpecifierExpr>(SrcSymbol.getExpr());207 MCRegister Link = MI.getOperand(0).getReg();208 MCRegister Dest = MI.getOperand(1).getReg();209 int64_t Imm = MI.getOperand(2).getImm();210 addFixup(Fixups, 0, Expr, ELF::R_RISCV_TLSDESC_CALL);211 MCInst Call =212 MCInstBuilder(RISCV::JALR).addReg(Link).addReg(Dest).addImm(Imm);213 214 uint32_t Binary = getBinaryCodeForInstr(Call, Fixups, STI);215 support::endian::write(CB, Binary, llvm::endianness::little);216}217 218// Expand PseudoAddTPRel to a simple ADD with the correct relocation.219void RISCVMCCodeEmitter::expandAddTPRel(const MCInst &MI,220 SmallVectorImpl<char> &CB,221 SmallVectorImpl<MCFixup> &Fixups,222 const MCSubtargetInfo &STI) const {223 MCOperand DestReg = MI.getOperand(0);224 MCOperand SrcReg = MI.getOperand(1);225 MCOperand TPReg = MI.getOperand(2);226 assert(TPReg.isReg() && TPReg.getReg() == RISCV::X4 &&227 "Expected thread pointer as second input to TP-relative add");228 229 MCOperand SrcSymbol = MI.getOperand(3);230 assert(SrcSymbol.isExpr() &&231 "Expected expression as third input to TP-relative add");232 233 const auto *Expr = dyn_cast<MCSpecifierExpr>(SrcSymbol.getExpr());234 assert(Expr && Expr->getSpecifier() == ELF::R_RISCV_TPREL_ADD &&235 "Expected tprel_add relocation on TP-relative symbol");236 237 addFixup(Fixups, 0, Expr, ELF::R_RISCV_TPREL_ADD);238 if (STI.hasFeature(RISCV::FeatureRelax))239 Fixups.back().setLinkerRelaxable();240 241 // Emit a normal ADD instruction with the given operands.242 MCInst TmpInst = MCInstBuilder(RISCV::ADD)243 .addOperand(DestReg)244 .addOperand(SrcReg)245 .addOperand(TPReg);246 uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);247 support::endian::write(CB, Binary, llvm::endianness::little);248}249 250static unsigned getInvertedBranchOp(unsigned BrOp) {251 switch (BrOp) {252 default:253 llvm_unreachable("Unexpected branch opcode!");254 case RISCV::PseudoLongBEQ:255 return RISCV::BNE;256 case RISCV::PseudoLongBNE:257 return RISCV::BEQ;258 case RISCV::PseudoLongBLT:259 return RISCV::BGE;260 case RISCV::PseudoLongBGE:261 return RISCV::BLT;262 case RISCV::PseudoLongBLTU:263 return RISCV::BGEU;264 case RISCV::PseudoLongBGEU:265 return RISCV::BLTU;266 case RISCV::PseudoLongQC_BEQI:267 return RISCV::QC_BNEI;268 case RISCV::PseudoLongQC_BNEI:269 return RISCV::QC_BEQI;270 case RISCV::PseudoLongQC_BLTI:271 return RISCV::QC_BGEI;272 case RISCV::PseudoLongQC_BGEI:273 return RISCV::QC_BLTI;274 case RISCV::PseudoLongQC_BLTUI:275 return RISCV::QC_BGEUI;276 case RISCV::PseudoLongQC_BGEUI:277 return RISCV::QC_BLTUI;278 case RISCV::PseudoLongQC_E_BEQI:279 return RISCV::QC_E_BNEI;280 case RISCV::PseudoLongQC_E_BNEI:281 return RISCV::QC_E_BEQI;282 case RISCV::PseudoLongQC_E_BLTI:283 return RISCV::QC_E_BGEI;284 case RISCV::PseudoLongQC_E_BGEI:285 return RISCV::QC_E_BLTI;286 case RISCV::PseudoLongQC_E_BLTUI:287 return RISCV::QC_E_BGEUI;288 case RISCV::PseudoLongQC_E_BGEUI:289 return RISCV::QC_E_BLTUI;290 }291}292 293// Expand PseudoLongBxx to an inverted conditional branch and an unconditional294// jump.295void RISCVMCCodeEmitter::expandLongCondBr(const MCInst &MI,296 SmallVectorImpl<char> &CB,297 SmallVectorImpl<MCFixup> &Fixups,298 const MCSubtargetInfo &STI) const {299 MCRegister SrcReg1 = MI.getOperand(0).getReg();300 MCRegister SrcReg2 = MI.getOperand(1).getReg();301 MCOperand SrcSymbol = MI.getOperand(2);302 unsigned Opcode = MI.getOpcode();303 bool IsEqTest =304 Opcode == RISCV::PseudoLongBNE || Opcode == RISCV::PseudoLongBEQ;305 306 bool UseCompressedBr = false;307 if (IsEqTest && STI.hasFeature(RISCV::FeatureStdExtZca)) {308 if (RISCV::X8 <= SrcReg1.id() && SrcReg1.id() <= RISCV::X15 &&309 SrcReg2.id() == RISCV::X0) {310 UseCompressedBr = true;311 } else if (RISCV::X8 <= SrcReg2.id() && SrcReg2.id() <= RISCV::X15 &&312 SrcReg1.id() == RISCV::X0) {313 std::swap(SrcReg1, SrcReg2);314 UseCompressedBr = true;315 }316 }317 318 uint32_t Offset;319 if (UseCompressedBr) {320 unsigned InvOpc =321 Opcode == RISCV::PseudoLongBNE ? RISCV::C_BEQZ : RISCV::C_BNEZ;322 MCInst TmpInst = MCInstBuilder(InvOpc).addReg(SrcReg1).addImm(6);323 uint16_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);324 support::endian::write<uint16_t>(CB, Binary, llvm::endianness::little);325 Offset = 2;326 } else {327 unsigned InvOpc = getInvertedBranchOp(Opcode);328 MCInst TmpInst =329 MCInstBuilder(InvOpc).addReg(SrcReg1).addReg(SrcReg2).addImm(8);330 uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);331 support::endian::write(CB, Binary, llvm::endianness::little);332 Offset = 4;333 }334 335 // Save the number fixups.336 size_t FixupStartIndex = Fixups.size();337 338 // Emit an unconditional jump to the destination.339 MCInst TmpInst =340 MCInstBuilder(RISCV::JAL).addReg(RISCV::X0).addOperand(SrcSymbol);341 uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);342 support::endian::write(CB, Binary, llvm::endianness::little);343 344 // Drop any fixup added so we can add the correct one.345 Fixups.resize(FixupStartIndex);346 347 if (SrcSymbol.isExpr())348 addFixup(Fixups, Offset, SrcSymbol.getExpr(), RISCV::fixup_riscv_jal);349}350 351// Expand PseudoLongQC_(E_)Bxxx to an inverted conditional branch and an352// unconditional jump.353void RISCVMCCodeEmitter::expandQCLongCondBrImm(const MCInst &MI,354 SmallVectorImpl<char> &CB,355 SmallVectorImpl<MCFixup> &Fixups,356 const MCSubtargetInfo &STI,357 unsigned Size) const {358 MCRegister SrcReg1 = MI.getOperand(0).getReg();359 auto BrImm = MI.getOperand(1).getImm();360 MCOperand SrcSymbol = MI.getOperand(2);361 unsigned Opcode = MI.getOpcode();362 uint32_t Offset;363 unsigned InvOpc = getInvertedBranchOp(Opcode);364 // Emit inverted conditional branch with offset:365 // 8 (QC.BXXX(4) + JAL(4))366 // or367 // 10 (QC.E.BXXX(6) + JAL(4)).368 if (Size == 4) {369 MCInst TmpBr =370 MCInstBuilder(InvOpc).addReg(SrcReg1).addImm(BrImm).addImm(8);371 uint32_t BrBinary = getBinaryCodeForInstr(TmpBr, Fixups, STI);372 support::endian::write(CB, BrBinary, llvm::endianness::little);373 } else {374 MCInst TmpBr =375 MCInstBuilder(InvOpc).addReg(SrcReg1).addImm(BrImm).addImm(10);376 uint64_t BrBinary =377 getBinaryCodeForInstr(TmpBr, Fixups, STI) & 0xffff'ffff'ffffu;378 SmallVector<char, 8> Encoding;379 support::endian::write(Encoding, BrBinary, llvm::endianness::little);380 assert(Encoding[6] == 0 && Encoding[7] == 0 &&381 "Unexpected encoding for 48-bit instruction");382 Encoding.truncate(6);383 CB.append(Encoding);384 }385 Offset = Size;386 // Save the number fixups.387 size_t FixupStartIndex = Fixups.size();388 // Emit an unconditional jump to the destination.389 MCInst TmpJ =390 MCInstBuilder(RISCV::JAL).addReg(RISCV::X0).addOperand(SrcSymbol);391 uint32_t JBinary = getBinaryCodeForInstr(TmpJ, Fixups, STI);392 support::endian::write(CB, JBinary, llvm::endianness::little);393 // Drop any fixup added so we can add the correct one.394 Fixups.resize(FixupStartIndex);395 if (SrcSymbol.isExpr())396 addFixup(Fixups, Offset, SrcSymbol.getExpr(), RISCV::fixup_riscv_jal);397}398 399void RISCVMCCodeEmitter::encodeInstruction(const MCInst &MI,400 SmallVectorImpl<char> &CB,401 SmallVectorImpl<MCFixup> &Fixups,402 const MCSubtargetInfo &STI) const {403 const MCInstrDesc &Desc = MCII.get(MI.getOpcode());404 // Get byte count of instruction.405 unsigned Size = Desc.getSize();406 407 // RISCVInstrInfo::getInstSizeInBytes expects that the total size of the408 // expanded instructions for each pseudo is correct in the Size field of the409 // tablegen definition for the pseudo.410 switch (MI.getOpcode()) {411 default:412 break;413 case RISCV::PseudoCALLReg:414 case RISCV::PseudoCALL:415 case RISCV::PseudoTAIL:416 case RISCV::PseudoJump:417 expandFunctionCall(MI, CB, Fixups, STI);418 MCNumEmitted += 2;419 return;420 case RISCV::PseudoAddTPRel:421 expandAddTPRel(MI, CB, Fixups, STI);422 MCNumEmitted += 1;423 return;424 case RISCV::PseudoLongBEQ:425 case RISCV::PseudoLongBNE:426 case RISCV::PseudoLongBLT:427 case RISCV::PseudoLongBGE:428 case RISCV::PseudoLongBLTU:429 case RISCV::PseudoLongBGEU:430 expandLongCondBr(MI, CB, Fixups, STI);431 MCNumEmitted += 2;432 return;433 case RISCV::PseudoLongQC_BEQI:434 case RISCV::PseudoLongQC_BNEI:435 case RISCV::PseudoLongQC_BLTI:436 case RISCV::PseudoLongQC_BGEI:437 case RISCV::PseudoLongQC_BLTUI:438 case RISCV::PseudoLongQC_BGEUI:439 expandQCLongCondBrImm(MI, CB, Fixups, STI, 4);440 MCNumEmitted += 2;441 return;442 case RISCV::PseudoLongQC_E_BEQI:443 case RISCV::PseudoLongQC_E_BNEI:444 case RISCV::PseudoLongQC_E_BLTI:445 case RISCV::PseudoLongQC_E_BGEI:446 case RISCV::PseudoLongQC_E_BLTUI:447 case RISCV::PseudoLongQC_E_BGEUI:448 expandQCLongCondBrImm(MI, CB, Fixups, STI, 6);449 MCNumEmitted += 2;450 return;451 case RISCV::PseudoTLSDESCCall:452 expandTLSDESCCall(MI, CB, Fixups, STI);453 MCNumEmitted += 1;454 return;455 }456 457 switch (Size) {458 default:459 llvm_unreachable("Unhandled encodeInstruction length!");460 case 2: {461 uint16_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);462 support::endian::write<uint16_t>(CB, Bits, llvm::endianness::little);463 break;464 }465 case 4: {466 uint32_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);467 support::endian::write(CB, Bits, llvm::endianness::little);468 break;469 }470 case 6: {471 uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI) & 0xffff'ffff'ffffu;472 SmallVector<char, 8> Encoding;473 support::endian::write(Encoding, Bits, llvm::endianness::little);474 assert(Encoding[6] == 0 && Encoding[7] == 0 &&475 "Unexpected encoding for 48-bit instruction");476 Encoding.truncate(6);477 CB.append(Encoding);478 break;479 }480 case 8: {481 uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);482 support::endian::write(CB, Bits, llvm::endianness::little);483 break;484 }485 }486 487 ++MCNumEmitted; // Keep track of the # of mi's emitted.488}489 490uint64_t491RISCVMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,492 SmallVectorImpl<MCFixup> &Fixups,493 const MCSubtargetInfo &STI) const {494 495 if (MO.isReg())496 return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());497 498 if (MO.isImm())499 return MO.getImm();500 501 llvm_unreachable("Unhandled expression!");502 return 0;503}504 505uint64_t506RISCVMCCodeEmitter::getImmOpValueMinus1(const MCInst &MI, unsigned OpNo,507 SmallVectorImpl<MCFixup> &Fixups,508 const MCSubtargetInfo &STI) const {509 const MCOperand &MO = MI.getOperand(OpNo);510 511 if (MO.isImm()) {512 uint64_t Res = MO.getImm();513 return (Res - 1);514 }515 516 llvm_unreachable("Unhandled expression!");517 return 0;518}519 520uint64_t521RISCVMCCodeEmitter::getImmOpValueSlist(const MCInst &MI, unsigned OpNo,522 SmallVectorImpl<MCFixup> &Fixups,523 const MCSubtargetInfo &STI) const {524 const MCOperand &MO = MI.getOperand(OpNo);525 assert(MO.isImm() && "Slist operand must be immediate");526 527 uint64_t Res = MO.getImm();528 switch (Res) {529 case 0:530 return 0;531 case 1:532 return 1;533 case 2:534 return 2;535 case 4:536 return 3;537 case 8:538 return 4;539 case 16:540 return 5;541 case 15:542 return 6;543 case 31:544 return 7;545 default:546 llvm_unreachable("Unhandled Slist value!");547 }548}549 550template <unsigned N>551unsigned552RISCVMCCodeEmitter::getImmOpValueAsrN(const MCInst &MI, unsigned OpNo,553 SmallVectorImpl<MCFixup> &Fixups,554 const MCSubtargetInfo &STI) const {555 const MCOperand &MO = MI.getOperand(OpNo);556 557 if (MO.isImm()) {558 uint64_t Res = MO.getImm();559 assert((Res & ((1 << N) - 1)) == 0 && "LSB is non-zero");560 return Res >> N;561 }562 563 return getImmOpValue(MI, OpNo, Fixups, STI);564}565 566uint64_t567RISCVMCCodeEmitter::getImmOpValueZibi(const MCInst &MI, unsigned OpNo,568 SmallVectorImpl<MCFixup> &Fixups,569 const MCSubtargetInfo &STI) const {570 const MCOperand &MO = MI.getOperand(OpNo);571 assert(MO.isImm() && "Zibi operand must be an immediate");572 int64_t Res = MO.getImm();573 if (Res == -1)574 return 0;575 576 return Res;577}578 579uint64_t RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo,580 SmallVectorImpl<MCFixup> &Fixups,581 const MCSubtargetInfo &STI) const {582 bool EnableRelax = STI.hasFeature(RISCV::FeatureRelax);583 const MCOperand &MO = MI.getOperand(OpNo);584 585 MCInstrDesc const &Desc = MCII.get(MI.getOpcode());586 unsigned MIFrm = RISCVII::getFormat(Desc.TSFlags);587 588 // If the destination is an immediate, there is nothing to do.589 if (MO.isImm())590 return MO.getImm();591 592 assert(MO.isExpr() &&593 "getImmOpValue expects only expressions or immediates");594 const MCExpr *Expr = MO.getExpr();595 MCExpr::ExprKind Kind = Expr->getKind();596 597 // `RelaxCandidate` must be set to `true` in two cases:598 // - The fixup's relocation gets a R_RISCV_RELAX relocation599 // - The underlying instruction may be relaxed to an instruction that gets a600 // `R_RISCV_RELAX` relocation.601 //602 // The actual emission of `R_RISCV_RELAX` will be handled in603 // `RISCVAsmBackend::applyFixup`.604 bool RelaxCandidate = false;605 auto AsmRelaxToLinkerRelaxableWithFeature = [&](unsigned Feature) -> void {606 if (!STI.hasFeature(RISCV::FeatureExactAssembly) && STI.hasFeature(Feature))607 RelaxCandidate = true;608 };609 610 unsigned FixupKind = RISCV::fixup_riscv_invalid;611 if (Kind == MCExpr::Specifier) {612 const auto *RVExpr = cast<MCSpecifierExpr>(Expr);613 FixupKind = RVExpr->getSpecifier();614 switch (RVExpr->getSpecifier()) {615 default:616 assert(FixupKind && FixupKind < FirstTargetFixupKind &&617 "invalid specifier");618 break;619 case ELF::R_RISCV_TPREL_ADD:620 // tprel_add is only used to indicate that a relocation should be emitted621 // for an add instruction used in TP-relative addressing. It should not be622 // expanded as if representing an actual instruction operand and so to623 // encounter it here is an error.624 llvm_unreachable(625 "ELF::R_RISCV_TPREL_ADD should not represent an instruction operand");626 case RISCV::S_LO:627 if (MIFrm == RISCVII::InstFormatI)628 FixupKind = RISCV::fixup_riscv_lo12_i;629 else if (MIFrm == RISCVII::InstFormatS)630 FixupKind = RISCV::fixup_riscv_lo12_s;631 else632 llvm_unreachable("VK_LO used with unexpected instruction format");633 RelaxCandidate = true;634 break;635 case ELF::R_RISCV_HI20:636 FixupKind = RISCV::fixup_riscv_hi20;637 RelaxCandidate = true;638 break;639 case RISCV::S_PCREL_LO:640 if (MIFrm == RISCVII::InstFormatI)641 FixupKind = RISCV::fixup_riscv_pcrel_lo12_i;642 else if (MIFrm == RISCVII::InstFormatS)643 FixupKind = RISCV::fixup_riscv_pcrel_lo12_s;644 else645 llvm_unreachable("VK_PCREL_LO used with unexpected instruction format");646 RelaxCandidate = true;647 break;648 case ELF::R_RISCV_PCREL_HI20:649 FixupKind = RISCV::fixup_riscv_pcrel_hi20;650 RelaxCandidate = true;651 break;652 case RISCV::S_TPREL_LO:653 if (MIFrm == RISCVII::InstFormatI)654 FixupKind = ELF::R_RISCV_TPREL_LO12_I;655 else if (MIFrm == RISCVII::InstFormatS)656 FixupKind = ELF::R_RISCV_TPREL_LO12_S;657 else658 llvm_unreachable("VK_TPREL_LO used with unexpected instruction format");659 RelaxCandidate = true;660 break;661 case ELF::R_RISCV_TPREL_HI20:662 RelaxCandidate = true;663 break;664 case ELF::R_RISCV_CALL_PLT:665 FixupKind = RISCV::fixup_riscv_call_plt;666 RelaxCandidate = true;667 break;668 case RISCV::S_QC_ABS20:669 FixupKind = RISCV::fixup_riscv_qc_abs20_u;670 RelaxCandidate = true;671 break;672 }673 } else if (Kind == MCExpr::SymbolRef || Kind == MCExpr::Binary) {674 // FIXME: Sub kind binary exprs have chance of underflow.675 if (MIFrm == RISCVII::InstFormatJ) {676 FixupKind = RISCV::fixup_riscv_jal;677 AsmRelaxToLinkerRelaxableWithFeature(RISCV::FeatureVendorXqcilb);678 } else if (MIFrm == RISCVII::InstFormatB) {679 FixupKind = RISCV::fixup_riscv_branch;680 // This might be assembler relaxed to `b<cc>; jal` but we cannot relax681 // the `jal` again in the assembler.682 } else if (MIFrm == RISCVII::InstFormatCJ) {683 FixupKind = RISCV::fixup_riscv_rvc_jump;684 AsmRelaxToLinkerRelaxableWithFeature(RISCV::FeatureVendorXqcilb);685 } else if (MIFrm == RISCVII::InstFormatCB) {686 FixupKind = RISCV::fixup_riscv_rvc_branch;687 // This might be assembler relaxed to `b<cc>; jal` but we cannot relax688 // the `jal` again in the assembler.689 } else if (MIFrm == RISCVII::InstFormatCI) {690 FixupKind = RISCV::fixup_riscv_rvc_imm;691 AsmRelaxToLinkerRelaxableWithFeature(RISCV::FeatureVendorXqcili);692 } else if (MIFrm == RISCVII::InstFormatI) {693 FixupKind = RISCV::fixup_riscv_12_i;694 } else if (MIFrm == RISCVII::InstFormatQC_EB) {695 FixupKind = RISCV::fixup_riscv_qc_e_branch;696 // This might be assembler relaxed to `qc.e.b<cc>; jal` but we cannot697 // relax the `jal` again in the assembler.698 } else if (MIFrm == RISCVII::InstFormatQC_EAI) {699 FixupKind = RISCV::fixup_riscv_qc_e_32;700 RelaxCandidate = true;701 } else if (MIFrm == RISCVII::InstFormatQC_EJ) {702 FixupKind = RISCV::fixup_riscv_qc_e_call_plt;703 RelaxCandidate = true;704 } else if (MIFrm == RISCVII::InstFormatNDS_BRANCH_10) {705 FixupKind = RISCV::fixup_riscv_nds_branch_10;706 }707 }708 709 assert(FixupKind != RISCV::fixup_riscv_invalid && "Unhandled expression!");710 711 addFixup(Fixups, 0, Expr, FixupKind);712 // If linker relaxation is enabled and supported by this relocation, set a bit713 // so that the assembler knows the size of the instruction is not fixed/known,714 // and the relocation will need a R_RISCV_RELAX relocation.715 if (EnableRelax && RelaxCandidate)716 Fixups.back().setLinkerRelaxable();717 ++MCNumFixups;718 719 return 0;720}721 722unsigned RISCVMCCodeEmitter::getVMaskReg(const MCInst &MI, unsigned OpNo,723 SmallVectorImpl<MCFixup> &Fixups,724 const MCSubtargetInfo &STI) const {725 MCOperand MO = MI.getOperand(OpNo);726 assert(MO.isReg() && "Expected a register.");727 728 switch (MO.getReg().id()) {729 default:730 llvm_unreachable("Invalid mask register.");731 case RISCV::V0:732 return 0;733 case RISCV::NoRegister:734 return 1;735 }736}737 738unsigned RISCVMCCodeEmitter::getRlistOpValue(const MCInst &MI, unsigned OpNo,739 SmallVectorImpl<MCFixup> &Fixups,740 const MCSubtargetInfo &STI) const {741 const MCOperand &MO = MI.getOperand(OpNo);742 assert(MO.isImm() && "Rlist operand must be immediate");743 auto Imm = MO.getImm();744 assert(Imm >= 4 && "EABI is currently not implemented");745 return Imm;746}747unsigned748RISCVMCCodeEmitter::getRlistS0OpValue(const MCInst &MI, unsigned OpNo,749 SmallVectorImpl<MCFixup> &Fixups,750 const MCSubtargetInfo &STI) const {751 const MCOperand &MO = MI.getOperand(OpNo);752 assert(MO.isImm() && "Rlist operand must be immediate");753 auto Imm = MO.getImm();754 assert(Imm >= 4 && "EABI is currently not implemented");755 assert(Imm != RISCVZC::RA && "Rlist operand must include s0");756 return Imm;757}758 759#include "RISCVGenMCCodeEmitter.inc"760