IntelJITEventListener.cpp revision 239462
1//===-- IntelJITEventListener.cpp - Tell Intel profiler about JITed code --===// 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 file defines a JITEventListener object to tell Intel(R) VTune(TM) 11// Amplifier XE 2011 about JITted functions. 12// 13//===----------------------------------------------------------------------===// 14 15#include "llvm/Config/config.h" 16#include "llvm/ExecutionEngine/JITEventListener.h" 17 18#define DEBUG_TYPE "amplifier-jit-event-listener" 19#include "llvm/DebugInfo.h" 20#include "llvm/Function.h" 21#include "llvm/Metadata.h" 22#include "llvm/ADT/DenseMap.h" 23#include "llvm/ADT/OwningPtr.h" 24#include "llvm/CodeGen/MachineFunction.h" 25#include "llvm/ExecutionEngine/IntelJITEventsWrapper.h" 26#include "llvm/Support/Debug.h" 27#include "llvm/Support/raw_ostream.h" 28#include "llvm/Support/Errno.h" 29#include "llvm/Support/ValueHandle.h" 30#include "EventListenerCommon.h" 31 32using namespace llvm; 33using namespace llvm::jitprofiling; 34 35namespace { 36 37class IntelJITEventListener : public JITEventListener { 38 typedef DenseMap<void*, unsigned int> MethodIDMap; 39 40 IntelJITEventsWrapper& Wrapper; 41 MethodIDMap MethodIDs; 42 FilenameCache Filenames; 43 44public: 45 IntelJITEventListener(IntelJITEventsWrapper& libraryWrapper) 46 : Wrapper(libraryWrapper) { 47 } 48 49 ~IntelJITEventListener() { 50 } 51 52 virtual void NotifyFunctionEmitted(const Function &F, 53 void *FnStart, size_t FnSize, 54 const EmittedFunctionDetails &Details); 55 56 virtual void NotifyFreeingMachineCode(void *OldPtr); 57}; 58 59static LineNumberInfo LineStartToIntelJITFormat( 60 uintptr_t StartAddress, 61 uintptr_t Address, 62 DebugLoc Loc) { 63 LineNumberInfo Result; 64 65 Result.Offset = Address - StartAddress; 66 Result.LineNumber = Loc.getLine(); 67 68 return Result; 69} 70 71static iJIT_Method_Load FunctionDescToIntelJITFormat( 72 IntelJITEventsWrapper& Wrapper, 73 const char* FnName, 74 uintptr_t FnStart, 75 size_t FnSize) { 76 iJIT_Method_Load Result; 77 memset(&Result, 0, sizeof(iJIT_Method_Load)); 78 79 Result.method_id = Wrapper.iJIT_GetNewMethodID(); 80 Result.method_name = const_cast<char*>(FnName); 81 Result.method_load_address = reinterpret_cast<void*>(FnStart); 82 Result.method_size = FnSize; 83 84 Result.class_id = 0; 85 Result.class_file_name = NULL; 86 Result.user_data = NULL; 87 Result.user_data_size = 0; 88 Result.env = iJDE_JittingAPI; 89 90 return Result; 91} 92 93// Adds the just-emitted function to the symbol table. 94void IntelJITEventListener::NotifyFunctionEmitted( 95 const Function &F, void *FnStart, size_t FnSize, 96 const EmittedFunctionDetails &Details) { 97 iJIT_Method_Load FunctionMessage = FunctionDescToIntelJITFormat(Wrapper, 98 F.getName().data(), 99 reinterpret_cast<uint64_t>(FnStart), 100 FnSize); 101 102 std::vector<LineNumberInfo> LineInfo; 103 104 if (!Details.LineStarts.empty()) { 105 // Now convert the line number information from the address/DebugLoc 106 // format in Details to the offset/lineno in Intel JIT API format. 107 108 LineInfo.reserve(Details.LineStarts.size() + 1); 109 110 DebugLoc FirstLoc = Details.LineStarts[0].Loc; 111 assert(!FirstLoc.isUnknown() 112 && "LineStarts should not contain unknown DebugLocs"); 113 114 MDNode *FirstLocScope = FirstLoc.getScope(F.getContext()); 115 DISubprogram FunctionDI = getDISubprogram(FirstLocScope); 116 if (FunctionDI.Verify()) { 117 FunctionMessage.source_file_name = const_cast<char*>( 118 Filenames.getFullPath(FirstLocScope)); 119 120 LineNumberInfo FirstLine; 121 FirstLine.Offset = 0; 122 FirstLine.LineNumber = FunctionDI.getLineNumber(); 123 LineInfo.push_back(FirstLine); 124 } 125 126 for (std::vector<EmittedFunctionDetails::LineStart>::const_iterator I = 127 Details.LineStarts.begin(), E = Details.LineStarts.end(); 128 I != E; ++I) { 129 // This implementation ignores the DebugLoc filename because the Intel 130 // JIT API does not support multiple source files associated with a single 131 // JIT function 132 LineInfo.push_back(LineStartToIntelJITFormat( 133 reinterpret_cast<uintptr_t>(FnStart), 134 I->Address, 135 I->Loc)); 136 137 // If we have no file name yet for the function, use the filename from 138 // the first instruction that has one 139 if (FunctionMessage.source_file_name == 0) { 140 MDNode *scope = I->Loc.getScope( 141 Details.MF->getFunction()->getContext()); 142 FunctionMessage.source_file_name = const_cast<char*>( 143 Filenames.getFullPath(scope)); 144 } 145 } 146 147 FunctionMessage.line_number_size = LineInfo.size(); 148 FunctionMessage.line_number_table = &*LineInfo.begin(); 149 } else { 150 FunctionMessage.line_number_size = 0; 151 FunctionMessage.line_number_table = 0; 152 } 153 154 Wrapper.iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, 155 &FunctionMessage); 156 MethodIDs[FnStart] = FunctionMessage.method_id; 157} 158 159void IntelJITEventListener::NotifyFreeingMachineCode(void *FnStart) { 160 MethodIDMap::iterator I = MethodIDs.find(FnStart); 161 if (I != MethodIDs.end()) { 162 Wrapper.iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_UNLOAD_START, &I->second); 163 MethodIDs.erase(I); 164 } 165} 166 167} // anonymous namespace. 168 169namespace llvm { 170JITEventListener *JITEventListener::createIntelJITEventListener() { 171 static OwningPtr<IntelJITEventsWrapper> JITProfilingWrapper( 172 new IntelJITEventsWrapper); 173 return new IntelJITEventListener(*JITProfilingWrapper); 174} 175 176// for testing 177JITEventListener *JITEventListener::createIntelJITEventListener( 178 IntelJITEventsWrapper* TestImpl) { 179 return new IntelJITEventListener(*TestImpl); 180} 181 182} // namespace llvm 183 184