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