]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - contrib/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp
MFC r244628:
[FreeBSD/stable/9.git] / contrib / llvm / 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 #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"
31
32 using namespace llvm;
33 using namespace llvm::jitprofiling;
34
35 namespace {
36
37 class IntelJITEventListener : public JITEventListener {
38   typedef DenseMap<void*, unsigned int> MethodIDMap;
39
40   OwningPtr<IntelJITEventsWrapper> Wrapper;
41   MethodIDMap MethodIDs;
42   FilenameCache Filenames;
43
44 public:
45   IntelJITEventListener(IntelJITEventsWrapper* libraryWrapper) {
46       Wrapper.reset(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   virtual void NotifyObjectEmitted(const ObjectImage &Obj);
59
60   virtual void NotifyFreeingObject(const ObjectImage &Obj);
61 };
62
63 static LineNumberInfo LineStartToIntelJITFormat(
64     uintptr_t StartAddress,
65     uintptr_t Address,
66     DebugLoc Loc) {
67   LineNumberInfo Result;
68
69   Result.Offset = Address - StartAddress;
70   Result.LineNumber = Loc.getLine();
71
72   return Result;
73 }
74
75 static iJIT_Method_Load FunctionDescToIntelJITFormat(
76     IntelJITEventsWrapper& Wrapper,
77     const char* FnName,
78     uintptr_t FnStart,
79     size_t FnSize) {
80   iJIT_Method_Load Result;
81   memset(&Result, 0, sizeof(iJIT_Method_Load));
82
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;
87
88   Result.class_id = 0;
89   Result.class_file_name = NULL;
90   Result.user_data = NULL;
91   Result.user_data_size = 0;
92   Result.env = iJDE_JittingAPI;
93
94   return Result;
95 }
96
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,
102                                       F.getName().data(),
103                                       reinterpret_cast<uint64_t>(FnStart),
104                                       FnSize);
105
106   std::vector<LineNumberInfo> LineInfo;
107
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.
111
112     LineInfo.reserve(Details.LineStarts.size() + 1);
113
114     DebugLoc FirstLoc = Details.LineStarts[0].Loc;
115     assert(!FirstLoc.isUnknown()
116            && "LineStarts should not contain unknown DebugLocs");
117
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));
123
124       LineNumberInfo FirstLine;
125       FirstLine.Offset = 0;
126       FirstLine.LineNumber = FunctionDI.getLineNumber();
127       LineInfo.push_back(FirstLine);
128     }
129
130     for (std::vector<EmittedFunctionDetails::LineStart>::const_iterator I =
131           Details.LineStarts.begin(), E = Details.LineStarts.end();
132           I != E; ++I) {
133       // This implementation ignores the DebugLoc filename because the Intel
134       // JIT API does not support multiple source files associated with a single
135       // JIT function
136       LineInfo.push_back(LineStartToIntelJITFormat(
137                           reinterpret_cast<uintptr_t>(FnStart),
138                           I->Address,
139                           I->Loc));
140
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));
148       }
149     }
150
151     FunctionMessage.line_number_size = LineInfo.size();
152     FunctionMessage.line_number_table = &*LineInfo.begin();
153   } else {
154     FunctionMessage.line_number_size = 0;
155     FunctionMessage.line_number_table = 0;
156   }
157
158   Wrapper->iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED,
159                             &FunctionMessage);
160   MethodIDs[FnStart] = FunctionMessage.method_id;
161 }
162
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);
167     MethodIDs.erase(I);
168   }
169 }
170
171 void IntelJITEventListener::NotifyObjectEmitted(const ObjectImage &Obj) {
172 }
173
174 void IntelJITEventListener::NotifyFreeingObject(const ObjectImage &Obj) {
175 }
176
177 }  // anonymous namespace.
178
179 namespace llvm {
180 JITEventListener *JITEventListener::createIntelJITEventListener() {
181   return new IntelJITEventListener(new IntelJITEventsWrapper);
182 }
183
184 // for testing
185 JITEventListener *JITEventListener::createIntelJITEventListener(
186                                       IntelJITEventsWrapper* TestImpl) {
187   return new IntelJITEventListener(TestImpl);
188 }
189
190 } // namespace llvm
191