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