33#define DEBUG_TYPE "mccodeemitter"
35STATISTIC(MCNumEmitted,
"Number of MC instructions emitted");
36STATISTIC(MCNumFixups,
"Number of MC fixups created");
40 RISCVMCCodeEmitter(
const RISCVMCCodeEmitter &) =
delete;
41 void operator=(
const RISCVMCCodeEmitter &) =
delete;
47 : Ctx(ctx), MCII(MCII) {}
49 ~RISCVMCCodeEmitter()
override =
default;
96 unsigned getImmOpValueAsrN(
const MCInst &
MI,
unsigned OpNo,
104 unsigned getVMaskReg(
const MCInst &
MI,
unsigned OpNo,
108 unsigned getRlistOpValue(
const MCInst &
MI,
unsigned OpNo,
112 unsigned getRlistS0OpValue(
const MCInst &
MI,
unsigned OpNo,
120 return new RISCVMCCodeEmitter(Ctx, MCII);
127 case ELF::R_RISCV_CALL_PLT:
153void RISCVMCCodeEmitter::expandFunctionCall(
const MCInst &
MI,
160 if (
MI.getOpcode() == RISCV::PseudoTAIL) {
163 }
else if (
MI.getOpcode() == RISCV::PseudoCALLReg) {
165 Ra =
MI.getOperand(0).getReg();
166 }
else if (
MI.getOpcode() == RISCV::PseudoCALL) {
169 }
else if (
MI.getOpcode() == RISCV::PseudoJump) {
171 Ra =
MI.getOperand(0).getReg();
175 assert(
Func.isExpr() &&
"Expected expression");
181 Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
184 if (
MI.getOpcode() == RISCV::PseudoTAIL ||
185 MI.getOpcode() == RISCV::PseudoJump)
191 Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
195void RISCVMCCodeEmitter::expandTLSDESCCall(
const MCInst &
MI,
201 "Expected expression as first input to TLSDESCCALL");
202 const auto *Expr = dyn_cast<MCSpecifierExpr>(SrcSymbol.
getExpr());
205 int64_t
Imm =
MI.getOperand(2).getImm();
206 addFixup(Fixups, 0, Expr, ELF::R_RISCV_TLSDESC_CALL);
215void RISCVMCCodeEmitter::expandAddTPRel(
const MCInst &
MI,
223 "Expected thread pointer as second input to TP-relative add");
227 "Expected expression as third input to TP-relative add");
229 const auto *Expr = dyn_cast<MCSpecifierExpr>(SrcSymbol.
getExpr());
230 assert(Expr && Expr->getSpecifier() == ELF::R_RISCV_TPREL_ADD &&
231 "Expected tprel_add relocation on TP-relative symbol");
233 addFixup(Fixups, 0, Expr, ELF::R_RISCV_TPREL_ADD);
235 Fixups.back().setLinkerRelaxable();
250 case RISCV::PseudoLongBEQ:
252 case RISCV::PseudoLongBNE:
254 case RISCV::PseudoLongBLT:
256 case RISCV::PseudoLongBGE:
258 case RISCV::PseudoLongBLTU:
260 case RISCV::PseudoLongBGEU:
262 case RISCV::PseudoLongQC_BEQI:
263 return RISCV::QC_BNEI;
264 case RISCV::PseudoLongQC_BNEI:
265 return RISCV::QC_BEQI;
266 case RISCV::PseudoLongQC_BLTI:
267 return RISCV::QC_BGEI;
268 case RISCV::PseudoLongQC_BGEI:
269 return RISCV::QC_BLTI;
270 case RISCV::PseudoLongQC_BLTUI:
271 return RISCV::QC_BGEUI;
272 case RISCV::PseudoLongQC_BGEUI:
273 return RISCV::QC_BLTUI;
274 case RISCV::PseudoLongQC_E_BEQI:
275 return RISCV::QC_E_BNEI;
276 case RISCV::PseudoLongQC_E_BNEI:
277 return RISCV::QC_E_BEQI;
278 case RISCV::PseudoLongQC_E_BLTI:
279 return RISCV::QC_E_BGEI;
280 case RISCV::PseudoLongQC_E_BGEI:
281 return RISCV::QC_E_BLTI;
282 case RISCV::PseudoLongQC_E_BLTUI:
283 return RISCV::QC_E_BGEUI;
284 case RISCV::PseudoLongQC_E_BGEUI:
285 return RISCV::QC_E_BLTUI;
291void RISCVMCCodeEmitter::expandLongCondBr(
const MCInst &
MI,
298 unsigned Opcode =
MI.getOpcode();
300 Opcode == RISCV::PseudoLongBNE || Opcode == RISCV::PseudoLongBEQ;
302 bool UseCompressedBr =
false;
303 if (IsEqTest && STI.
hasFeature(RISCV::FeatureStdExtZca)) {
304 if (RISCV::X8 <= SrcReg1.
id() && SrcReg1.
id() <= RISCV::X15 &&
305 SrcReg2.
id() == RISCV::X0) {
306 UseCompressedBr =
true;
307 }
else if (RISCV::X8 <= SrcReg2.
id() && SrcReg2.
id() <= RISCV::X15 &&
308 SrcReg1.
id() == RISCV::X0) {
310 UseCompressedBr =
true;
315 if (UseCompressedBr) {
317 Opcode == RISCV::PseudoLongBNE ? RISCV::C_BEQZ : RISCV::C_BNEZ;
332 size_t FixupStartIndex =
Fixups.size();
341 Fixups.resize(FixupStartIndex);
349void RISCVMCCodeEmitter::expandQCLongCondBrImm(
const MCInst &
MI,
353 unsigned Size)
const {
355 auto BrImm =
MI.getOperand(1).getImm();
357 unsigned Opcode =
MI.getOpcode();
367 uint32_t BrBinary = getBinaryCodeForInstr(TmpBr, Fixups, STI);
373 getBinaryCodeForInstr(TmpBr, Fixups, STI) & 0xffff'ffff'ffffu;
376 assert(Encoding[6] == 0 && Encoding[7] == 0 &&
377 "Unexpected encoding for 48-bit instruction");
383 size_t FixupStartIndex =
Fixups.size();
387 uint32_t JBinary = getBinaryCodeForInstr(TmpJ, Fixups, STI);
390 Fixups.resize(FixupStartIndex);
395void RISCVMCCodeEmitter::encodeInstruction(
const MCInst &
MI,
406 switch (
MI.getOpcode()) {
409 case RISCV::PseudoCALLReg:
410 case RISCV::PseudoCALL:
411 case RISCV::PseudoTAIL:
412 case RISCV::PseudoJump:
413 expandFunctionCall(
MI, CB, Fixups, STI);
416 case RISCV::PseudoAddTPRel:
417 expandAddTPRel(
MI, CB, Fixups, STI);
420 case RISCV::PseudoLongBEQ:
421 case RISCV::PseudoLongBNE:
422 case RISCV::PseudoLongBLT:
423 case RISCV::PseudoLongBGE:
424 case RISCV::PseudoLongBLTU:
425 case RISCV::PseudoLongBGEU:
426 expandLongCondBr(
MI, CB, Fixups, STI);
429 case RISCV::PseudoLongQC_BEQI:
430 case RISCV::PseudoLongQC_BNEI:
431 case RISCV::PseudoLongQC_BLTI:
432 case RISCV::PseudoLongQC_BGEI:
433 case RISCV::PseudoLongQC_BLTUI:
434 case RISCV::PseudoLongQC_BGEUI:
435 expandQCLongCondBrImm(
MI, CB, Fixups, STI, 4);
438 case RISCV::PseudoLongQC_E_BEQI:
439 case RISCV::PseudoLongQC_E_BNEI:
440 case RISCV::PseudoLongQC_E_BLTI:
441 case RISCV::PseudoLongQC_E_BGEI:
442 case RISCV::PseudoLongQC_E_BLTUI:
443 case RISCV::PseudoLongQC_E_BGEUI:
444 expandQCLongCondBrImm(
MI, CB, Fixups, STI, 6);
447 case RISCV::PseudoTLSDESCCall:
448 expandTLSDESCCall(
MI, CB, Fixups, STI);
467 uint64_t Bits = getBinaryCodeForInstr(
MI, Fixups, STI) & 0xffff'ffff'ffffu;
470 assert(Encoding[6] == 0 && Encoding[7] == 0 &&
471 "Unexpected encoding for 48-bit instruction");
492 return Ctx.getRegisterInfo()->getEncodingValue(MO.
getReg());
502RISCVMCCodeEmitter::getImmOpValueMinus1(
const MCInst &
MI,
unsigned OpNo,
517RISCVMCCodeEmitter::getImmOpValueSlist(
const MCInst &
MI,
unsigned OpNo,
521 assert(MO.
isImm() &&
"Slist operand must be immediate");
548RISCVMCCodeEmitter::getImmOpValueAsrN(
const MCInst &
MI,
unsigned OpNo,
555 assert((Res & ((1 <<
N) - 1)) == 0 &&
"LSB is non-zero");
559 return getImmOpValue(
MI, OpNo, Fixups, STI);
565 bool EnableRelax = STI.
hasFeature(RISCV::FeatureRelax);
576 "getImmOpValue expects only expressions or immediates");
587 bool RelaxCandidate =
false;
588 auto AsmRelaxToLinkerRelaxableWithFeature = [&](
unsigned Feature) ->
void {
590 RelaxCandidate =
true;
595 const auto *RVExpr = cast<MCSpecifierExpr>(Expr);
597 switch (RVExpr->getSpecifier()) {
600 "invalid specifier");
602 case ELF::R_RISCV_TPREL_ADD:
608 "ELF::R_RISCV_TPREL_ADD should not represent an instruction operand");
616 RelaxCandidate =
true;
618 case ELF::R_RISCV_HI20:
620 RelaxCandidate =
true;
629 RelaxCandidate =
true;
631 case ELF::R_RISCV_PCREL_HI20:
633 RelaxCandidate =
true;
642 RelaxCandidate =
true;
644 case ELF::R_RISCV_TPREL_HI20:
645 RelaxCandidate =
true;
647 case ELF::R_RISCV_CALL_PLT:
649 RelaxCandidate =
true;
653 RelaxCandidate =
true;
660 AsmRelaxToLinkerRelaxableWithFeature(RISCV::FeatureVendorXqcilb);
667 AsmRelaxToLinkerRelaxableWithFeature(RISCV::FeatureVendorXqcilb);
682 RelaxCandidate =
true;
685 RelaxCandidate =
true;
693 addFixup(Fixups, 0, Expr, FixupKind);
697 if (EnableRelax && RelaxCandidate)
698 Fixups.back().setLinkerRelaxable();
704unsigned RISCVMCCodeEmitter::getVMaskReg(
const MCInst &
MI,
unsigned OpNo,
715 case RISCV::NoRegister:
720unsigned RISCVMCCodeEmitter::getRlistOpValue(
const MCInst &
MI,
unsigned OpNo,
724 assert(MO.
isImm() &&
"Rlist operand must be immediate");
726 assert(Imm >= 4 &&
"EABI is currently not implemented");
730RISCVMCCodeEmitter::getRlistS0OpValue(
const MCInst &
MI,
unsigned OpNo,
734 assert(MO.
isImm() &&
"Rlist operand must be immediate");
736 assert(Imm >= 4 &&
"EABI is currently not implemented");
741#include "RISCVGenMCCodeEmitter.inc"
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static void addFixup(SmallVectorImpl< MCFixup > &Fixups, uint32_t Offset, const MCExpr *Value, uint16_t Kind)
static unsigned getInvertedBranchOp(unsigned BrOp)
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
MCCodeEmitter - Generic instruction encoding interface.
virtual void encodeInstruction(const MCInst &Inst, SmallVectorImpl< char > &CB, SmallVectorImpl< MCFixup > &Fixups, const MCSubtargetInfo &STI) const =0
Encode the given Inst to bytes and append to CB.
MCCodeEmitter & operator=(const MCCodeEmitter &)=delete
Context object for machine code objects.
Base class for the full range of assembler expressions which are needed for parsing.
@ SymbolRef
References to labels and assigned expressions.
@ Specifier
Expression with a relocation specifier.
@ Binary
Binary expressions.
static MCFixup create(uint32_t Offset, const MCExpr *Value, MCFixupKind Kind, bool PCRel=false)
Consider bit fields if we need more flags.
MCInstBuilder & addReg(MCRegister Reg)
Add a new register operand.
MCInstBuilder & addOperand(const MCOperand &Op)
Add an operand.
MCInstBuilder & addImm(int64_t Val)
Add a new integer immediate operand.
MCInstBuilder & addExpr(const MCExpr *Val)
Add a new MCExpr operand.
Instances of this class represent a single low-level machine instruction.
Describe properties that are true of each instruction in the target description file.
Interface to description of machine instruction set.
Instances of this class represent operands of the MCInst class.
MCRegister getReg() const
Returns the register number.
const MCExpr * getExpr() const
Wrapper class representing physical registers. Should be passed by value.
constexpr unsigned id() const
Generic base class for all target subtargets.
bool hasFeature(unsigned Feature) const
const FeatureBitset & getFeatureBits() const
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void truncate(size_type N)
Like resize, but requires that N is less than size().
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
LLVM Value Representation.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static unsigned getFormat(uint64_t TSFlags)
static MCRegister getTailExpandUseRegNo(const FeatureBitset &FeatureBits)
@ InstFormatNDS_BRANCH_10
@ fixup_riscv_pcrel_lo12_i
@ fixup_riscv_pcrel_lo12_s
@ fixup_riscv_nds_branch_10
@ fixup_riscv_qc_e_call_plt
@ fixup_riscv_qc_e_branch
NodeAddr< FuncNode * > Func
void write(void *memory, value_type value, endianness endian)
Write a value to memory with a particular endianness.
This is an optimization pass for GlobalISel generic memory operations.
MCCodeEmitter * createRISCVMCCodeEmitter(const MCInstrInfo &MCII, MCContext &Ctx)
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Description of the encoding of one expression Op.