[MCJIT] Remove JITEventListener::NotifyFunctionEmitted - this method is dead
[oota-llvm.git] / lib / ExecutionEngine / IntelJITEvents / IntelJITEventListener.cpp
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 #include "llvm/IR/DebugInfo.h"
19 #include "llvm/IR/Function.h"
20 #include "llvm/IR/Metadata.h"
21 #include "llvm/ADT/DenseMap.h"
22 #include "llvm/CodeGen/MachineFunction.h"
23 #include "llvm/DebugInfo/DIContext.h"
24 #include "llvm/ExecutionEngine/ObjectImage.h"
25 #include "llvm/Object/ObjectFile.h"
26 #include "llvm/Support/Debug.h"
27 #include "llvm/Support/raw_ostream.h"
28 #include "llvm/Support/Errno.h"
29 #include "llvm/IR/ValueHandle.h"
30 #include "EventListenerCommon.h"
31 #include "IntelJITEventsWrapper.h"
32
33 using namespace llvm;
34 using namespace llvm::jitprofiling;
35
36 #define DEBUG_TYPE "amplifier-jit-event-listener"
37
38 namespace {
39
40 class IntelJITEventListener : public JITEventListener {
41   typedef DenseMap<void*, unsigned int> MethodIDMap;
42
43   std::unique_ptr<IntelJITEventsWrapper> Wrapper;
44   MethodIDMap MethodIDs;
45   FilenameCache Filenames;
46
47   typedef SmallVector<const void *, 64> MethodAddressVector;
48   typedef DenseMap<const void *, MethodAddressVector>  ObjectMap;
49
50   ObjectMap  LoadedObjectMap;
51
52 public:
53   IntelJITEventListener(IntelJITEventsWrapper* libraryWrapper) {
54       Wrapper.reset(libraryWrapper);
55   }
56
57   ~IntelJITEventListener() {
58   }
59
60   virtual void NotifyFreeingMachineCode(void *OldPtr);
61
62   virtual void NotifyObjectEmitted(const ObjectImage &Obj);
63
64   virtual void NotifyFreeingObject(const ObjectImage &Obj);
65 };
66
67 static LineNumberInfo DILineInfoToIntelJITFormat(uintptr_t StartAddress,
68                                                  uintptr_t Address,
69                                                  DILineInfo Line) {
70   LineNumberInfo Result;
71
72   Result.Offset = Address - StartAddress;
73   Result.LineNumber = Line.Line;
74
75   return Result;
76 }
77
78 static iJIT_Method_Load FunctionDescToIntelJITFormat(
79     IntelJITEventsWrapper& Wrapper,
80     const char* FnName,
81     uintptr_t FnStart,
82     size_t FnSize) {
83   iJIT_Method_Load Result;
84   memset(&Result, 0, sizeof(iJIT_Method_Load));
85
86   Result.method_id = Wrapper.iJIT_GetNewMethodID();
87   Result.method_name = const_cast<char*>(FnName);
88   Result.method_load_address = reinterpret_cast<void*>(FnStart);
89   Result.method_size = FnSize;
90
91   Result.class_id = 0;
92   Result.class_file_name = NULL;
93   Result.user_data = NULL;
94   Result.user_data_size = 0;
95   Result.env = iJDE_JittingAPI;
96
97   return Result;
98 }
99
100 void IntelJITEventListener::NotifyFreeingMachineCode(void *FnStart) {
101   MethodIDMap::iterator I = MethodIDs.find(FnStart);
102   if (I != MethodIDs.end()) {
103     Wrapper->iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_UNLOAD_START, &I->second);
104     MethodIDs.erase(I);
105   }
106 }
107
108 void IntelJITEventListener::NotifyObjectEmitted(const ObjectImage &Obj) {
109   // Get the address of the object image for use as a unique identifier
110   const void* ObjData = Obj.getData().data();
111   DIContext* Context = DIContext::getDWARFContext(*Obj.getObjectFile());
112   MethodAddressVector Functions;
113
114   // Use symbol info to iterate functions in the object.
115   for (object::symbol_iterator I = Obj.begin_symbols(),
116                                E = Obj.end_symbols();
117                         I != E;
118                         ++I) {
119     std::vector<LineNumberInfo> LineInfo;
120     std::string SourceFileName;
121
122     object::SymbolRef::Type SymType;
123     if (I->getType(SymType)) continue;
124     if (SymType == object::SymbolRef::ST_Function) {
125       StringRef  Name;
126       uint64_t   Addr;
127       uint64_t   Size;
128       if (I->getName(Name)) continue;
129       if (I->getAddress(Addr)) continue;
130       if (I->getSize(Size)) continue;
131
132       // Record this address in a local vector
133       Functions.push_back((void*)Addr);
134
135       // Build the function loaded notification message
136       iJIT_Method_Load FunctionMessage = FunctionDescToIntelJITFormat(*Wrapper,
137                                            Name.data(),
138                                            Addr,
139                                            Size);
140       if (Context) {
141         DILineInfoTable  Lines = Context->getLineInfoForAddressRange(Addr, Size);
142         DILineInfoTable::iterator  Begin = Lines.begin();
143         DILineInfoTable::iterator  End = Lines.end();
144         for (DILineInfoTable::iterator It = Begin; It != End; ++It) {
145           LineInfo.push_back(DILineInfoToIntelJITFormat((uintptr_t)Addr,
146                                                         It->first,
147                                                         It->second));
148         }
149         if (LineInfo.size() == 0) {
150           FunctionMessage.source_file_name = 0;
151           FunctionMessage.line_number_size = 0;
152           FunctionMessage.line_number_table = 0;
153         } else {
154           SourceFileName = Lines.front().second.FileName;
155           FunctionMessage.source_file_name = const_cast<char *>(SourceFileName.c_str());
156           FunctionMessage.line_number_size = LineInfo.size();
157           FunctionMessage.line_number_table = &*LineInfo.begin();
158         }
159       } else {
160         FunctionMessage.source_file_name = 0;
161         FunctionMessage.line_number_size = 0;
162         FunctionMessage.line_number_table = 0;
163       }
164
165       Wrapper->iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED,
166                                 &FunctionMessage);
167       MethodIDs[(void*)Addr] = FunctionMessage.method_id;
168     }
169   }
170
171   // To support object unload notification, we need to keep a list of
172   // registered function addresses for each loaded object.  We will
173   // use the MethodIDs map to get the registered ID for each function.
174   LoadedObjectMap[ObjData] = Functions;
175 }
176
177 void IntelJITEventListener::NotifyFreeingObject(const ObjectImage &Obj) {
178   // Get the address of the object image for use as a unique identifier
179   const void* ObjData = Obj.getData().data();
180
181   // Get the object's function list from LoadedObjectMap
182   ObjectMap::iterator OI = LoadedObjectMap.find(ObjData);
183   if (OI == LoadedObjectMap.end())
184     return;
185   MethodAddressVector& Functions = OI->second;
186
187   // Walk the function list, unregistering each function
188   for (MethodAddressVector::iterator FI = Functions.begin(),
189                                      FE = Functions.end();
190        FI != FE;
191        ++FI) {
192     void* FnStart = const_cast<void*>(*FI);
193     MethodIDMap::iterator MI = MethodIDs.find(FnStart);
194     if (MI != MethodIDs.end()) {
195       Wrapper->iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_UNLOAD_START,
196                                 &MI->second);
197       MethodIDs.erase(MI);
198     }
199   }
200
201   // Erase the object from LoadedObjectMap
202   LoadedObjectMap.erase(OI);
203 }
204
205 }  // anonymous namespace.
206
207 namespace llvm {
208 JITEventListener *JITEventListener::createIntelJITEventListener() {
209   return new IntelJITEventListener(new IntelJITEventsWrapper);
210 }
211
212 // for testing
213 JITEventListener *JITEventListener::createIntelJITEventListener(
214                                       IntelJITEventsWrapper* TestImpl) {
215   return new IntelJITEventListener(TestImpl);
216 }
217
218 } // namespace llvm
219