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 } 208