1 //===-- llvm-jitlistener.cpp - Utility for testing MCJIT event listener ---===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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.
14 //===----------------------------------------------------------------------===//
16 #include "llvm/ADT/OwningPtr.h"
17 #include "llvm/ADT/Triple.h"
18 #include "../../lib/ExecutionEngine/IntelJITEvents/IntelJITEventsWrapper.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/LLVMContext.h"
24 #include "llvm/Module.h"
25 #include "llvm/Support/CommandLine.h"
26 #include "llvm/Support/Host.h"
27 #include "llvm/Support/IRReader.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"
40 typedef std::vector<std::pair<std::string, unsigned int> > SourceLocations;
41 typedef std::map<uint64_t, SourceLocations> NativeCodeMap;
43 NativeCodeMap ReportedDebugFuncs;
45 int NotifyEvent(iJIT_JVM_EVENT EventType, void *EventSpecificData) {
47 case iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED: {
48 if (!EventSpecificData) {
50 "Error: The JIT event listener did not provide a event data.";
53 iJIT_Method_Load* msg = static_cast<iJIT_Method_Load*>(EventSpecificData);
55 ReportedDebugFuncs[msg->method_id];
57 outs() << "Method load [" << msg->method_id << "]: " << msg->method_name
58 << ", Size = " << msg->method_size << "\n";
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.";
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";
76 case iJVM_EVENT_TYPE_METHOD_UNLOAD_START: {
77 if (!EventSpecificData) {
79 "Error: The JIT event listener did not provide a event data.";
83 = *reinterpret_cast<unsigned int*>(EventSpecificData);
84 assert(1 == ReportedDebugFuncs.erase(UnloadId));
85 outs() << "Method unload [" << UnloadId << "]\n";
94 iJIT_IsProfilingActiveFlags IsProfilingActive(void) {
95 // for testing, pretend we have an Intel Parallel Amplifier XE 2011
97 return iJIT_SAMPLING_ON;
100 unsigned int GetNewMethodID(void) {
101 static unsigned int id = 0;
105 class JitEventListenerTest {
107 void InitEE(const std::string &IRFile) {
108 LLVMContext &Context = getGlobalContext();
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();
115 // Parse the bitcode...
117 TheModule = ParseIRFile(IRFile, Err, Context);
119 errs() << Err.getMessage();
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();
129 errs() << "Unable to create memory manager.";
133 // Tell the memory manager to poison freed memory so that accessing freed
134 // memory is more easily tested.
135 MemMgr->setPoisonMemory(true);
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(LLVM_HOSTTRIPLE);
142 if (Tuple.isOSWindows() && Triple::ELF != Tuple.getEnvironment()) {
143 Tuple.setEnvironment(Triple::ELF);
144 TheModule->setTargetTriple(Tuple.getTriple());
149 TheJIT.reset(EngineBuilder(TheModule)
150 .setEngineKind(EngineKind::JIT)
152 .setJITMemoryManager(MemMgr)
155 if (Error.empty() == false)
163 LLVMContext Context; // Global ownership
164 Module *TheModule; // Owned by ExecutionEngine.
165 JITMemoryManager *JMM; // Owned by ExecutionEngine.
166 OwningPtr<ExecutionEngine> TheJIT;
169 void ProcessInput(const std::string &Filename) {
172 llvm::OwningPtr<llvm::JITEventListener> Listener(JITEventListener::createIntelJITEventListener(
173 new IntelJITEventsWrapper(NotifyEvent, 0,
174 IsProfilingActive, 0, 0,
177 TheJIT->RegisterJITEventListener(Listener.get());
179 TheJIT->finalizeObject();
181 // Destroy the JIT engine instead of unregistering to get unload events.
188 } // end anonymous namespace
190 static cl::opt<std::string>
191 InputFilename(cl::Positional, cl::desc("<input IR file>"),
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.
200 cl::ParseCommandLineOptions(argc, argv, "llvm jit event listener test utility\n");
202 JitEventListenerTest Test;
204 Test.ProcessInput(InputFilename);