Split out the IRReader header and the utility functions it provides into
[oota-llvm.git] / tools / llvm-jitlistener / llvm-jitlistener.cpp
1 //===-- llvm-jitlistener.cpp - Utility for testing MCJIT event listener ---===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This program is a used by lit tests to verify the MCJIT JITEventListener
11 // interface.  It registers a mock JIT event listener, generates a module from
12 // an input IR file and dumps the reported event information to stdout.
13 //
14 //===----------------------------------------------------------------------===//
15
16 #include "llvm/IR/LLVMContext.h"
17 #include "../../lib/ExecutionEngine/IntelJITEvents/IntelJITEventsWrapper.h"
18 #include "llvm/ADT/OwningPtr.h"
19 #include "llvm/ADT/Triple.h"
20 #include "llvm/ExecutionEngine/JITEventListener.h"
21 #include "llvm/ExecutionEngine/JITMemoryManager.h"
22 #include "llvm/ExecutionEngine/MCJIT.h"
23 #include "llvm/ExecutionEngine/ObjectImage.h"
24 #include "llvm/IR/Module.h"
25 #include "llvm/IRReader/IRReader.h"
26 #include "llvm/Support/CommandLine.h"
27 #include "llvm/Support/Host.h"
28 #include "llvm/Support/ManagedStatic.h"
29 #include "llvm/Support/MemoryBuffer.h"
30 #include "llvm/Support/PrettyStackTrace.h"
31 #include "llvm/Support/Signals.h"
32 #include "llvm/Support/SourceMgr.h"
33 #include "llvm/Support/TargetSelect.h"
34 #include <string>
35
36 using namespace llvm;
37
38 namespace {
39
40 typedef std::vector<std::pair<std::string, unsigned int> > SourceLocations;
41 typedef std::map<uint64_t, SourceLocations> NativeCodeMap;
42
43 NativeCodeMap  ReportedDebugFuncs;
44
45 int NotifyEvent(iJIT_JVM_EVENT EventType, void *EventSpecificData) {
46   switch (EventType) {
47     case iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED: {
48       if (!EventSpecificData) {
49         errs() <<
50           "Error: The JIT event listener did not provide a event data.";
51         return -1;
52       }
53       iJIT_Method_Load* msg = static_cast<iJIT_Method_Load*>(EventSpecificData);
54
55       ReportedDebugFuncs[msg->method_id];
56
57       outs() << "Method load [" << msg->method_id << "]: " << msg->method_name
58              << ", Size = " << msg->method_size << "\n";
59
60       for(unsigned int i = 0; i < msg->line_number_size; ++i) {
61         if (!msg->line_number_table) {
62           errs() << "A function with a non-zero line count had no line table.";
63           return -1;
64         }
65         std::pair<std::string, unsigned int> loc(
66           std::string(msg->source_file_name),
67           msg->line_number_table[i].LineNumber);
68         ReportedDebugFuncs[msg->method_id].push_back(loc);
69         outs() << "  Line info @ " << msg->line_number_table[i].Offset
70                << ": " << msg->source_file_name
71                << ", line " << msg->line_number_table[i].LineNumber << "\n";
72       }
73       outs() << "\n";
74     }
75     break;
76     case iJVM_EVENT_TYPE_METHOD_UNLOAD_START: {
77       if (!EventSpecificData) {
78         errs() <<
79           "Error: The JIT event listener did not provide a event data.";
80         return -1;
81       }
82       unsigned int UnloadId
83         = *reinterpret_cast<unsigned int*>(EventSpecificData);
84       assert(1 == ReportedDebugFuncs.erase(UnloadId));
85       outs() << "Method unload [" << UnloadId << "]\n";
86     }
87     break;
88     default:
89       break;
90   }
91   return 0;
92 }
93
94 iJIT_IsProfilingActiveFlags IsProfilingActive(void) {
95   // for testing, pretend we have an Intel Parallel Amplifier XE 2011
96   // instance attached
97   return iJIT_SAMPLING_ON;
98 }
99
100 unsigned int GetNewMethodID(void) {
101   static unsigned int id = 0;
102   return ++id;
103 }
104
105 class JitEventListenerTest {
106 protected:
107   void InitEE(const std::string &IRFile) {
108     LLVMContext &Context = getGlobalContext();
109
110     // If we have a native target, initialize it to ensure it is linked in and
111     // usable by the JIT.
112     InitializeNativeTarget();
113     InitializeNativeTargetAsmPrinter();
114
115     // Parse the bitcode...
116     SMDiagnostic Err;
117     TheModule = ParseIRFile(IRFile, Err, Context);
118     if (!TheModule) {
119       errs() << Err.getMessage();
120       return;
121     }
122
123     // FIXME: This is using the default legacy JITMemoryManager because it
124     // supports poison memory.  At some point, we'll need to update this to
125     // use an MCJIT-specific memory manager.  It might be nice to have the
126     // poison memory option there too.
127     JITMemoryManager *MemMgr = JITMemoryManager::CreateDefaultMemManager();
128     if (!MemMgr) {
129       errs() << "Unable to create memory manager.";
130       return;
131     }
132
133     // Tell the memory manager to poison freed memory so that accessing freed
134     // memory is more easily tested.
135     MemMgr->setPoisonMemory(true);
136
137     // Override the triple to generate ELF on Windows since that's supported
138     Triple Tuple(TheModule->getTargetTriple());
139     if (Tuple.getTriple().empty())
140       Tuple.setTriple(sys::getProcessTriple());
141
142     if (Tuple.isOSWindows() && Triple::ELF != Tuple.getEnvironment()) {
143       Tuple.setEnvironment(Triple::ELF);
144       TheModule->setTargetTriple(Tuple.getTriple());
145     }
146
147     // Compile the IR
148     std::string Error;
149     TheJIT.reset(EngineBuilder(TheModule)
150       .setEngineKind(EngineKind::JIT)
151       .setErrorStr(&Error)
152       .setJITMemoryManager(MemMgr)
153       .setUseMCJIT(true)
154       .create());
155     if (Error.empty() == false)
156       errs() << Error;
157   }
158
159   void DestroyEE() {
160     TheJIT.reset();
161   }
162
163   LLVMContext Context; // Global ownership
164   Module *TheModule; // Owned by ExecutionEngine.
165   JITMemoryManager *JMM; // Owned by ExecutionEngine.
166   OwningPtr<ExecutionEngine> TheJIT;
167
168 public:
169   void ProcessInput(const std::string &Filename) {
170     InitEE(Filename);
171
172     llvm::OwningPtr<llvm::JITEventListener> Listener(JITEventListener::createIntelJITEventListener(
173         new IntelJITEventsWrapper(NotifyEvent, 0,
174           IsProfilingActive, 0, 0,
175           GetNewMethodID)));
176
177     TheJIT->RegisterJITEventListener(Listener.get());
178
179     TheJIT->finalizeObject();
180
181     // Destroy the JIT engine instead of unregistering to get unload events.
182     DestroyEE();
183   }
184 };
185
186
187
188 } // end anonymous namespace
189
190 static cl::opt<std::string>
191 InputFilename(cl::Positional, cl::desc("<input IR file>"),
192                cl::Required);
193
194 int main(int argc, char **argv) {
195   // Print a stack trace if we signal out.
196   sys::PrintStackTraceOnErrorSignal();
197   PrettyStackTraceProgram X(argc, argv);
198   llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.
199
200   cl::ParseCommandLineOptions(argc, argv, "llvm jit event listener test utility\n");
201
202   JitEventListenerTest Test;
203
204   Test.ProcessInput(InputFilename);
205
206   return 0;
207 }