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