[Mesa-dev] [PATCH] gallivm: Use the LLVM's C disassembly interface.

Jose Fonseca jfonseca at vmware.com
Fri May 29 04:20:48 PDT 2015


On 28/05/15 19:26, Roland Scheidegger wrote:
> 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.
>>       */
>>
>

I forgot to update configure.ac accordingly and had to do it on a 
follow-up change.

If there are any further build issues with this change let me know.

Jose



More information about the mesa-dev mailing list