IntelJITEventListener.cpp revision 234285
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/Function.h"
20#include "llvm/Metadata.h"
21#include "llvm/ADT/DenseMap.h"
22#include "llvm/ADT/OwningPtr.h"
23#include "llvm/Analysis/DebugInfo.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