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