[llvm] r313486 - [RISCV] Add support for disassembly
Alex Bradbury via llvm-commits
llvm-commits at lists.llvm.org
Sun Sep 17 07:36:28 PDT 2017
Author: asb
Date: Sun Sep 17 07:36:28 2017
New Revision: 313486
URL: http://llvm.org/viewvc/llvm-project?rev=313486&view=rev
Log:
[RISCV] Add support for disassembly
This Disassembly support allows for 'round-trip' testing, and rv32i-valid.s
has been updated appropriately.
Differential Revision: https://reviews.llvm.org/D23567
Added:
llvm/trunk/lib/Target/RISCV/Disassembler/
llvm/trunk/lib/Target/RISCV/Disassembler/CMakeLists.txt
llvm/trunk/lib/Target/RISCV/Disassembler/LLVMBuild.txt
llvm/trunk/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
Modified:
llvm/trunk/lib/Target/RISCV/CMakeLists.txt
llvm/trunk/lib/Target/RISCV/LLVMBuild.txt
llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp
llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.h
llvm/trunk/lib/Target/RISCV/RISCVInstrFormats.td
llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.td
llvm/trunk/test/MC/RISCV/rv32i-valid.s
Modified: llvm/trunk/lib/Target/RISCV/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/CMakeLists.txt?rev=313486&r1=313485&r2=313486&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/CMakeLists.txt (original)
+++ llvm/trunk/lib/Target/RISCV/CMakeLists.txt Sun Sep 17 07:36:28 2017
@@ -5,6 +5,8 @@ tablegen(LLVM RISCVGenInstrInfo.inc -gen
tablegen(LLVM RISCVGenMCCodeEmitter.inc -gen-emitter)
tablegen(LLVM RISCVGenAsmMatcher.inc -gen-asm-matcher)
tablegen(LLVM RISCVGenAsmWriter.inc -gen-asm-writer)
+tablegen(LLVM RISCVGenSubtargetInfo.inc -gen-subtarget)
+tablegen(LLVM RISCVGenDisassemblerTables.inc -gen-disassembler)
add_public_tablegen_target(RISCVCommonTableGen)
@@ -13,6 +15,7 @@ add_llvm_target(RISCVCodeGen
)
add_subdirectory(AsmParser)
+add_subdirectory(Disassembler)
add_subdirectory(InstPrinter)
add_subdirectory(MCTargetDesc)
add_subdirectory(TargetInfo)
Added: llvm/trunk/lib/Target/RISCV/Disassembler/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/Disassembler/CMakeLists.txt?rev=313486&view=auto
==============================================================================
--- llvm/trunk/lib/Target/RISCV/Disassembler/CMakeLists.txt (added)
+++ llvm/trunk/lib/Target/RISCV/Disassembler/CMakeLists.txt Sun Sep 17 07:36:28 2017
@@ -0,0 +1,3 @@
+add_llvm_library(LLVMRISCVDisassembler
+ RISCVDisassembler.cpp
+ )
Added: llvm/trunk/lib/Target/RISCV/Disassembler/LLVMBuild.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/Disassembler/LLVMBuild.txt?rev=313486&view=auto
==============================================================================
--- llvm/trunk/lib/Target/RISCV/Disassembler/LLVMBuild.txt (added)
+++ llvm/trunk/lib/Target/RISCV/Disassembler/LLVMBuild.txt Sun Sep 17 07:36:28 2017
@@ -0,0 +1,24 @@
+;===- ./lib/Target/RISCV/Disassembler/LLVMBuild.txt ------------*- Conf -*--===;
+;
+; The LLVM Compiler Infrastructure
+;
+; This file is distributed under the University of Illinois Open Source
+; License. See LICENSE.TXT for details.
+;
+;===------------------------------------------------------------------------===;
+;
+; This is an LLVMBuild description file for the components in this subdirectory.
+;
+; For more information on the LLVMBuild system, please see:
+;
+; http://llvm.org/docs/LLVMBuild.html
+;
+;===------------------------------------------------------------------------===;
+
+[component_0]
+type = Library
+name = RISCVDisassembler
+parent = RISCV
+required_libraries = MCDisassembler RISCVInfo Support
+add_to_library_groups = RISCV
+
Added: llvm/trunk/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp?rev=313486&view=auto
==============================================================================
--- llvm/trunk/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp (added)
+++ llvm/trunk/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp Sun Sep 17 07:36:28 2017
@@ -0,0 +1,135 @@
+//===-- RISCVDisassembler.cpp - Disassembler for RISCV --------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the RISCVDisassembler class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MCTargetDesc/RISCVMCTargetDesc.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCDisassembler/MCDisassembler.h"
+#include "llvm/MC/MCFixedLenDisassembler.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/TargetRegistry.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "riscv-disassembler"
+
+typedef MCDisassembler::DecodeStatus DecodeStatus;
+
+namespace {
+class RISCVDisassembler : public MCDisassembler {
+
+public:
+ RISCVDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx)
+ : MCDisassembler(STI, Ctx) {}
+
+ DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
+ ArrayRef<uint8_t> Bytes, uint64_t Address,
+ raw_ostream &VStream,
+ raw_ostream &CStream) const override;
+};
+} // end anonymous namespace
+
+static MCDisassembler *createRISCVDisassembler(const Target &T,
+ const MCSubtargetInfo &STI,
+ MCContext &Ctx) {
+ return new RISCVDisassembler(STI, Ctx);
+}
+
+extern "C" void LLVMInitializeRISCVDisassembler() {
+ // Register the disassembler for each target.
+ TargetRegistry::RegisterMCDisassembler(getTheRISCV32Target(),
+ createRISCVDisassembler);
+ TargetRegistry::RegisterMCDisassembler(getTheRISCV64Target(),
+ createRISCVDisassembler);
+}
+
+static const unsigned GPRDecoderTable[] = {
+ RISCV::X0_32, RISCV::X1_32, RISCV::X2_32, RISCV::X3_32,
+ RISCV::X4_32, RISCV::X5_32, RISCV::X6_32, RISCV::X7_32,
+ RISCV::X8_32, RISCV::X9_32, RISCV::X10_32, RISCV::X11_32,
+ RISCV::X12_32, RISCV::X13_32, RISCV::X14_32, RISCV::X15_32,
+ RISCV::X16_32, RISCV::X17_32, RISCV::X18_32, RISCV::X19_32,
+ RISCV::X20_32, RISCV::X21_32, RISCV::X22_32, RISCV::X23_32,
+ RISCV::X24_32, RISCV::X25_32, RISCV::X26_32, RISCV::X27_32,
+ RISCV::X28_32, RISCV::X29_32, RISCV::X30_32, RISCV::X31_32
+};
+
+static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, uint64_t RegNo,
+ uint64_t Address,
+ const void *Decoder) {
+ if (RegNo > sizeof(GPRDecoderTable)) {
+ return MCDisassembler::Fail;
+ }
+
+ // We must define our own mapping from RegNo to register identifier.
+ // Accessing index RegNo in the register class will work in the case that
+ // registers were added in ascending order, but not in general.
+ unsigned Reg = GPRDecoderTable[RegNo];
+ Inst.addOperand(MCOperand::createReg(Reg));
+ return MCDisassembler::Success;
+}
+
+template <unsigned N>
+static DecodeStatus decodeUImmOperand(MCInst &Inst, uint64_t Imm,
+ int64_t Address, const void *Decoder) {
+ assert(isUInt<N>(Imm) && "Invalid immediate");
+ Inst.addOperand(MCOperand::createImm(Imm));
+ return MCDisassembler::Success;
+}
+
+template <unsigned N>
+static DecodeStatus decodeSImmOperand(MCInst &Inst, uint64_t Imm,
+ int64_t Address, const void *Decoder) {
+ assert(isUInt<N>(Imm) && "Invalid immediate");
+ // Sign-extend the number in the bottom N bits of Imm
+ Inst.addOperand(MCOperand::createImm(SignExtend64<N>(Imm)));
+ return MCDisassembler::Success;
+}
+
+template <unsigned N>
+static DecodeStatus decodeSImmOperandAndLsl1(MCInst &Inst, uint64_t Imm,
+ int64_t Address,
+ const void *Decoder) {
+ assert(isUInt<N>(Imm) && "Invalid immediate");
+ // Sign-extend the number in the bottom N bits of Imm after accounting for
+ // the fact that the N bit immediate is stored in N-1 bits (the LSB is
+ // always zero)
+ Inst.addOperand(MCOperand::createImm(SignExtend64<N>(Imm << 1)));
+ return MCDisassembler::Success;
+}
+
+#include "RISCVGenDisassemblerTables.inc"
+
+DecodeStatus RISCVDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
+ ArrayRef<uint8_t> Bytes,
+ uint64_t Address,
+ raw_ostream &OS,
+ raw_ostream &CS) const {
+ // TODO: although assuming 4-byte instructions is sufficient for RV32 and
+ // RV64, this will need modification when supporting the compressed
+ // instruction set extension (RVC) which uses 16-bit instructions. Other
+ // instruction set extensions have the option of defining instructions up to
+ // 176 bits wide.
+ Size = 4;
+ if (Bytes.size() < 4) {
+ Size = 0;
+ return MCDisassembler::Fail;
+ }
+
+ // Get the four bytes of the instruction.
+ uint32_t Inst = support::endian::read32le(Bytes.data());
+
+ return decodeInstruction(DecoderTable32, MI, Inst, Address, this, STI);
+}
Modified: llvm/trunk/lib/Target/RISCV/LLVMBuild.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/LLVMBuild.txt?rev=313486&r1=313485&r2=313486&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/LLVMBuild.txt (original)
+++ llvm/trunk/lib/Target/RISCV/LLVMBuild.txt Sun Sep 17 07:36:28 2017
@@ -16,7 +16,7 @@
;===------------------------------------------------------------------------===;
[common]
-subdirectories = AsmParser InstPrinter TargetInfo MCTargetDesc
+subdirectories = AsmParser Disassembler InstPrinter TargetInfo MCTargetDesc
[component_0]
type = TargetGroup
@@ -24,6 +24,7 @@ name = RISCV
parent = Target
has_asmparser = 1
has_asmprinter = 1
+has_disassembler = 1
[component_1]
type = Library
Modified: llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp?rev=313486&r1=313485&r2=313486&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp (original)
+++ llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp Sun Sep 17 07:36:28 2017
@@ -59,6 +59,9 @@ 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;
};
} // end anonymous namespace
@@ -105,6 +108,23 @@ RISCVMCCodeEmitter::getImmOpValueAsr1(co
}
llvm_unreachable("Unhandled expression!");
+
+ return 0;
+}
+
+unsigned RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+
+ const MCOperand &MO = MI.getOperand(OpNo);
+
+ // If the destination is an immediate, there is nothing to do
+ if (MO.isImm())
+ return MO.getImm();
+
+ llvm_unreachable("Unhandled expression!");
+
+ return 0;
}
#include "RISCVGenMCCodeEmitter.inc"
Modified: llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp?rev=313486&r1=313485&r2=313486&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp (original)
+++ llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp Sun Sep 17 07:36:28 2017
@@ -29,6 +29,9 @@
#define GET_REGINFO_MC_DESC
#include "RISCVGenRegisterInfo.inc"
+#define GET_SUBTARGETINFO_MC_DESC
+#include "RISCVGenSubtargetInfo.inc"
+
using namespace llvm;
static MCInstrInfo *createRISCVMCInstrInfo() {
@@ -64,5 +67,6 @@ extern "C" void LLVMInitializeRISCVTarge
TargetRegistry::RegisterMCAsmBackend(*T, createRISCVAsmBackend);
TargetRegistry::RegisterMCCodeEmitter(*T, createRISCVMCCodeEmitter);
TargetRegistry::RegisterMCInstPrinter(*T, createRISCVMCInstPrinter);
+ TargetRegistry::RegisterMCSubtargetInfo(*T, createRISCVMCSubtargetInfoImpl);
}
}
Modified: llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.h?rev=313486&r1=313485&r2=313486&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.h (original)
+++ llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.h Sun Sep 17 07:36:28 2017
@@ -55,4 +55,7 @@ MCObjectWriter *createRISCVELFObjectWrit
#define GET_INSTRINFO_ENUM
#include "RISCVGenInstrInfo.inc"
+#define GET_SUBTARGETINFO_ENUM
+#include "RISCVGenSubtargetInfo.inc"
+
#endif
Modified: llvm/trunk/lib/Target/RISCV/RISCVInstrFormats.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/RISCVInstrFormats.td?rev=313486&r1=313485&r2=313486&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/RISCVInstrFormats.td (original)
+++ llvm/trunk/lib/Target/RISCV/RISCVInstrFormats.td Sun Sep 17 07:36:28 2017
@@ -28,6 +28,11 @@
class RISCVInst<dag outs, dag ins, string asmstr, list<dag> pattern>
: Instruction {
field bits<32> Inst;
+ // SoftFail is a field the disassembler can use to provide a way for
+ // instructions to not match without killing the whole decode process. It is
+ // mainly used for ARM, but Tablegen expects this field to exist or it fails
+ // to build the decode table.
+ field bits<32> SoftFail = 0;
let Size = 4;
bits<7> Opcode = 0;
Modified: llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.td?rev=313486&r1=313485&r2=313486&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.td (original)
+++ llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.td Sun Sep 17 07:36:28 2017
@@ -36,34 +36,42 @@ def FenceArg : AsmOperandClass {
def fencearg : Operand<i32> {
let ParserMatchClass = FenceArg;
let PrintMethod = "printFenceArg";
+ let DecoderMethod = "decodeUImmOperand<4>";
}
def uimm5 : Operand<i32> {
let ParserMatchClass = UImmAsmOperand<5>;
+ let DecoderMethod = "decodeUImmOperand<5>";
}
def simm12 : Operand<i32> {
let ParserMatchClass = SImmAsmOperand<12>;
+ let DecoderMethod = "decodeSImmOperand<12>";
}
def uimm12 : Operand<i32> {
let ParserMatchClass = UImmAsmOperand<12>;
+ let DecoderMethod = "decodeUImmOperand<12>";
}
// A 13-bit signed immediate where the least significant bit is zero.
def simm13_lsb0 : Operand<i32> {
let ParserMatchClass = SImmAsmOperand<13, "Lsb0">;
let EncoderMethod = "getImmOpValueAsr1";
+ let DecoderMethod = "decodeSImmOperandAndLsl1<13>";
}
def uimm20 : Operand<i32> {
let ParserMatchClass = UImmAsmOperand<20>;
+ let EncoderMethod = "getImmOpValue";
+ let DecoderMethod = "decodeUImmOperand<20>";
}
// A 21-bit signed immediate where the least significant bit is zero.
def simm21_lsb0 : Operand<i32> {
let ParserMatchClass = SImmAsmOperand<21, "Lsb0">;
let EncoderMethod = "getImmOpValueAsr1";
+ let DecoderMethod = "decodeSImmOperandAndLsl1<21>";
}
// As noted in RISCVRegisterInfo.td, the hope is that support for
Modified: llvm/trunk/test/MC/RISCV/rv32i-valid.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/RISCV/rv32i-valid.s?rev=313486&r1=313485&r2=313486&view=diff
==============================================================================
--- llvm/trunk/test/MC/RISCV/rv32i-valid.s (original)
+++ llvm/trunk/test/MC/RISCV/rv32i-valid.s Sun Sep 17 07:36:28 2017
@@ -2,6 +2,10 @@
# RUN: | FileCheck -check-prefixes=CHECK,CHECK-INST %s
# RUN: llvm-mc %s -triple=riscv64 -show-encoding \
# RUN: | FileCheck -check-prefixes=CHECK,CHECK-INST %s
+# RUN: llvm-mc -filetype=obj -triple riscv32 < %s \
+# RUN: | llvm-objdump -d - | FileCheck -check-prefix=CHECK-INST %s
+# RUN: llvm-mc -filetype=obj -triple riscv64 < %s \
+# RUN: | llvm-objdump -d - | FileCheck -check-prefix=CHECK-INST %s
# CHECK-INST: lui a0, 2
# CHECK: encoding: [0x37,0x25,0x00,0x00]
More information about the llvm-commits
mailing list