Home | History | Annotate | Download | only in gallivm
      1 /**************************************************************************
      2  *
      3  * Copyright 2009-2011 VMware, Inc.
      4  * All Rights Reserved.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the
      8  * "Software"), to deal in the Software without restriction, including
      9  * without limitation the rights to use, copy, modify, merge, publish,
     10  * distribute, sub license, and/or sell copies of the Software, and to
     11  * permit persons to whom the Software is furnished to do so, subject to
     12  * the following conditions:
     13  *
     14  * The above copyright notice and this permission notice (including the
     15  * next paragraph) shall be included in all copies or substantial portions
     16  * of the Software.
     17  *
     18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
     21  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
     22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     25  *
     26  **************************************************************************/
     27 
     28 #include <stddef.h>
     29 
     30 #include <llvm-c/Core.h>
     31 #include <llvm/Target/TargetMachine.h>
     32 #include <llvm/Target/TargetInstrInfo.h>
     33 #include <llvm/Support/raw_ostream.h>
     34 #include <llvm/Support/MemoryObject.h>
     35 
     36 #if HAVE_LLVM >= 0x0300
     37 #include <llvm/Support/TargetRegistry.h>
     38 #else /* HAVE_LLVM < 0x0300 */
     39 #include <llvm/Target/TargetRegistry.h>
     40 #endif /* HAVE_LLVM < 0x0300 */
     41 
     42 #if HAVE_LLVM >= 0x0209
     43 #include <llvm/Support/Host.h>
     44 #else /* HAVE_LLVM < 0x0209 */
     45 #include <llvm/System/Host.h>
     46 #endif /* HAVE_LLVM < 0x0209 */
     47 
     48 #if HAVE_LLVM >= 0x0207
     49 #include <llvm/MC/MCDisassembler.h>
     50 #include <llvm/MC/MCAsmInfo.h>
     51 #include <llvm/MC/MCInst.h>
     52 #include <llvm/MC/MCInstPrinter.h>
     53 #endif /* HAVE_LLVM >= 0x0207 */
     54 #if HAVE_LLVM >= 0x0301
     55 #include <llvm/MC/MCRegisterInfo.h>
     56 #endif /* HAVE_LLVM >= 0x0301 */
     57 
     58 #include "util/u_math.h"
     59 #include "util/u_debug.h"
     60 
     61 #include "lp_bld_debug.h"
     62 
     63 
     64 
     65 /**
     66  * Check alignment.
     67  *
     68  * It is important that this check is not implemented as a macro or inlined
     69  * function, as the compiler assumptions in respect to alignment of global
     70  * and stack variables would often make the check a no op, defeating the
     71  * whole purpose of the exercise.
     72  */
     73 extern "C" boolean
     74 lp_check_alignment(const void *ptr, unsigned alignment)
     75 {
     76    assert(util_is_power_of_two(alignment));
     77    return ((uintptr_t)ptr & (alignment - 1)) == 0;
     78 }
     79 
     80 
     81 class raw_debug_ostream :
     82    public llvm::raw_ostream
     83 {
     84 private:
     85    uint64_t pos;
     86 
     87 public:
     88    raw_debug_ostream() : pos(0) { }
     89 
     90    void write_impl(const char *Ptr, size_t Size);
     91 
     92 #if HAVE_LLVM >= 0x207
     93    uint64_t current_pos() const { return pos; }
     94    size_t preferred_buffer_size() const { return 512; }
     95 #else
     96    uint64_t current_pos() { return pos; }
     97    size_t preferred_buffer_size() { return 512; }
     98 #endif
     99 };
    100 
    101 
    102 void
    103 raw_debug_ostream::write_impl(const char *Ptr, size_t Size)
    104 {
    105    if (Size > 0) {
    106       char *lastPtr = (char *)&Ptr[Size];
    107       char last = *lastPtr;
    108       *lastPtr = 0;
    109       _debug_printf("%*s", Size, Ptr);
    110       *lastPtr = last;
    111       pos += Size;
    112    }
    113 }
    114 
    115 
    116 /**
    117  * Same as LLVMDumpValue, but through our debugging channels.
    118  */
    119 extern "C" void
    120 lp_debug_dump_value(LLVMValueRef value)
    121 {
    122 #if (defined(PIPE_OS_WINDOWS) && !defined(PIPE_CC_MSVC)) || defined(PIPE_OS_EMBDDED)
    123    raw_debug_ostream os;
    124    llvm::unwrap(value)->print(os);
    125    os.flush();
    126 #else
    127    LLVMDumpValue(value);
    128 #endif
    129 }
    130 
    131 
    132 #if HAVE_LLVM >= 0x0207
    133 /*
    134  * MemoryObject wrapper around a buffer of memory, to be used by MC
    135  * disassembler.
    136  */
    137 class BufferMemoryObject:
    138    public llvm::MemoryObject
    139 {
    140 private:
    141    const uint8_t *Bytes;
    142    uint64_t Length;
    143 public:
    144    BufferMemoryObject(const uint8_t *bytes, uint64_t length) :
    145       Bytes(bytes), Length(length)
    146    {
    147    }
    148 
    149    uint64_t getBase() const
    150    {
    151       return 0;
    152    }
    153 
    154    uint64_t getExtent() const
    155    {
    156       return Length;
    157    }
    158 
    159    int readByte(uint64_t addr, uint8_t *byte) const
    160    {
    161       if (addr > getExtent())
    162          return -1;
    163       *byte = Bytes[addr];
    164       return 0;
    165    }
    166 };
    167 #endif /* HAVE_LLVM >= 0x0207 */
    168 
    169 
    170 /*
    171  * Disassemble a function, using the LLVM MC disassembler.
    172  *
    173  * See also:
    174  * - http://blog.llvm.org/2010/01/x86-disassembler.html
    175  * - http://blog.llvm.org/2010/04/intro-to-llvm-mc-project.html
    176  */
    177 extern "C" void
    178 lp_disassemble(const void* func)
    179 {
    180 #if HAVE_LLVM >= 0x0207
    181    using namespace llvm;
    182 
    183    const uint8_t *bytes = (const uint8_t *)func;
    184 
    185    /*
    186     * Limit disassembly to this extent
    187     */
    188    const uint64_t extent = 96 * 1024;
    189 
    190    uint64_t max_pc = 0;
    191 
    192    /*
    193     * Initialize all used objects.
    194     */
    195 
    196 #if HAVE_LLVM >= 0x0301
    197    std::string Triple = sys::getDefaultTargetTriple();
    198 #else
    199    std::string Triple = sys::getHostTriple();
    200 #endif
    201 
    202    std::string Error;
    203    const Target *T = TargetRegistry::lookupTarget(Triple, Error);
    204 
    205 #if HAVE_LLVM >= 0x0300
    206    OwningPtr<const MCAsmInfo> AsmInfo(T->createMCAsmInfo(Triple));
    207 #else
    208    OwningPtr<const MCAsmInfo> AsmInfo(T->createAsmInfo(Triple));
    209 #endif
    210 
    211    if (!AsmInfo) {
    212       debug_printf("error: no assembly info for target %s\n", Triple.c_str());
    213       return;
    214    }
    215 
    216 #if HAVE_LLVM >= 0x0300
    217    const MCSubtargetInfo *STI = T->createMCSubtargetInfo(Triple, sys::getHostCPUName(), "");
    218    OwningPtr<const MCDisassembler> DisAsm(T->createMCDisassembler(*STI));
    219 #else
    220    OwningPtr<const MCDisassembler> DisAsm(T->createMCDisassembler());
    221 #endif
    222    if (!DisAsm) {
    223       debug_printf("error: no disassembler for target %s\n", Triple.c_str());
    224       return;
    225    }
    226 
    227    raw_debug_ostream Out;
    228 
    229 #if HAVE_LLVM >= 0x0300
    230    unsigned int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
    231 #else
    232    int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
    233 #endif
    234 
    235 #if HAVE_LLVM >= 0x0301
    236    OwningPtr<const MCRegisterInfo> MRI(T->createMCRegInfo(Triple));
    237    if (!MRI) {
    238       debug_printf("error: no register info for target %s\n", Triple.c_str());
    239       return;
    240    }
    241 
    242    OwningPtr<const MCInstrInfo> MII(T->createMCInstrInfo());
    243    if (!MII) {
    244       debug_printf("error: no instruction info for target %s\n", Triple.c_str());
    245       return;
    246    }
    247 #endif
    248 
    249 #if HAVE_LLVM >= 0x0301
    250    OwningPtr<MCInstPrinter> Printer(
    251          T->createMCInstPrinter(AsmPrinterVariant, *AsmInfo, *MII, *MRI, *STI));
    252 #elif HAVE_LLVM == 0x0300
    253    OwningPtr<MCInstPrinter> Printer(
    254          T->createMCInstPrinter(AsmPrinterVariant, *AsmInfo, *STI));
    255 #elif HAVE_LLVM >= 0x0208
    256    OwningPtr<MCInstPrinter> Printer(
    257          T->createMCInstPrinter(AsmPrinterVariant, *AsmInfo));
    258 #else
    259    OwningPtr<MCInstPrinter> Printer(
    260          T->createMCInstPrinter(AsmPrinterVariant, *AsmInfo, Out));
    261 #endif
    262    if (!Printer) {
    263       debug_printf("error: no instruction printer for target %s\n", Triple.c_str());
    264       return;
    265    }
    266 
    267 #if HAVE_LLVM >= 0x0301
    268    TargetOptions options;
    269 #if defined(DEBUG)
    270    options.JITEmitDebugInfo = true;
    271 #endif
    272 #if defined(PIPE_ARCH_X86)
    273    options.StackAlignmentOverride = 4;
    274 #endif
    275 #if defined(DEBUG) || defined(PROFILE)
    276    options.NoFramePointerElim = true;
    277 #endif
    278    TargetMachine *TM = T->createTargetMachine(Triple, sys::getHostCPUName(), "", options);
    279 #elif HAVE_LLVM == 0x0300
    280    TargetMachine *TM = T->createTargetMachine(Triple, sys::getHostCPUName(), "");
    281 #else
    282    TargetMachine *TM = T->createTargetMachine(Triple, "");
    283 #endif
    284 
    285    const TargetInstrInfo *TII = TM->getInstrInfo();
    286 
    287    /*
    288     * Wrap the data in a MemoryObject
    289     */
    290    BufferMemoryObject memoryObject((const uint8_t *)bytes, extent);
    291 
    292    uint64_t pc;
    293    pc = 0;
    294    while (true) {
    295       MCInst Inst;
    296       uint64_t Size;
    297 
    298       /*
    299        * Print address.  We use addresses relative to the start of the function,
    300        * so that between runs.
    301        */
    302 
    303       debug_printf("%6lu:\t", (unsigned long)pc);
    304 
    305       if (!DisAsm->getInstruction(Inst, Size, memoryObject,
    306                                  pc,
    307 #if HAVE_LLVM >= 0x0300
    308 				  nulls(), nulls())) {
    309 #else
    310 				  nulls())) {
    311 #endif
    312          debug_printf("invalid\n");
    313          pc += 1;
    314       }
    315 
    316       /*
    317        * Output the bytes in hexidecimal format.
    318        */
    319 
    320       if (0) {
    321          unsigned i;
    322          for (i = 0; i < Size; ++i) {
    323             debug_printf("%02x ", ((const uint8_t*)bytes)[pc + i]);
    324          }
    325          for (; i < 16; ++i) {
    326             debug_printf("   ");
    327          }
    328       }
    329 
    330       /*
    331        * Print the instruction.
    332        */
    333 
    334 #if HAVE_LLVM >= 0x0300
    335       Printer->printInst(&Inst, Out, "");
    336 #elif HAVE_LLVM >= 0x208
    337       Printer->printInst(&Inst, Out);
    338 #else
    339       Printer->printInst(&Inst);
    340 #endif
    341       Out.flush();
    342 
    343       /*
    344        * Advance.
    345        */
    346 
    347       pc += Size;
    348 
    349 #if HAVE_LLVM >= 0x0300
    350       const MCInstrDesc &TID = TII->get(Inst.getOpcode());
    351 #else
    352       const TargetInstrDesc &TID = TII->get(Inst.getOpcode());
    353 #endif
    354 
    355       /*
    356        * Keep track of forward jumps to a nearby address.
    357        */
    358 
    359       if (TID.isBranch()) {
    360          for (unsigned i = 0; i < Inst.getNumOperands(); ++i) {
    361             const MCOperand &operand = Inst.getOperand(i);
    362             if (operand.isImm()) {
    363                uint64_t jump;
    364 
    365                /*
    366                 * FIXME: Handle both relative and absolute addresses correctly.
    367                 * EDInstInfo actually has this info, but operandTypes and
    368                 * operandFlags enums are not exposed in the public interface.
    369                 */
    370 
    371                if (1) {
    372                   /*
    373                    * PC relative addr.
    374                    */
    375 
    376                   jump = pc + operand.getImm();
    377                } else {
    378                   /*
    379                    * Absolute addr.
    380                    */
    381 
    382                   jump = (uint64_t)operand.getImm();
    383                }
    384 
    385                /*
    386                 * Output the address relative to the function start, given
    387                 * that MC will print the addresses relative the current pc.
    388                 */
    389                debug_printf("\t\t; %lu", (unsigned long)jump);
    390 
    391                /*
    392                 * Ignore far jumps given it could be actually a tail return to
    393                 * a random address.
    394                 */
    395 
    396                if (jump > max_pc &&
    397                    jump < extent) {
    398                   max_pc = jump;
    399                }
    400             }
    401          }
    402       }
    403 
    404       debug_printf("\n");
    405 
    406       /*
    407        * Stop disassembling on return statements, if there is no record of a
    408        * jump to a successive address.
    409        */
    410 
    411       if (TID.isReturn()) {
    412          if (pc > max_pc) {
    413             break;
    414          }
    415       }
    416    }
    417 
    418    /*
    419     * Print GDB command, useful to verify output.
    420     */
    421 
    422    if (0) {
    423       debug_printf("disassemble %p %p\n", bytes, bytes + pc);
    424    }
    425 
    426    debug_printf("\n");
    427 #else /* HAVE_LLVM < 0x0207 */
    428    (void)func;
    429 #endif /* HAVE_LLVM < 0x0207 */
    430 }
    431 
    432