diff options
Diffstat (limited to 'llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp')
-rw-r--r-- | llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp | 58 |
1 files changed, 52 insertions, 6 deletions
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp index f4eaf06f622..f8212159331 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp @@ -11,6 +11,9 @@ // //===----------------------------------------------------------------------===// +#include "MCTargetDesc/RISCVBaseInfo.h" +#include "MCTargetDesc/RISCVFixupKinds.h" +#include "MCTargetDesc/RISCVMCExpr.h" #include "MCTargetDesc/RISCVMCTargetDesc.h" #include "llvm/ADT/Statistic.h" #include "llvm/MC/MCAsmInfo.h" @@ -18,8 +21,10 @@ #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSymbol.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/EndianStream.h" #include "llvm/Support/raw_ostream.h" @@ -28,15 +33,18 @@ using namespace llvm; #define DEBUG_TYPE "mccodeemitter" STATISTIC(MCNumEmitted, "Number of MC instructions emitted"); +STATISTIC(MCNumFixups, "Number of MC fixups created"); namespace { class RISCVMCCodeEmitter : public MCCodeEmitter { RISCVMCCodeEmitter(const RISCVMCCodeEmitter &) = delete; void operator=(const RISCVMCCodeEmitter &) = delete; MCContext &Ctx; + MCInstrInfo const &MCII; public: - RISCVMCCodeEmitter(MCContext &ctx) : Ctx(ctx) {} + RISCVMCCodeEmitter(MCContext &ctx, MCInstrInfo const &MCII) + : Ctx(ctx), MCII(MCII) {} ~RISCVMCCodeEmitter() override {} @@ -59,6 +67,7 @@ public: unsigned getImmOpValueAsr1(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const; + unsigned getImmOpValue(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const; @@ -68,7 +77,7 @@ public: MCCodeEmitter *llvm::createRISCVMCCodeEmitter(const MCInstrInfo &MCII, const MCRegisterInfo &MRI, MCContext &Ctx) { - return new RISCVMCCodeEmitter(Ctx); + return new RISCVMCCodeEmitter(Ctx, MCII); } void RISCVMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, @@ -107,9 +116,7 @@ RISCVMCCodeEmitter::getImmOpValueAsr1(const MCInst &MI, unsigned OpNo, return Res >> 1; } - llvm_unreachable("Unhandled expression!"); - - return 0; + return getImmOpValue(MI, OpNo, Fixups, STI); } unsigned RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo, @@ -118,11 +125,50 @@ unsigned RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo, const MCOperand &MO = MI.getOperand(OpNo); + MCInstrDesc const &Desc = MCII.get(MI.getOpcode()); + unsigned MIFrm = Desc.TSFlags & RISCVII::InstFormatMask; + // If the destination is an immediate, there is nothing to do if (MO.isImm()) return MO.getImm(); - llvm_unreachable("Unhandled expression!"); + assert(MO.isExpr() && + "getImmOpValue expects only expressions or immediates"); + const MCExpr *Expr = MO.getExpr(); + MCExpr::ExprKind Kind = Expr->getKind(); + RISCV::Fixups FixupKind = RISCV::fixup_riscv_invalid; + if (Kind == MCExpr::Target) { + const RISCVMCExpr *RVExpr = cast<RISCVMCExpr>(Expr); + + switch (RVExpr->getKind()) { + case RISCVMCExpr::VK_RISCV_None: + case RISCVMCExpr::VK_RISCV_Invalid: + llvm_unreachable("Unhandled fixup kind!"); + case RISCVMCExpr::VK_RISCV_LO: + FixupKind = MIFrm == RISCVII::InstFormatI ? RISCV::fixup_riscv_lo12_i + : RISCV::fixup_riscv_lo12_s; + break; + case RISCVMCExpr::VK_RISCV_HI: + FixupKind = RISCV::fixup_riscv_hi20; + break; + case RISCVMCExpr::VK_RISCV_PCREL_HI: + FixupKind = RISCV::fixup_riscv_pcrel_hi20; + break; + } + } else if (Kind == MCExpr::SymbolRef && + cast<MCSymbolRefExpr>(Expr)->getKind() == MCSymbolRefExpr::VK_None) { + if (Desc.getOpcode() == RISCV::JAL) { + FixupKind = RISCV::fixup_riscv_jal; + } else if (MIFrm == RISCVII::InstFormatSB) { + FixupKind = RISCV::fixup_riscv_branch; + } + } + + assert(FixupKind != RISCV::fixup_riscv_invalid && "Unhandled expression!"); + + Fixups.push_back( + MCFixup::create(0, Expr, MCFixupKind(FixupKind), MI.getLoc())); + ++MCNumFixups; return 0; } |