summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
diff options
context:
space:
mode:
authorAlex Bradbury <asb@lowrisc.org>2017-09-28 08:26:24 +0000
committerAlex Bradbury <asb@lowrisc.org>2017-09-28 08:26:24 +0000
commit9d3f12501a4594421a8d07053dd9dbaa652c7418 (patch)
treed802b5c35d624cb00ed2c3e7578b4afa6f3195df /llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
parent07f1e2e2b3880bfc3e470bb111c31028371ab8f3 (diff)
downloadbcm5719-llvm-9d3f12501a4594421a8d07053dd9dbaa652c7418.tar.gz
bcm5719-llvm-9d3f12501a4594421a8d07053dd9dbaa652c7418.zip
[RISCV] Add common fixups and relocations
%lo(), %hi(), and %pcrel_hi() are supported and test cases have been added to ensure the appropriate fixups and relocations are generated. I've added an instruction format field which is used in RISCVMCCodeEmitter to, for instance, tell whether it should emit a lo12_i fixup or a lo12_s fixup (RISC-V has two 12-bit immediate encodings depending on the instruction type). Differential Revision: https://reviews.llvm.org/D23568 llvm-svn: 314389
Diffstat (limited to 'llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp')
-rw-r--r--llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp58
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;
}
OpenPOWER on IntegriCloud