Skip to content

Commit

Permalink
[WIP] Implements LLVM based disassembler for the debugger.
Browse files Browse the repository at this point in the history
This will work for all of our platforms, x86, ARMv7, and AArch64.
Main issue with this is that LLVM's cmake files aren't correctly finding the LLVM install.
Not sure if this is Ubuntu's issue or not, it may just work on other operating systems.

We could potentially improve this, you can pass in a specific CPU in to the LLVM disassembler. This would probably affect latency times that are
reported by LLVM's disassembly? This needs to be further investigated later.
  • Loading branch information
Sonicadvance1 committed Oct 24, 2014
1 parent 3ab921d commit 7f060ee
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 3 deletions.
14 changes: 14 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,20 @@ if(NOT ANDROID)
message("OpenAL NOT found, disabling OpenAL sound backend")
endif(OPENAL_FOUND)

if (LLVM_DIR)
add_definitions(-DHAS_LLVM=1)
set(HAS_LLVM 1)
find_package(LLVM REQUIRED CONFIG)

include_directories(${LLVM_INCLUDE_DIRS})
add_definitions(${LLVM_DEFINITIONS})

llvm_map_components_to_libnames(LLVM_LIBRARIES all)

message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
endif()

set(USE_X11 0)

if(UNIX AND NOT APPLE)
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/DolphinWX/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ if(ANDROID)
set(CPACK_PACKAGE_EXECUTABLES ${CPACK_PACKAGE_EXECUTABLES} ${DOLPHIN_EXE})
elseif(wxWidgets_FOUND)
add_executable(${DOLPHIN_EXE} ${SRCS} ${GUI_SRCS})
target_link_libraries(${DOLPHIN_EXE} ${LIBS} ${WXLIBS})
target_link_libraries(${DOLPHIN_EXE} ${LIBS} ${WXLIBS} ${LLVM_LIBRARIES})
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
include(BundleUtilities)
set(BUNDLE_PATH ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${DOLPHIN_EXE}.app)
Expand Down
78 changes: 77 additions & 1 deletion Source/Core/DolphinWX/Debugger/JitWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@
#include <disasm.h> // Bochs
#include <sstream>

#if defined(HAS_LLVM)
// PowerPC.h defines PC.
// This conflicts with a function that has an argument named PC
#undef PC
#include <llvm-c/Disassembler.h>
#include <llvm-c/Target.h>
#endif

#include <wx/button.h>
#include <wx/chartype.h>
#include <wx/defs.h>
Expand All @@ -33,6 +41,68 @@
#include "DolphinWX/WxUtils.h"
#include "DolphinWX/Debugger/JitWindow.h"

#if defined(HAS_LLVM)
// This class declaration should be in the header
// Due to the conflict with the PC define and the function with PC as an argument
// it has to be in this file instead.
// Once that conflict is resolved this can be moved to the header
class HostDisassemblerLLVM : public HostDisassembler
{
public:
HostDisassemblerLLVM(const std::string host_disasm);
~HostDisassemblerLLVM()
{
if (m_can_disasm)
LLVMDisasmDispose(m_llvm_context);
}

private:
bool m_can_disasm;
LLVMDisasmContextRef m_llvm_context;

std::string DisassembleHostBlock(const u8* code_start, const u32 code_size, u32* host_instructions_count) override;
};

HostDisassemblerLLVM::HostDisassemblerLLVM(const std::string host_disasm)
: m_can_disasm(false)
{
LLVMInitializeAllTargetInfos();
LLVMInitializeAllTargetMCs();
LLVMInitializeAllDisassemblers();

m_llvm_context = LLVMCreateDisasm(host_disasm.c_str(), nullptr, 0, 0, nullptr);

// Couldn't create llvm context
if (!m_llvm_context)
return;
LLVMSetDisasmOptions(m_llvm_context,
LLVMDisassembler_Option_AsmPrinterVariant |
LLVMDisassembler_Option_PrintLatency);

m_can_disasm = true;
}

std::string HostDisassemblerLLVM::DisassembleHostBlock(const u8* code_start, const u32 code_size, u32 *host_instructions_count)
{
if (!m_can_disasm)
return "(No LLVM context)";

u64 disasmPtr = (u64)code_start;
const u8 *end = code_start + code_size;

std::ostringstream x86_disasm;
while ((u8*)disasmPtr < end)
{
char inst_disasm[256];
disasmPtr += LLVMDisasmInstruction(m_llvm_context, (u8*)disasmPtr, (u64)(end - disasmPtr), (u64)disasmPtr, inst_disasm, 256);
x86_disasm << inst_disasm << std::endl;
(*host_instructions_count)++;
}

return x86_disasm.str();
}
#endif

std::string HostDisassembler::DisassembleBlock(u32* address, u32* host_instructions_count, u32* code_size)
{
if (!jit)
Expand Down Expand Up @@ -143,8 +213,14 @@ CJitWindow::CJitWindow(wxWindow* parent, wxWindowID id, const wxPoint& pos,
sizerSplit->Fit(this);
sizerBig->Fit(this);

#ifdef _M_X86
#if defined(_M_X86) && defined(HAS_LLVM)
m_disassembler.reset(new HostDisassemblerLLVM("x86_64-none-unknown"));
#elif defined(_M_X86)
m_disassembler.reset(new HostDisassemblerX86());
#elif defined(_M_ARM_64) && defined(HAS_LLVM)
m_disassembler.reset(new HostDisassemblerLLVM("aarch64-none-unknown"));
#elif defined(_M_ARM_32) && defined(HAS_LLVM)
m_disassembler.reset(new HostDisassemblerLLVM("armv7-none-unknown"));
#else
m_disassembler.reset(new HostDisassembler());
#endif
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/DolphinWX/Debugger/JitWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class HostDisassembler
std::string DisassembleBlock(u32* address, u32* host_instructions_count, u32* code_size);

private:
virtual std::string DisassembleHostBlock(const u8* code_start, const u32 code_size, u32* host_instructions_count) { return ""; }
virtual std::string DisassembleHostBlock(const u8* code_start, const u32 code_size, u32* host_instructions_count) { return "(No disassembler)"; }
};

class HostDisassemblerX86 : public HostDisassembler
Expand Down

0 comments on commit 7f060ee

Please sign in to comment.