1 //===-- IntelJITEventListener.cpp - Tell Intel profiler about JITed code --===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines a JITEventListener object to tell Intel(R) VTune(TM)
11 // Amplifier XE 2011 about JITted functions.
13 //===----------------------------------------------------------------------===//
15 #include "llvm/Config/config.h"
16 #include "llvm/ExecutionEngine/JITEventListener.h"
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/Support/Debug.h"
26 #include "llvm/Support/raw_ostream.h"
27 #include "llvm/Support/Errno.h"
28 #include "llvm/Support/ValueHandle.h"
29 #include "EventListenerCommon.h"
30 #include "IntelJITEventsWrapper.h"
33 using namespace llvm::jitprofiling;
37 class IntelJITEventListener : public JITEventListener {
38 typedef DenseMap<void*, unsigned int> MethodIDMap;
40 OwningPtr<IntelJITEventsWrapper> Wrapper;
41 MethodIDMap MethodIDs;
42 FilenameCache Filenames;
45 IntelJITEventListener(IntelJITEventsWrapper* libraryWrapper) {
46 Wrapper.reset(libraryWrapper);
49 ~IntelJITEventListener() {
52 virtual void NotifyFunctionEmitted(const Function &F,
53 void *FnStart, size_t FnSize,
54 const EmittedFunctionDetails &Details);
56 virtual void NotifyFreeingMachineCode(void *OldPtr);
58 virtual void NotifyObjectEmitted(const ObjectImage &Obj);
60 virtual void NotifyFreeingObject(const ObjectImage &Obj);
63 static LineNumberInfo LineStartToIntelJITFormat(
64 uintptr_t StartAddress,
67 LineNumberInfo Result;
69 Result.Offset = Address - StartAddress;
70 Result.LineNumber = Loc.getLine();
75 static iJIT_Method_Load FunctionDescToIntelJITFormat(
76 IntelJITEventsWrapper& Wrapper,
80 iJIT_Method_Load Result;
81 memset(&Result, 0, sizeof(iJIT_Method_Load));
83 Result.method_id = Wrapper.iJIT_GetNewMethodID();
84 Result.method_name = const_cast<char*>(FnName);
85 Result.method_load_address = reinterpret_cast<void*>(FnStart);
86 Result.method_size = FnSize;
89 Result.class_file_name = NULL;
90 Result.user_data = NULL;
91 Result.user_data_size = 0;
92 Result.env = iJDE_JittingAPI;
97 // Adds the just-emitted function to the symbol table.
98 void IntelJITEventListener::NotifyFunctionEmitted(
99 const Function &F, void *FnStart, size_t FnSize,
100 const EmittedFunctionDetails &Details) {
101 iJIT_Method_Load FunctionMessage = FunctionDescToIntelJITFormat(*Wrapper,
103 reinterpret_cast<uint64_t>(FnStart),
106 std::vector<LineNumberInfo> LineInfo;
108 if (!Details.LineStarts.empty()) {
109 // Now convert the line number information from the address/DebugLoc
110 // format in Details to the offset/lineno in Intel JIT API format.
112 LineInfo.reserve(Details.LineStarts.size() + 1);
114 DebugLoc FirstLoc = Details.LineStarts[0].Loc;
115 assert(!FirstLoc.isUnknown()
116 && "LineStarts should not contain unknown DebugLocs");
118 MDNode *FirstLocScope = FirstLoc.getScope(F.getContext());
119 DISubprogram FunctionDI = getDISubprogram(FirstLocScope);
120 if (FunctionDI.Verify()) {
121 FunctionMessage.source_file_name = const_cast<char*>(
122 Filenames.getFullPath(FirstLocScope));
124 LineNumberInfo FirstLine;
125 FirstLine.Offset = 0;
126 FirstLine.LineNumber = FunctionDI.getLineNumber();
127 LineInfo.push_back(FirstLine);
130 for (std::vector<EmittedFunctionDetails::LineStart>::const_iterator I =
131 Details.LineStarts.begin(), E = Details.LineStarts.end();
133 // This implementation ignores the DebugLoc filename because the Intel
134 // JIT API does not support multiple source files associated with a single
136 LineInfo.push_back(LineStartToIntelJITFormat(
137 reinterpret_cast<uintptr_t>(FnStart),
141 // If we have no file name yet for the function, use the filename from
142 // the first instruction that has one
143 if (FunctionMessage.source_file_name == 0) {
144 MDNode *scope = I->Loc.getScope(
145 Details.MF->getFunction()->getContext());
146 FunctionMessage.source_file_name = const_cast<char*>(
147 Filenames.getFullPath(scope));
151 FunctionMessage.line_number_size = LineInfo.size();
152 FunctionMessage.line_number_table = &*LineInfo.begin();
154 FunctionMessage.line_number_size = 0;
155 FunctionMessage.line_number_table = 0;
158 Wrapper->iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED,
160 MethodIDs[FnStart] = FunctionMessage.method_id;
163 void IntelJITEventListener::NotifyFreeingMachineCode(void *FnStart) {
164 MethodIDMap::iterator I = MethodIDs.find(FnStart);
165 if (I != MethodIDs.end()) {
166 Wrapper->iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_UNLOAD_START, &I->second);
171 void IntelJITEventListener::NotifyObjectEmitted(const ObjectImage &Obj) {
174 void IntelJITEventListener::NotifyFreeingObject(const ObjectImage &Obj) {
177 } // anonymous namespace.
180 JITEventListener *JITEventListener::createIntelJITEventListener() {
181 return new IntelJITEventListener(new IntelJITEventsWrapper);
185 JITEventListener *JITEventListener::createIntelJITEventListener(
186 IntelJITEventsWrapper* TestImpl) {
187 return new IntelJITEventListener(TestImpl);