[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