gallivm: Use LLVM MC disassembler, instead of udis86.
Included in LLVM 2.7+. Unlink udis86, should support all instructions that LLVM can emit.
This commit is contained in:
parent
d2332569d2
commit
e6314db0ac
|
@ -12,7 +12,7 @@ GALLIUM_DRIVERS_DIRS += llvmpipe
|
|||
OPT_FLAGS = -O3 -ansi -pedantic
|
||||
ARCH_FLAGS = -mmmx -msse -msse2 -mstackrealign
|
||||
|
||||
DEFINES += -DNDEBUG -DGALLIUM_LLVMPIPE -DHAVE_UDIS86
|
||||
DEFINES += -DNDEBUG -DGALLIUM_LLVMPIPE
|
||||
|
||||
# override -std=c99
|
||||
CFLAGS += -std=gnu99
|
||||
|
@ -41,4 +41,4 @@ else
|
|||
endif
|
||||
|
||||
LD = g++
|
||||
GL_LIB_DEPS = $(LLVM_LDFLAGS) $(LLVM_LIBS) $(EXTRA_LIB_PATH) -lX11 -lXext -lm -lpthread -lstdc++ -ludis86
|
||||
GL_LIB_DEPS = $(LLVM_LDFLAGS) $(LLVM_LIBS) $(EXTRA_LIB_PATH) -lX11 -lXext -lm -lpthread -lstdc++
|
||||
|
|
|
@ -1400,8 +1400,6 @@ if test "x$enable_gallium" = xno -a "x$enable_openvg" = xyes; then
|
|||
fi
|
||||
if test "x$enable_gallium" = xyes; then
|
||||
SRC_DIRS="$SRC_DIRS gallium gallium/winsys gallium/targets"
|
||||
AC_CHECK_HEADER([udis86.h], [HAS_UDIS86="yes"],
|
||||
[HAS_UDIS86="no"])
|
||||
AC_PATH_PROG([LLVM_CONFIG], [llvm-config], [no])
|
||||
fi
|
||||
|
||||
|
@ -1653,10 +1651,6 @@ if test "x$enable_gallium_llvm" = xyes; then
|
|||
LLVM_CFLAGS=`$LLVM_CONFIG --cppflags`
|
||||
LLVM_LIBS="`$LLVM_CONFIG --libs jit interpreter nativecodegen bitwriter` -lstdc++"
|
||||
|
||||
if test "x$HAS_UDIS86" != xno; then
|
||||
LLVM_LIBS="$LLVM_LIBS -ludis86"
|
||||
DEFINES="$DEFINES -DHAVE_UDIS86"
|
||||
fi
|
||||
LLVM_LDFLAGS=`$LLVM_CONFIG --ldflags`
|
||||
GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS llvmpipe"
|
||||
DEFINES="$DEFINES -DGALLIUM_LLVMPIPE -D__STDC_CONSTANT_MACROS"
|
||||
|
|
|
@ -602,7 +602,6 @@ def generate(env):
|
|||
env.Tool('yacc')
|
||||
if env['llvm']:
|
||||
env.Tool('llvm')
|
||||
env.Tool('udis86')
|
||||
|
||||
pkg_config_modules(env, 'x11', ['x11', 'xext'])
|
||||
pkg_config_modules(env, 'drm', ['libdrm'])
|
||||
|
|
|
@ -142,7 +142,7 @@ def generate(env):
|
|||
|
||||
try:
|
||||
env.ParseConfig('llvm-config --cppflags')
|
||||
env.ParseConfig('llvm-config --libs jit interpreter nativecodegen bitwriter')
|
||||
env.ParseConfig('llvm-config --libs')
|
||||
env.ParseConfig('llvm-config --ldflags')
|
||||
except OSError:
|
||||
print 'scons: llvm-config version %s failed' % llvm_version
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
"""udis86
|
||||
|
||||
Tool-specific initialization for udis86
|
||||
|
||||
"""
|
||||
|
||||
#
|
||||
# Copyright (c) 2009 VMware, Inc.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining
|
||||
# a copy of this software and associated documentation files (the
|
||||
# "Software"), to deal in the Software without restriction, including
|
||||
# without limitation the rights to use, copy, modify, merge, publish,
|
||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
||||
# permit persons to whom the Software is furnished to do so, subject to
|
||||
# the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included
|
||||
# in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
def generate(env):
|
||||
conf = env.Configure()
|
||||
|
||||
if conf.CheckHeader('udis86.h'): # and conf.CheckLib('udis86'):
|
||||
env['UDIS86'] = True
|
||||
env.Prepend(LIBS = ['udis86'])
|
||||
else:
|
||||
env['UDIS86'] = False
|
||||
|
||||
conf.Finish()
|
||||
|
||||
def exists(env):
|
||||
return True
|
||||
|
||||
# vim:set ts=4 sw=4 et:
|
|
@ -161,7 +161,6 @@ GALLIVM_SOURCES = \
|
|||
gallivm/lp_bld_bitarit.c \
|
||||
gallivm/lp_bld_const.c \
|
||||
gallivm/lp_bld_conv.c \
|
||||
gallivm/lp_bld_debug.c \
|
||||
gallivm/lp_bld_flow.c \
|
||||
gallivm/lp_bld_format_aos.c \
|
||||
gallivm/lp_bld_format_soa.c \
|
||||
|
@ -189,6 +188,7 @@ GALLIVM_SOURCES = \
|
|||
draw/draw_pt_fetch_shade_pipeline_llvm.c
|
||||
|
||||
GALLIVM_CPP_SOURCES = \
|
||||
gallivm/lp_bld_debug.cpp \
|
||||
gallivm/lp_bld_misc.cpp
|
||||
|
||||
GENERATED_SOURCES = \
|
||||
|
|
|
@ -203,16 +203,13 @@ source = [
|
|||
]
|
||||
|
||||
if env['llvm']:
|
||||
if env['UDIS86']:
|
||||
env.Append(CPPDEFINES = [('HAVE_UDIS86', '1')])
|
||||
|
||||
source += [
|
||||
'gallivm/lp_bld_arit.c',
|
||||
'gallivm/lp_bld_assert.c',
|
||||
'gallivm/lp_bld_bitarit.c',
|
||||
'gallivm/lp_bld_const.c',
|
||||
'gallivm/lp_bld_conv.c',
|
||||
'gallivm/lp_bld_debug.c',
|
||||
'gallivm/lp_bld_debug.cpp',
|
||||
'gallivm/lp_bld_flow.c',
|
||||
'gallivm/lp_bld_format_aos.c',
|
||||
'gallivm/lp_bld_format_soa.c',
|
||||
|
|
|
@ -1,141 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2009 VMware, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
#ifdef HAVE_UDIS86
|
||||
#include <udis86.h>
|
||||
#endif
|
||||
|
||||
#include "util/u_math.h"
|
||||
#include "util/u_debug.h"
|
||||
#include "lp_bld_debug.h"
|
||||
|
||||
|
||||
/**
|
||||
* Check alignment.
|
||||
*
|
||||
* It is important that this check is not implemented as a macro or inlined
|
||||
* function, as the compiler assumptions in respect to alignment of global
|
||||
* and stack variables would often make the check a no op, defeating the
|
||||
* whole purpose of the exercise.
|
||||
*/
|
||||
boolean
|
||||
lp_check_alignment(const void *ptr, unsigned alignment)
|
||||
{
|
||||
assert(util_is_power_of_two(alignment));
|
||||
return ((uintptr_t)ptr & (alignment - 1)) == 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lp_disassemble(const void* func)
|
||||
{
|
||||
#ifdef HAVE_UDIS86
|
||||
ud_t ud_obj;
|
||||
uint64_t max_jmp_pc;
|
||||
uint inst_no;
|
||||
boolean emit_addrs = TRUE, emit_line_nos = FALSE;
|
||||
|
||||
ud_init(&ud_obj);
|
||||
|
||||
ud_set_input_buffer(&ud_obj, (void*)func, 0xffff);
|
||||
|
||||
max_jmp_pc = (uint64_t) (uintptr_t) func;
|
||||
ud_set_pc(&ud_obj, max_jmp_pc);
|
||||
|
||||
#ifdef PIPE_ARCH_X86
|
||||
ud_set_mode(&ud_obj, 32);
|
||||
#endif
|
||||
#ifdef PIPE_ARCH_X86_64
|
||||
ud_set_mode(&ud_obj, 64);
|
||||
#endif
|
||||
|
||||
ud_set_syntax(&ud_obj, UD_SYN_ATT);
|
||||
|
||||
while (ud_disassemble(&ud_obj)) {
|
||||
|
||||
if (emit_addrs) {
|
||||
#ifdef PIPE_ARCH_X86
|
||||
debug_printf("0x%08lx:\t", (unsigned long)ud_insn_off(&ud_obj));
|
||||
#endif
|
||||
#ifdef PIPE_ARCH_X86_64
|
||||
debug_printf("0x%016llx:\t", (unsigned long long)ud_insn_off(&ud_obj));
|
||||
#endif
|
||||
}
|
||||
else if (emit_line_nos) {
|
||||
debug_printf("%6d:\t", inst_no);
|
||||
inst_no++;
|
||||
}
|
||||
#if 0
|
||||
debug_printf("%-16s ", ud_insn_hex(&ud_obj));
|
||||
#endif
|
||||
|
||||
debug_printf("%s\n", ud_insn_asm(&ud_obj));
|
||||
|
||||
if(ud_obj.mnemonic != UD_Icall) {
|
||||
unsigned i;
|
||||
for(i = 0; i < 3; ++i) {
|
||||
const struct ud_operand *op = &ud_obj.operand[i];
|
||||
if (op->type == UD_OP_JIMM){
|
||||
uint64_t pc = ud_obj.pc;
|
||||
|
||||
switch (op->size) {
|
||||
case 8:
|
||||
pc += op->lval.sbyte;
|
||||
break;
|
||||
case 16:
|
||||
pc += op->lval.sword;
|
||||
break;
|
||||
case 32:
|
||||
pc += op->lval.sdword;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if(pc > max_jmp_pc)
|
||||
max_jmp_pc = pc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ud_obj.mnemonic == UD_Iinvalid ||
|
||||
(ud_insn_off(&ud_obj) >= max_jmp_pc &&
|
||||
(ud_obj.mnemonic == UD_Iret ||
|
||||
ud_obj.mnemonic == UD_Ijmp)))
|
||||
break;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Print GDB command, useful to verify udis86 output */
|
||||
debug_printf("disassemble %p %p\n", func, (void*)(uintptr_t)ud_obj.pc);
|
||||
#endif
|
||||
|
||||
debug_printf("\n");
|
||||
#else
|
||||
(void)func;
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,355 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2009-2011 VMware, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#include <llvm-c/Core.h>
|
||||
#include <llvm/Target/TargetMachine.h>
|
||||
#include <llvm/Target/TargetRegistry.h>
|
||||
#include <llvm/Target/TargetSelect.h>
|
||||
#include <llvm/Target/TargetInstrInfo.h>
|
||||
#include <llvm/Support/raw_ostream.h>
|
||||
#include <llvm/Support/MemoryObject.h>
|
||||
#include <llvm/System/Host.h>
|
||||
|
||||
#if HAVE_LLVM >= 0x0207
|
||||
#include <llvm/MC/MCDisassembler.h>
|
||||
#include <llvm/MC/MCAsmInfo.h>
|
||||
#include <llvm/MC/MCInst.h>
|
||||
#include <llvm/MC/MCInstPrinter.h>
|
||||
#endif /* HAVE_LLVM >= 0x0207 */
|
||||
|
||||
#include "util/u_math.h"
|
||||
#include "util/u_debug.h"
|
||||
|
||||
#include "lp_bld_debug.h"
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Check alignment.
|
||||
*
|
||||
* It is important that this check is not implemented as a macro or inlined
|
||||
* function, as the compiler assumptions in respect to alignment of global
|
||||
* and stack variables would often make the check a no op, defeating the
|
||||
* whole purpose of the exercise.
|
||||
*/
|
||||
extern "C" boolean
|
||||
lp_check_alignment(const void *ptr, unsigned alignment)
|
||||
{
|
||||
assert(util_is_power_of_two(alignment));
|
||||
return ((uintptr_t)ptr & (alignment - 1)) == 0;
|
||||
}
|
||||
|
||||
|
||||
class raw_debug_ostream :
|
||||
public llvm::raw_ostream
|
||||
{
|
||||
uint64_t pos;
|
||||
|
||||
void write_impl(const char *Ptr, size_t Size);
|
||||
uint64_t current_pos() { return pos; }
|
||||
uint64_t current_pos() const { return pos; }
|
||||
|
||||
#if HAVE_LLVM >= 0x207
|
||||
uint64_t preferred_buffer_size() { return 512; }
|
||||
#else
|
||||
size_t preferred_buffer_size() { return 512; }
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
raw_debug_ostream::write_impl(const char *Ptr, size_t Size)
|
||||
{
|
||||
if (Size > 0) {
|
||||
char *lastPtr = (char *)&Ptr[Size];
|
||||
char last = *lastPtr;
|
||||
*lastPtr = 0;
|
||||
_debug_printf("%*s", Size, Ptr);
|
||||
*lastPtr = last;
|
||||
pos += Size;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Same as LLVMDumpValue, but through our debugging channels.
|
||||
*/
|
||||
extern "C" void
|
||||
lp_debug_dump_value(LLVMValueRef value)
|
||||
{
|
||||
#if (defined(PIPE_OS_WINDOWS) && !defined(PIPE_CC_MSVC)) || defined(PIPE_OS_EMBDDED)
|
||||
raw_debug_ostream os;
|
||||
llvm::unwrap(value)->print(os);
|
||||
os.flush();
|
||||
#else
|
||||
LLVMDumpValue(value);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* MemoryObject wrapper around a buffer of memory, to be used by MC
|
||||
* disassembler.
|
||||
*/
|
||||
class BufferMemoryObject:
|
||||
public llvm::MemoryObject
|
||||
{
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Disassemble a function, using the LLVM MC disassembler.
|
||||
*
|
||||
* See also:
|
||||
* - http://blog.llvm.org/2010/01/x86-disassembler.html
|
||||
* - http://blog.llvm.org/2010/04/intro-to-llvm-mc-project.html
|
||||
*/
|
||||
extern "C" void
|
||||
lp_disassemble(const void* func)
|
||||
{
|
||||
#if HAVE_LLVM >= 0x0207
|
||||
using namespace llvm;
|
||||
|
||||
const uint8_t *bytes = (const uint8_t *)func;
|
||||
|
||||
/*
|
||||
* Limit disassembly to this extent
|
||||
*/
|
||||
const uint64_t extent = 0x10000;
|
||||
|
||||
uint64_t max_pc = 0;
|
||||
|
||||
/*
|
||||
* Initialize all used objects.
|
||||
*/
|
||||
|
||||
std::string Triple = sys::getHostTriple();
|
||||
|
||||
std::string Error;
|
||||
const Target *T = TargetRegistry::lookupTarget(Triple, Error);
|
||||
|
||||
#if HAVE_LLVM >= 0x0208
|
||||
InitializeNativeTargetAsmPrinter();
|
||||
#else
|
||||
InitializeAllAsmPrinters();
|
||||
#endif
|
||||
|
||||
InitializeAllDisassemblers();
|
||||
|
||||
OwningPtr<const MCAsmInfo> AsmInfo(T->createAsmInfo(Triple));
|
||||
|
||||
if (!AsmInfo) {
|
||||
debug_printf("error: no assembly info for target %s\n", Triple.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
OwningPtr<const MCDisassembler> DisAsm(T->createMCDisassembler());
|
||||
if (!DisAsm) {
|
||||
debug_printf("error: no disassembler for target %s\n", Triple.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
raw_debug_ostream Out;
|
||||
|
||||
int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
|
||||
#if HAVE_LLVM >= 0x0208
|
||||
OwningPtr<MCInstPrinter> Printer(
|
||||
T->createMCInstPrinter(AsmPrinterVariant, *AsmInfo));
|
||||
#else
|
||||
OwningPtr<MCInstPrinter> Printer(
|
||||
T->createMCInstPrinter(AsmPrinterVariant, *AsmInfo, Out));
|
||||
#endif
|
||||
if (!Printer) {
|
||||
debug_printf("error: no instruction printer for target %s\n", Triple.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
TargetMachine *TM = T->createTargetMachine(Triple, "");
|
||||
|
||||
const TargetInstrInfo *TII = TM->getInstrInfo();
|
||||
|
||||
/*
|
||||
* Wrap the data in a MemoryObject
|
||||
*/
|
||||
BufferMemoryObject memoryObject((const uint8_t *)bytes, extent);
|
||||
|
||||
uint64_t pc;
|
||||
pc = 0;
|
||||
while (true) {
|
||||
MCInst Inst;
|
||||
uint64_t Size;
|
||||
|
||||
/*
|
||||
* Print address. We use addresses relative to the start of the function,
|
||||
* so that between runs.
|
||||
*/
|
||||
|
||||
debug_printf("%6lu:\t", (unsigned long)pc);
|
||||
|
||||
if (!DisAsm->getInstruction(Inst, Size, memoryObject,
|
||||
pc,
|
||||
nulls())) {
|
||||
debug_printf("invalid\n");
|
||||
pc += 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Output the bytes in hexidecimal format.
|
||||
*/
|
||||
|
||||
if (0) {
|
||||
unsigned i;
|
||||
for (i = 0; i < Size; ++i) {
|
||||
debug_printf("%02x ", ((const uint8_t*)bytes)[pc + i]);
|
||||
}
|
||||
for (; i < 16; ++i) {
|
||||
debug_printf(" ");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Print the instruction.
|
||||
*/
|
||||
|
||||
#if HAVE_LLVM >= 0x208
|
||||
Printer->printInst(&Inst, Out);
|
||||
#else
|
||||
Printer->printInst(&Inst);
|
||||
#endif
|
||||
Out.flush();
|
||||
|
||||
/*
|
||||
* Advance.
|
||||
*/
|
||||
|
||||
pc += Size;
|
||||
|
||||
const TargetInstrDesc &TID = TII->get(Inst.getOpcode());
|
||||
|
||||
/*
|
||||
* Keep track of forward jumps to a nearby address.
|
||||
*/
|
||||
|
||||
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.
|
||||
*/
|
||||
debug_printf("\t\t; %lu", (unsigned long)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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
debug_printf("\n");
|
||||
|
||||
/*
|
||||
* Stop disassembling on return statements, if there is no record of a
|
||||
* jump to a successive address.
|
||||
*/
|
||||
|
||||
if (TID.isReturn()) {
|
||||
if (pc > max_pc) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Print GDB command, useful to verify output.
|
||||
*/
|
||||
|
||||
if (0) {
|
||||
debug_printf("disassemble %p %p\n", bytes, bytes + pc);
|
||||
}
|
||||
|
||||
debug_printf("\n");
|
||||
#else
|
||||
(void)func;
|
||||
#endif
|
||||
}
|
||||
|
|
@ -45,6 +45,11 @@
|
|||
#define GALLIVM_DEBUG_GC (1 << 6)
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
extern unsigned gallivm_debug;
|
||||
#else
|
||||
|
@ -81,4 +86,9 @@ void
|
|||
lp_disassemble(const void* func);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* !LP_BLD_DEBUG_H */
|
||||
|
|
|
@ -46,66 +46,6 @@
|
|||
#include "util/u_debug.h"
|
||||
|
||||
|
||||
#if (defined(PIPE_OS_WINDOWS) && !defined(PIPE_CC_MSVC)) || defined(PIPE_OS_EMBDDED)
|
||||
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
class raw_debug_ostream :
|
||||
public llvm::raw_ostream
|
||||
{
|
||||
uint64_t pos;
|
||||
|
||||
void write_impl(const char *Ptr, size_t Size);
|
||||
uint64_t current_pos() { return pos; }
|
||||
uint64_t current_pos() const { return pos; }
|
||||
|
||||
#if HAVE_LLVM >= 0x207
|
||||
uint64_t preferred_buffer_size() { return 512; }
|
||||
#else
|
||||
size_t preferred_buffer_size() { return 512; }
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
raw_debug_ostream::write_impl(const char *Ptr, size_t Size)
|
||||
{
|
||||
if (Size > 0) {
|
||||
char *lastPtr = (char *)&Ptr[Size];
|
||||
char last = *lastPtr;
|
||||
*lastPtr = 0;
|
||||
_debug_printf("%*s", Size, Ptr);
|
||||
*lastPtr = last;
|
||||
pos += Size;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Same as LLVMDumpValue, but through our debugging channels.
|
||||
*/
|
||||
extern "C" void
|
||||
lp_debug_dump_value(LLVMValueRef value)
|
||||
{
|
||||
raw_debug_ostream os;
|
||||
llvm::unwrap(value)->print(os);
|
||||
os.flush();
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
|
||||
|
||||
extern "C" void
|
||||
lp_debug_dump_value(LLVMValueRef value)
|
||||
{
|
||||
LLVMDumpValue(value);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Register the engine with oprofile.
|
||||
*
|
||||
|
|
|
@ -12,7 +12,7 @@ Requirements
|
|||
|
||||
See /proc/cpuinfo to know what your CPU supports.
|
||||
|
||||
- LLVM 2.6 (or later)
|
||||
- LLVM. Version 2.8 recommended. 2.6 or later required.
|
||||
|
||||
For Linux, on a recent Debian based distribution do:
|
||||
|
||||
|
@ -30,21 +30,8 @@ Requirements
|
|||
debug=no. This is necessary as LLVM builds as static library so the chosen
|
||||
MS CRT must match.
|
||||
|
||||
The version of LLVM from SVN ("2.7svn") from mid-March 2010 is pretty
|
||||
stable and has some features not in version 2.6.
|
||||
|
||||
- scons (optional)
|
||||
|
||||
- udis86, http://udis86.sourceforge.net/ (optional). My personal repository
|
||||
supports more opcodes which haven't been merged upstream yet:
|
||||
|
||||
git clone git://anongit.freedesktop.org/~jrfonseca/udis86
|
||||
cd udis86
|
||||
./autogen.sh
|
||||
./configure --with-pic
|
||||
make
|
||||
sudo make install
|
||||
|
||||
|
||||
Building
|
||||
========
|
||||
|
@ -94,13 +81,7 @@ that no tail call optimizations are done by gcc.
|
|||
|
||||
To better profile JIT code you'll need to build LLVM with oprofile integration.
|
||||
|
||||
source_dir=$PWD/llvm-2.6
|
||||
build_dir=$source_dir/build/profile
|
||||
install_dir=$source_dir-profile
|
||||
|
||||
mkdir -p "$build_dir"
|
||||
cd "$build_dir" && \
|
||||
$source_dir/configure \
|
||||
./configure \
|
||||
--prefix=$install_dir \
|
||||
--enable-optimized \
|
||||
--disable-profiling \
|
||||
|
|
Loading…
Reference in New Issue