IntelJITEventListener.cpp revision 239462
1234285Sdim//===-- IntelJITEventListener.cpp - Tell Intel profiler about JITed code --===// 2234285Sdim// 3234285Sdim// The LLVM Compiler Infrastructure 4234285Sdim// 5234285Sdim// This file is distributed under the University of Illinois Open Source 6234285Sdim// License. See LICENSE.TXT for details. 7234285Sdim// 8234285Sdim//===----------------------------------------------------------------------===// 9234285Sdim// 10234285Sdim// This file defines a JITEventListener object to tell Intel(R) VTune(TM) 11234285Sdim// Amplifier XE 2011 about JITted functions. 12234285Sdim// 13234285Sdim//===----------------------------------------------------------------------===// 14234285Sdim 15234285Sdim#include "llvm/Config/config.h" 16234285Sdim#include "llvm/ExecutionEngine/JITEventListener.h" 17234285Sdim 18234285Sdim#define DEBUG_TYPE "amplifier-jit-event-listener" 19239462Sdim#include "llvm/DebugInfo.h" 20234285Sdim#include "llvm/Function.h" 21234285Sdim#include "llvm/Metadata.h" 22234285Sdim#include "llvm/ADT/DenseMap.h" 23234285Sdim#include "llvm/ADT/OwningPtr.h" 24234285Sdim#include "llvm/CodeGen/MachineFunction.h" 25234285Sdim#include "llvm/ExecutionEngine/IntelJITEventsWrapper.h" 26234285Sdim#include "llvm/Support/Debug.h" 27234285Sdim#include "llvm/Support/raw_ostream.h" 28234285Sdim#include "llvm/Support/Errno.h" 29234285Sdim#include "llvm/Support/ValueHandle.h" 30234285Sdim#include "EventListenerCommon.h" 31234285Sdim 32234285Sdimusing namespace llvm; 33234285Sdimusing namespace llvm::jitprofiling; 34234285Sdim 35234285Sdimnamespace { 36234285Sdim 37234285Sdimclass IntelJITEventListener : public JITEventListener { 38234285Sdim typedef DenseMap<void*, unsigned int> MethodIDMap; 39234285Sdim 40234285Sdim IntelJITEventsWrapper& Wrapper; 41234285Sdim MethodIDMap MethodIDs; 42234285Sdim FilenameCache Filenames; 43234285Sdim 44234285Sdimpublic: 45234285Sdim IntelJITEventListener(IntelJITEventsWrapper& libraryWrapper) 46234285Sdim : Wrapper(libraryWrapper) { 47234285Sdim } 48234285Sdim 49234285Sdim ~IntelJITEventListener() { 50234285Sdim } 51234285Sdim 52234285Sdim virtual void NotifyFunctionEmitted(const Function &F, 53234285Sdim void *FnStart, size_t FnSize, 54234285Sdim const EmittedFunctionDetails &Details); 55234285Sdim 56234285Sdim virtual void NotifyFreeingMachineCode(void *OldPtr); 57234285Sdim}; 58234285Sdim 59234285Sdimstatic LineNumberInfo LineStartToIntelJITFormat( 60234285Sdim uintptr_t StartAddress, 61234285Sdim uintptr_t Address, 62234285Sdim DebugLoc Loc) { 63234285Sdim LineNumberInfo Result; 64234285Sdim 65234285Sdim Result.Offset = Address - StartAddress; 66234285Sdim Result.LineNumber = Loc.getLine(); 67234285Sdim 68234285Sdim return Result; 69234285Sdim} 70234285Sdim 71234285Sdimstatic iJIT_Method_Load FunctionDescToIntelJITFormat( 72234285Sdim IntelJITEventsWrapper& Wrapper, 73234285Sdim const char* FnName, 74234285Sdim uintptr_t FnStart, 75234285Sdim size_t FnSize) { 76234285Sdim iJIT_Method_Load Result; 77234285Sdim memset(&Result, 0, sizeof(iJIT_Method_Load)); 78234285Sdim 79234285Sdim Result.method_id = Wrapper.iJIT_GetNewMethodID(); 80234285Sdim Result.method_name = const_cast<char*>(FnName); 81234285Sdim Result.method_load_address = reinterpret_cast<void*>(FnStart); 82234285Sdim Result.method_size = FnSize; 83234285Sdim 84234285Sdim Result.class_id = 0; 85234285Sdim Result.class_file_name = NULL; 86234285Sdim Result.user_data = NULL; 87234285Sdim Result.user_data_size = 0; 88234285Sdim Result.env = iJDE_JittingAPI; 89234285Sdim 90234285Sdim return Result; 91234285Sdim} 92234285Sdim 93234285Sdim// Adds the just-emitted function to the symbol table. 94234285Sdimvoid IntelJITEventListener::NotifyFunctionEmitted( 95234285Sdim const Function &F, void *FnStart, size_t FnSize, 96234285Sdim const EmittedFunctionDetails &Details) { 97234285Sdim iJIT_Method_Load FunctionMessage = FunctionDescToIntelJITFormat(Wrapper, 98234285Sdim F.getName().data(), 99234285Sdim reinterpret_cast<uint64_t>(FnStart), 100234285Sdim FnSize); 101234285Sdim 102234285Sdim std::vector<LineNumberInfo> LineInfo; 103234285Sdim 104234285Sdim if (!Details.LineStarts.empty()) { 105234285Sdim // Now convert the line number information from the address/DebugLoc 106234285Sdim // format in Details to the offset/lineno in Intel JIT API format. 107234285Sdim 108234285Sdim LineInfo.reserve(Details.LineStarts.size() + 1); 109234285Sdim 110234285Sdim DebugLoc FirstLoc = Details.LineStarts[0].Loc; 111234285Sdim assert(!FirstLoc.isUnknown() 112234285Sdim && "LineStarts should not contain unknown DebugLocs"); 113234285Sdim 114234285Sdim MDNode *FirstLocScope = FirstLoc.getScope(F.getContext()); 115234285Sdim DISubprogram FunctionDI = getDISubprogram(FirstLocScope); 116234285Sdim if (FunctionDI.Verify()) { 117234285Sdim FunctionMessage.source_file_name = const_cast<char*>( 118234285Sdim Filenames.getFullPath(FirstLocScope)); 119234285Sdim 120234285Sdim LineNumberInfo FirstLine; 121234285Sdim FirstLine.Offset = 0; 122234285Sdim FirstLine.LineNumber = FunctionDI.getLineNumber(); 123234285Sdim LineInfo.push_back(FirstLine); 124234285Sdim } 125234285Sdim 126234285Sdim for (std::vector<EmittedFunctionDetails::LineStart>::const_iterator I = 127234285Sdim Details.LineStarts.begin(), E = Details.LineStarts.end(); 128234285Sdim I != E; ++I) { 129234285Sdim // This implementation ignores the DebugLoc filename because the Intel 130234285Sdim // JIT API does not support multiple source files associated with a single 131234285Sdim // JIT function 132234285Sdim LineInfo.push_back(LineStartToIntelJITFormat( 133234285Sdim reinterpret_cast<uintptr_t>(FnStart), 134234285Sdim I->Address, 135234285Sdim I->Loc)); 136234285Sdim 137234285Sdim // If we have no file name yet for the function, use the filename from 138234285Sdim // the first instruction that has one 139234285Sdim if (FunctionMessage.source_file_name == 0) { 140234285Sdim MDNode *scope = I->Loc.getScope( 141239462Sdim Details.MF->getFunction()->getContext()); 142234285Sdim FunctionMessage.source_file_name = const_cast<char*>( 143234285Sdim Filenames.getFullPath(scope)); 144234285Sdim } 145234285Sdim } 146234285Sdim 147234285Sdim FunctionMessage.line_number_size = LineInfo.size(); 148234285Sdim FunctionMessage.line_number_table = &*LineInfo.begin(); 149234285Sdim } else { 150234285Sdim FunctionMessage.line_number_size = 0; 151234285Sdim FunctionMessage.line_number_table = 0; 152234285Sdim } 153234285Sdim 154234285Sdim Wrapper.iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, 155239462Sdim &FunctionMessage); 156234285Sdim MethodIDs[FnStart] = FunctionMessage.method_id; 157234285Sdim} 158234285Sdim 159234285Sdimvoid IntelJITEventListener::NotifyFreeingMachineCode(void *FnStart) { 160234285Sdim MethodIDMap::iterator I = MethodIDs.find(FnStart); 161234285Sdim if (I != MethodIDs.end()) { 162234285Sdim Wrapper.iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_UNLOAD_START, &I->second); 163234285Sdim MethodIDs.erase(I); 164234285Sdim } 165234285Sdim} 166234285Sdim 167234285Sdim} // anonymous namespace. 168234285Sdim 169234285Sdimnamespace llvm { 170234285SdimJITEventListener *JITEventListener::createIntelJITEventListener() { 171234285Sdim static OwningPtr<IntelJITEventsWrapper> JITProfilingWrapper( 172234285Sdim new IntelJITEventsWrapper); 173234285Sdim return new IntelJITEventListener(*JITProfilingWrapper); 174234285Sdim} 175234285Sdim 176234285Sdim// for testing 177234285SdimJITEventListener *JITEventListener::createIntelJITEventListener( 178234285Sdim IntelJITEventsWrapper* TestImpl) { 179234285Sdim return new IntelJITEventListener(*TestImpl); 180234285Sdim} 181234285Sdim 182234285Sdim} // namespace llvm 183234285Sdim 184