[Mesa-dev] [PATCH] gallivm: Use the LLVM's C disassembly interface.
Roland Scheidegger
sroland at vmware.com
Thu May 28 11:26:05 PDT 2015
Looks ok, it's massively simpler and shouldn't break as often.
Reviewed-by: Roland Scheidegger <sroland at vmware.com>
Am 28.05.2015 um 17:57 schrieb Jose Fonseca:
> It doesn't do everything we want. In particular it doesn't allow to
> detect jumps or return opcodes. Currently we detect the x86's RET
> opcode.
>
> Even though it's worse for LLVM 3.3, it's an improvement for LLVM 3.7,
> which was totally busted.
> ---
> scons/llvm.py | 4 +-
> src/gallium/auxiliary/gallivm/lp_bld_debug.cpp | 260 ++++---------------------
> 2 files changed, 40 insertions(+), 224 deletions(-)
>
> diff --git a/scons/llvm.py b/scons/llvm.py
> index 17278df..c59b8cb 100644
> --- a/scons/llvm.py
> +++ b/scons/llvm.py
> @@ -120,6 +120,7 @@ def generate(env):
> ])
> elif llvm_version >= distutils.version.LooseVersion('3.5'):
> env.Prepend(LIBS = [
> + 'LLVMMCDisassembler',
> 'LLVMBitWriter', 'LLVMMCJIT', 'LLVMRuntimeDyld',
> 'LLVMX86Disassembler', 'LLVMX86AsmParser', 'LLVMX86CodeGen',
> 'LLVMSelectionDAG', 'LLVMAsmPrinter', 'LLVMX86Desc',
> @@ -132,6 +133,7 @@ def generate(env):
> ])
> else:
> env.Prepend(LIBS = [
> + 'LLVMMCDisassembler',
> 'LLVMBitWriter', 'LLVMX86Disassembler', 'LLVMX86AsmParser',
> 'LLVMX86CodeGen', 'LLVMX86Desc', 'LLVMSelectionDAG',
> 'LLVMAsmPrinter', 'LLVMMCParser', 'LLVMX86AsmPrinter',
> @@ -189,7 +191,7 @@ def generate(env):
> if '-fno-rtti' in cxxflags:
> env.Append(CXXFLAGS = ['-fno-rtti'])
>
> - components = ['engine', 'mcjit', 'bitwriter', 'x86asmprinter']
> + components = ['engine', 'mcjit', 'bitwriter', 'x86asmprinter', 'mcdisassembler']
>
> env.ParseConfig('llvm-config --libs ' + ' '.join(components))
> env.ParseConfig('llvm-config --ldflags')
> diff --git a/src/gallium/auxiliary/gallivm/lp_bld_debug.cpp b/src/gallium/auxiliary/gallivm/lp_bld_debug.cpp
> index 76c302f..64fb044 100644
> --- a/src/gallium/auxiliary/gallivm/lp_bld_debug.cpp
> +++ b/src/gallium/auxiliary/gallivm/lp_bld_debug.cpp
> @@ -28,40 +28,12 @@
> #include <stddef.h>
>
> #include <llvm-c/Core.h>
> -#include <llvm/Target/TargetMachine.h>
> -#include <llvm/Target/TargetInstrInfo.h>
> +#include <llvm-c/Disassembler.h>
> #include <llvm/Support/raw_ostream.h>
> #include <llvm/Support/Format.h>
> -
> -#if HAVE_LLVM >= 0x0306
> -#include <llvm/Target/TargetSubtargetInfo.h>
> -#else
> -#include <llvm/Support/MemoryObject.h>
> -#endif
> -
> -#include <llvm/Support/TargetRegistry.h>
> -#include <llvm/MC/MCSubtargetInfo.h>
> -
> #include <llvm/Support/Host.h>
> -
> #include <llvm/IR/Module.h>
>
> -#include <llvm/MC/MCDisassembler.h>
> -#include <llvm/MC/MCAsmInfo.h>
> -#include <llvm/MC/MCInst.h>
> -#include <llvm/MC/MCInstPrinter.h>
> -#include <llvm/MC/MCRegisterInfo.h>
> -
> -#if HAVE_LLVM >= 0x0305
> -#define OwningPtr std::unique_ptr
> -#else
> -#include <llvm/ADT/OwningPtr.h>
> -#endif
> -
> -#if HAVE_LLVM >= 0x0305
> -#include <llvm/MC/MCContext.h>
> -#endif
> -
> #include "util/u_math.h"
> #include "util/u_debug.h"
>
> @@ -133,7 +105,7 @@ lp_get_module_id(LLVMModuleRef module)
> extern "C" void
> lp_debug_dump_value(LLVMValueRef value)
> {
> -#if (defined(PIPE_OS_WINDOWS) && !defined(PIPE_CC_MSVC)) || defined(PIPE_OS_EMBDDED)
> +#if (defined(PIPE_OS_WINDOWS) && !defined(PIPE_CC_MSVC)) || defined(PIPE_OS_EMBEDDED)
> raw_debug_ostream os;
> llvm::unwrap(value)->print(os);
> os.flush();
> @@ -143,44 +115,16 @@ lp_debug_dump_value(LLVMValueRef value)
> }
>
>
> -#if HAVE_LLVM < 0x0306
> -
> -/*
> - * MemoryObject wrapper around a buffer of memory, to be used by MC
> - * disassembler.
> - */
> -class BufferMemoryObject:
> - public llvm::MemoryObject
> +static const char *
> +disassemblerSymbolLookupCB(void *DisInfo,
> + uint64_t ReferenceValue,
> + uint64_t *ReferenceType,
> + uint64_t ReferencePC,
> + const char **ReferenceName)
> {
> -private:
> - const uint8_t *Bytes;
> - uint64_t Length;
> -public:
> - BufferMemoryObject(const uint8_t *bytes, uint64_t length) :
> - Bytes(bytes), Length(length)
> - {
> - }
> -
> - uint64_t getBase() const
> - {
> - return 0;
> - }
> -
> - uint64_t getExtent() const
> - {
> - return Length;
> - }
> -
> - int readByte(uint64_t addr, uint8_t *byte) const
> - {
> - if (addr > getExtent())
> - return -1;
> - *byte = Bytes[addr];
> - return 0;
> - }
> -};
> -
> -#endif /* HAVE_LLVM < 0x0306 */
> + // TODO: Maybe this can be used to guess jumps
> + return NULL;
> +}
>
>
> /*
> @@ -193,8 +137,6 @@ public:
> static size_t
> disassemble(const void* func, llvm::raw_ostream & Out)
> {
> - using namespace llvm;
> -
> const uint8_t *bytes = (const uint8_t *)func;
>
> /*
> @@ -202,101 +144,23 @@ disassemble(const void* func, llvm::raw_ostream & Out)
> */
> const uint64_t extent = 96 * 1024;
>
> - uint64_t max_pc = 0;
> -
> /*
> * Initialize all used objects.
> */
>
> - std::string Triple = sys::getDefaultTargetTriple();
> -
> - std::string Error;
> - const Target *T = TargetRegistry::lookupTarget(Triple, Error);
> -
> -#if HAVE_LLVM >= 0x0304
> - OwningPtr<const MCAsmInfo> AsmInfo(T->createMCAsmInfo(*T->createMCRegInfo(Triple), Triple));
> -#else
> - OwningPtr<const MCAsmInfo> AsmInfo(T->createMCAsmInfo(Triple));
> -#endif
> -
> - if (!AsmInfo) {
> - Out << "error: no assembly info for target " << Triple << "\n";
> - Out.flush();
> - return 0;
> - }
> -
> - unsigned int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
> -
> - OwningPtr<const MCRegisterInfo> MRI(T->createMCRegInfo(Triple));
> - if (!MRI) {
> - Out << "error: no register info for target " << Triple.c_str() << "\n";
> - Out.flush();
> - return 0;
> - }
> -
> - OwningPtr<const MCInstrInfo> MII(T->createMCInstrInfo());
> - if (!MII) {
> - Out << "error: no instruction info for target " << Triple.c_str() << "\n";
> - Out.flush();
> - return 0;
> - }
> + std::string Triple = llvm::sys::getProcessTriple();
> + LLVMDisasmContextRef D = LLVMCreateDisasm(Triple.c_str(), NULL, 0, NULL, &disassemblerSymbolLookupCB);
> + char outline[1024];
>
> -#if HAVE_LLVM >= 0x0305
> - OwningPtr<const MCSubtargetInfo> STI(T->createMCSubtargetInfo(Triple, sys::getHostCPUName(), ""));
> - OwningPtr<MCContext> MCCtx(new MCContext(AsmInfo.get(), MRI.get(), 0));
> - OwningPtr<const MCDisassembler> DisAsm(T->createMCDisassembler(*STI, *MCCtx));
> -#else
> - OwningPtr<const MCSubtargetInfo> STI(T->createMCSubtargetInfo(Triple, sys::getHostCPUName(), ""));
> - OwningPtr<const MCDisassembler> DisAsm(T->createMCDisassembler(*STI));
> -#endif
> - if (!DisAsm) {
> - Out << "error: no disassembler for target " << Triple << "\n";
> - Out.flush();
> + if (!D) {
> + Out << "error: couldn't create disassembler for triple " << Triple << "\n";
> return 0;
> }
>
> -
> -#if HAVE_LLVM >= 0x0307
> - OwningPtr<MCInstPrinter> Printer(
> - T->createMCInstPrinter(llvm::Triple(Triple), AsmPrinterVariant, *AsmInfo, *MII, *MRI));
> -#else
> - OwningPtr<MCInstPrinter> Printer(
> - T->createMCInstPrinter(AsmPrinterVariant, *AsmInfo, *MII, *MRI, *STI));
> -#endif
> - if (!Printer) {
> - Out << "error: no instruction printer for target " << Triple.c_str() << "\n";
> - Out.flush();
> - return 0;
> - }
> -
> - TargetOptions options;
> -#if defined(DEBUG) && HAVE_LLVM < 0x0307
> - options.JITEmitDebugInfo = true;
> -#endif
> -#if defined(PIPE_ARCH_X86)
> - options.StackAlignmentOverride = 4;
> -#endif
> -#if defined(DEBUG) || defined(PROFILE)
> -#if HAVE_LLVM < 0x0307
> - options.NoFramePointerElim = true;
> -#endif
> -#endif
> - OwningPtr<TargetMachine> TM(T->createTargetMachine(Triple, sys::getHostCPUName(), "", options));
> -
> - /*
> - * Wrap the data in a MemoryObject
> - */
> -#if HAVE_LLVM >= 0x0306
> - ArrayRef<uint8_t> memoryObject((const uint8_t *)bytes, extent);
> -#else
> - BufferMemoryObject memoryObject((const uint8_t *)bytes, extent);
> -#endif
> -
> uint64_t pc;
> pc = 0;
> - while (true) {
> - MCInst Inst;
> - uint64_t Size;
> + while (pc < extent) {
> + size_t Size;
>
> /*
> * Print address. We use addresses relative to the start of the function,
> @@ -305,11 +169,13 @@ disassemble(const void* func, llvm::raw_ostream & Out)
>
> Out << llvm::format("%6lu:\t", (unsigned long)pc);
>
> - if (!DisAsm->getInstruction(Inst, Size, memoryObject,
> - pc,
> - nulls(), nulls())) {
> - Out << "invalid";
> + Size = LLVMDisasmInstruction(D, (uint8_t *)bytes + pc, extent - pc, 0, outline,
> + sizeof outline);
> +
> + if (!Size) {
> + Out << "invalid\n";
> pc += 1;
> + break;
> }
>
> /*
> @@ -319,7 +185,7 @@ disassemble(const void* func, llvm::raw_ostream & Out)
> if (0) {
> unsigned i;
> for (i = 0; i < Size; ++i) {
> - Out << llvm::format("%02x ", ((const uint8_t*)bytes)[pc + i]);
> + Out << llvm::format("%02x ", bytes[pc + i]);
> }
> for (; i < 16; ++i) {
> Out << " ";
> @@ -329,81 +195,27 @@ disassemble(const void* func, llvm::raw_ostream & Out)
> /*
> * Print the instruction.
> */
> -#if HAVE_LLVM >= 0x0307
> - Printer->printInst(&Inst, Out, "", *STI);
> -#else
> - Printer->printInst(&Inst, Out, "");
> -#endif
>
> - /*
> - * Advance.
> - */
> + Out << outline;
>
> - pc += Size;
> -
> - const MCInstrDesc &TID = MII->get(Inst.getOpcode());
> + Out << "\n";
>
> /*
> - * Keep track of forward jumps to a nearby address.
> + * Stop disassembling on return statements, if there is no record of a
> + * jump to a successive address.
> + *
> + * XXX: This currently assumes x86
> */
>
> - if (TID.isBranch()) {
> - for (unsigned i = 0; i < Inst.getNumOperands(); ++i) {
> - const MCOperand &operand = Inst.getOperand(i);
> - if (operand.isImm()) {
> - uint64_t jump;
> -
> - /*
> - * FIXME: Handle both relative and absolute addresses correctly.
> - * EDInstInfo actually has this info, but operandTypes and
> - * operandFlags enums are not exposed in the public interface.
> - */
> -
> - if (1) {
> - /*
> - * PC relative addr.
> - */
> -
> - jump = pc + operand.getImm();
> - } else {
> - /*
> - * Absolute addr.
> - */
> -
> - jump = (uint64_t)operand.getImm();
> - }
> -
> - /*
> - * Output the address relative to the function start, given
> - * that MC will print the addresses relative the current pc.
> - */
> - Out << "\t\t; " << jump;
> -
> - /*
> - * Ignore far jumps given it could be actually a tail return to
> - * a random address.
> - */
> -
> - if (jump > max_pc &&
> - jump < extent) {
> - max_pc = jump;
> - }
> - }
> - }
> + if (Size == 1 && bytes[pc] == 0xc3) {
> + break;
> }
>
> - Out << "\n";
> -
> /*
> - * Stop disassembling on return statements, if there is no record of a
> - * jump to a successive address.
> + * Advance.
> */
>
> - if (TID.isReturn()) {
> - if (pc > max_pc) {
> - break;
> - }
> - }
> + pc += Size;
>
> if (pc >= extent) {
> Out << "disassembly larger than " << extent << "bytes, aborting\n";
> @@ -414,6 +226,8 @@ disassemble(const void* func, llvm::raw_ostream & Out)
> Out << "\n";
> Out.flush();
>
> + LLVMDisasmDispose(D);
> +
> /*
> * Print GDB command, useful to verify output.
> */
>
More information about the mesa-dev
mailing list