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 "../../lib/ExecutionEngine/IntelJITEvents/IntelJITEventsWrapper.h" 17 #include "llvm/ADT/Triple.h" 18 #include "llvm/ExecutionEngine/JITEventListener.h" 19 #include "llvm/ExecutionEngine/MCJIT.h" 20 #include "llvm/ExecutionEngine/SectionMemoryManager.h" 21 #include "llvm/IR/LLVMContext.h" 22 #include "llvm/IR/Module.h" 23 #include "llvm/IRReader/IRReader.h" 24 #include "llvm/Support/CommandLine.h" 25 #include "llvm/Support/Debug.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 "llvm/Support/raw_ostream.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 std::unique_ptr<Module> TheModule(parseIRFile(IRFile, Err, Context)); 118 if (!TheModule) { 119 errs() << Err.getMessage(); 120 return; 121 } 122 123 RTDyldMemoryManager *MemMgr = new SectionMemoryManager(); 124 if (!MemMgr) { 125 errs() << "Unable to create memory manager."; 126 return; 127 } 128 129 // Override the triple to generate ELF on Windows since that's supported 130 Triple Tuple(TheModule->getTargetTriple()); 131 if (Tuple.getTriple().empty()) 132 Tuple.setTriple(sys::getProcessTriple()); 133 134 if (Tuple.isOSWindows() && !Tuple.isOSBinFormatELF()) { 135 Tuple.setObjectFormat(Triple::ELF); 136 TheModule->setTargetTriple(Tuple.getTriple()); 137 } 138 139 // Compile the IR 140 std::string Error; 141 TheJIT.reset(EngineBuilder(std::move(TheModule)) 142 .setEngineKind(EngineKind::JIT) 143 .setErrorStr(&Error) 144 .setMCJITMemoryManager(std::unique_ptr<RTDyldMemoryManager>(MemMgr)) 145 .create()); 146 if (Error.empty() == false) 147 errs() << Error; 148 } 149 150 void DestroyEE() { 151 TheJIT.reset(); 152 } 153 154 LLVMContext Context; // Global ownership 155 std::unique_ptr<ExecutionEngine> TheJIT; 156 157 public: 158 void ProcessInput(const std::string &Filename) { 159 InitEE(Filename); 160 161 std::unique_ptr<llvm::JITEventListener> Listener( 162 JITEventListener::createIntelJITEventListener(new IntelJITEventsWrapper( 163 NotifyEvent, 0, IsProfilingActive, 0, 0, GetNewMethodID))); 164 165 TheJIT->RegisterJITEventListener(Listener.get()); 166 167 TheJIT->finalizeObject(); 168 169 // Destroy the JIT engine instead of unregistering to get unload events. 170 DestroyEE(); 171 } 172 }; 173 174 175 176 } // end anonymous namespace 177 178 static cl::opt<std::string> 179 InputFilename(cl::Positional, cl::desc("<input IR file>"), 180 cl::Required); 181 182 int main(int argc, char **argv) { 183 // Print a stack trace if we signal out. 184 sys::PrintStackTraceOnErrorSignal(); 185 PrettyStackTraceProgram X(argc, argv); 186 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. 187 188 cl::ParseCommandLineOptions(argc, argv, "llvm jit event listener test utility\n"); 189 190 JitEventListenerTest Test; 191 192 Test.ProcessInput(InputFilename); 193 194 return 0; 195 } 196