1//===-- RISCVMCCodeEmitter.cpp - Convert RISC-V code to machine code ------===// 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-exception 7//===----------------------------------------------------------------------===// 9// This file implements the RISCVMCCodeEmitter class. 11//===----------------------------------------------------------------------===// 33#define DEBUG_TYPE "mccodeemitter" 35STATISTIC(MCNumEmitted,
"Number of MC instructions emitted");
36STATISTIC(MCNumFixups,
"Number of MC fixups created");
40 RISCVMCCodeEmitter(
const RISCVMCCodeEmitter &) =
delete;
41voidoperator=(
const RISCVMCCodeEmitter &) =
delete;
47 : Ctx(ctx), MCII(MCII) {}
49 ~RISCVMCCodeEmitter()
override =
default;
71 /// TableGen'erated function for getting the binary encoding for an 77 /// Return binary encoding of operand. If the machine operand requires 78 /// relocation, record the relocation and return zero. 91unsigned getVMaskReg(
constMCInst &
MI,
unsigned OpNo,
95unsigned getRlistOpValue(
constMCInst &
MI,
unsigned OpNo,
99unsigned getRegReg(
constMCInst &
MI,
unsigned OpNo,
103}
// end anonymous namespace 107returnnew RISCVMCCodeEmitter(Ctx, MCII);
110// Expand PseudoCALL(Reg), PseudoTAIL and PseudoJump to AUIPC and JALR with 111// relocation types. We expand those pseudo-instructions while encoding them, 112// meaning AUIPC and JALR won't go through RISC-V MC to MC compressed 113// instruction transformation. This is acceptable because AUIPC has no 16-bit 114// form and C_JALR has no immediate operand field. We let linker relaxation 115// deal with it. When linker relaxation is enabled, AUIPC and JALR have a 116// chance to relax to JAL. 117// If the C extension is enabled, JAL has a chance relax to C_JAL. 118void RISCVMCCodeEmitter::expandFunctionCall(
constMCInst &
MI,
125if (
MI.getOpcode() == RISCV::PseudoTAIL) {
126 Func =
MI.getOperand(0);
128 }
elseif (
MI.getOpcode() == RISCV::PseudoCALLReg) {
130 Ra =
MI.getOperand(0).getReg();
131 }
elseif (
MI.getOpcode() == RISCV::PseudoCALL) {
134 }
elseif (
MI.getOpcode() == RISCV::PseudoJump) {
136 Ra =
MI.getOperand(0).getReg();
144// Emit AUIPC Ra, Func with R_RISCV_CALL relocation type. 146Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
149if (
MI.getOpcode() == RISCV::PseudoTAIL ||
150MI.getOpcode() == RISCV::PseudoJump)
151// Emit JALR X0, Ra, 0 154// Emit JALR Ra, Ra, 0 156Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
160void RISCVMCCodeEmitter::expandTLSDESCCall(
constMCInst &
MI,
166"Expected expression as first input to TLSDESCCALL");
170 int64_t
Imm =
MI.getOperand(2).getImm();
180// Expand PseudoAddTPRel to a simple ADD with the correct relocation. 181void RISCVMCCodeEmitter::expandAddTPRel(
constMCInst &
MI,
189"Expected thread pointer as second input to TP-relative add");
193"Expected expression as third input to TP-relative add");
197"Expected tprel_add relocation on TP-relative symbol");
199// Emit the correct tprel_add relocation for the symbol. 203// Emit fixup_riscv_relax for tprel_add where the relax feature is enabled. 210// Emit a normal ADD instruction with the given operands. 223case RISCV::PseudoLongBEQ:
225case RISCV::PseudoLongBNE:
227case RISCV::PseudoLongBLT:
229case RISCV::PseudoLongBGE:
231case RISCV::PseudoLongBLTU:
233case RISCV::PseudoLongBGEU:
238// Expand PseudoLongBxx to an inverted conditional branch and an unconditional 240void RISCVMCCodeEmitter::expandLongCondBr(
constMCInst &
MI,
247unsigned Opcode =
MI.getOpcode();
249 Opcode == RISCV::PseudoLongBNE || Opcode == RISCV::PseudoLongBEQ;
251bool UseCompressedBr =
false;
252if (IsEqTest && (STI.
hasFeature(RISCV::FeatureStdExtC) ||
254if (RISCV::X8 <= SrcReg1.
id() && SrcReg1.
id() <= RISCV::X15 &&
255 SrcReg2.
id() == RISCV::X0) {
256 UseCompressedBr =
true;
257 }
elseif (RISCV::X8 <= SrcReg2.
id() && SrcReg2.
id() <= RISCV::X15 &&
258 SrcReg1.
id() == RISCV::X0) {
260 UseCompressedBr =
true;
265if (UseCompressedBr) {
267 Opcode == RISCV::PseudoLongBNE ? RISCV::C_BEQZ : RISCV::C_BNEZ;
281// Save the number fixups. 282size_t FixupStartIndex =
Fixups.size();
284// Emit an unconditional jump to the destination. 290// Drop any fixup added so we can add the correct one. 291Fixups.resize(FixupStartIndex);
300void RISCVMCCodeEmitter::encodeInstruction(
constMCInst &
MI,
305// Get byte count of instruction. 308// RISCVInstrInfo::getInstSizeInBytes expects that the total size of the 309// expanded instructions for each pseudo is correct in the Size field of the 310// tablegen definition for the pseudo. 311switch (
MI.getOpcode()) {
314case RISCV::PseudoCALLReg:
315case RISCV::PseudoCALL:
316case RISCV::PseudoTAIL:
317case RISCV::PseudoJump:
318 expandFunctionCall(
MI, CB, Fixups, STI);
321case RISCV::PseudoAddTPRel:
322 expandAddTPRel(
MI, CB, Fixups, STI);
325case RISCV::PseudoLongBEQ:
326case RISCV::PseudoLongBNE:
327case RISCV::PseudoLongBLT:
328case RISCV::PseudoLongBGE:
329case RISCV::PseudoLongBLTU:
330case RISCV::PseudoLongBGEU:
331 expandLongCondBr(
MI, CB, Fixups, STI);
334case RISCV::PseudoTLSDESCCall:
335 expandTLSDESCCall(
MI, CB, Fixups, STI);
354uint64_tBits = getBinaryCodeForInstr(
MI, Fixups, STI) & 0xffff'ffff'ffffu;
357assert(Encoding[6] == 0 && Encoding[7] == 0 &&
358"Unexpected encoding for 48-bit instruction");
370 ++MCNumEmitted;
// Keep track of the # of mi's emitted. 379return Ctx.getRegisterInfo()->getEncodingValue(MO.
getReg());
389RISCVMCCodeEmitter::getImmOpValueAsr1(
constMCInst &
MI,
unsigned OpNo,
396assert((Res & 1) == 0 &&
"LSB is non-zero");
400return getImmOpValue(
MI, OpNo, Fixups, STI);
406bool EnableRelax = STI.
hasFeature(RISCV::FeatureRelax);
412// If the destination is an immediate, there is nothing to do. 417"getImmOpValue expects only expressions or immediates");
421bool RelaxCandidate =
false;
431// tprel_add is only used to indicate that a relocation should be emitted 432// for an add instruction used in TP-relative addressing. It should not be 433// expanded as if representing an actual instruction operand and so to 434// encounter it here is an error. 436"VK_RISCV_TPREL_ADD should not represent an instruction operand");
444 RelaxCandidate =
true;
448 RelaxCandidate =
true;
457"VK_RISCV_PCREL_LO used with unexpected instruction format");
458 RelaxCandidate =
true;
462 RelaxCandidate =
true;
474"VK_RISCV_TPREL_LO used with unexpected instruction format");
475 RelaxCandidate =
true;
479 RelaxCandidate =
true;
489 RelaxCandidate =
true;
493 RelaxCandidate =
true;
509 cast<MCSymbolRefExpr>(Expr)->getKind() ==
512// FIXME: Sub kind binary exprs have chance of underflow. 532// Ensure an R_RISCV_RELAX relocation will be emitted if linker relaxation is 533// enabled and the current fixup will result in a relocation that may be 535if (EnableRelax && RelaxCandidate) {
546unsigned RISCVMCCodeEmitter::getVMaskReg(
constMCInst &
MI,
unsigned OpNo,
557case RISCV::NoRegister:
562unsigned RISCVMCCodeEmitter::getRlistOpValue(
constMCInst &
MI,
unsigned OpNo,
566assert(MO.
isImm() &&
"Rlist operand must be immediate");
568assert(Imm >= 4 &&
"EABI is currently not implemented");
572unsigned RISCVMCCodeEmitter::getRegReg(
constMCInst &
MI,
unsigned OpNo,
579unsignedOp = Ctx.getRegisterInfo()->getEncodingValue(MO.
getReg());
580unsigned Op1 = Ctx.getRegisterInfo()->getEncodingValue(MO1.
getReg());
585#include "RISCVGenMCCodeEmitter.inc" static unsigned getInvertedBranchOp(unsigned BrOp)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
This class represents an Operation in the Expression.
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
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
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.
@ Target
Target specific expression.
@ Binary
Binary expressions.
static MCFixup create(uint32_t Offset, const MCExpr *Value, MCFixupKind Kind, SMLoc Loc=SMLoc())
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
VariantKind getKind() const
@ VK_RISCV_TLSDESC_ADD_LO
@ VK_RISCV_TLSDESC_LOAD_LO
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.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static unsigned getFormat(uint64_t TSFlags)
static unsigned getTailExpandUseRegNo(const FeatureBitset &FeatureBits)
@ fixup_riscv_tprel_lo12_s
@ fixup_riscv_tls_got_hi20
@ fixup_riscv_tls_gd_hi20
@ fixup_riscv_pcrel_lo12_i
@ fixup_riscv_tlsdesc_call
@ fixup_riscv_pcrel_lo12_s
@ fixup_riscv_tprel_lo12_i
@ fixup_riscv_tlsdesc_load_lo12
@ fixup_riscv_tlsdesc_hi20
@ fixup_riscv_tlsdesc_add_lo12
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)
MCFixupKind
Extensible enumeration to represent the type of a fixup.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Description of the encoding of one expression Op.