Add profiling support for Intel Parallel Amplifier XE (VTune) for JITted code in...
[oota-llvm.git] / lib / ExecutionEngine / OProfileJIT / OProfileJITEventListener.cpp
1 //===-- OProfileJITEventListener.cpp - Tell OProfile about JITted 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 that uses OProfileWrapper to tell
11 // oprofile about JITted functions, including source line information.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "llvm/Config/config.h"
16 #include "llvm/ExecutionEngine/JITEventListener.h"
17
18 #define DEBUG_TYPE "oprofile-jit-event-listener"
19 #include "llvm/Function.h"
20 #include "llvm/ADT/OwningPtr.h"
21 #include "llvm/Analysis/DebugInfo.h"
22 #include "llvm/CodeGen/MachineFunction.h"
23 #include "llvm/ExecutionEngine/OProfileWrapper.h"
24 #include "llvm/Support/Debug.h"
25 #include "llvm/Support/raw_ostream.h"
26 #include "llvm/Support/Errno.h"
27 #include "EventListenerCommon.h"
28
29 #include <dirent.h>
30 #include <fcntl.h>
31
32 using namespace llvm;
33 using namespace llvm::jitprofiling;
34
35 namespace {
36
37 class OProfileJITEventListener : public JITEventListener {
38   OProfileWrapper& Wrapper;
39
40   void initialize();
41
42 public:
43   OProfileJITEventListener(OProfileWrapper& LibraryWrapper)
44   : Wrapper(LibraryWrapper) {
45     initialize();
46   }
47
48   ~OProfileJITEventListener();
49
50   virtual void NotifyFunctionEmitted(const Function &F,
51                                 void *FnStart, size_t FnSize,
52                                 const JITEvent_EmittedFunctionDetails &Details);
53
54   virtual void NotifyFreeingMachineCode(void *OldPtr);
55 };
56
57 void OProfileJITEventListener::initialize() {
58   if (!Wrapper.op_open_agent()) {
59     const std::string err_str = sys::StrError();
60     DEBUG(dbgs() << "Failed to connect to OProfile agent: " << err_str << "\n");
61   } else {
62     DEBUG(dbgs() << "Connected to OProfile agent.\n");
63   }
64 }
65
66 OProfileJITEventListener::~OProfileJITEventListener() {
67   if (Wrapper.isAgentAvailable()) {
68     if (Wrapper.op_close_agent() == -1) {
69       const std::string err_str = sys::StrError();
70       DEBUG(dbgs() << "Failed to disconnect from OProfile agent: "
71                    << err_str << "\n");
72     } else {
73       DEBUG(dbgs() << "Disconnected from OProfile agent.\n");
74     }
75   }
76 }
77
78 static debug_line_info LineStartToOProfileFormat(
79     const MachineFunction &MF, FilenameCache &Filenames,
80     uintptr_t Address, DebugLoc Loc) {
81   debug_line_info Result;
82   Result.vma = Address;
83   Result.lineno = Loc.getLine();
84   Result.filename = Filenames.getFilename(
85     Loc.getScope(MF.getFunction()->getContext()));
86   DEBUG(dbgs() << "Mapping " << reinterpret_cast<void*>(Result.vma) << " to "
87                << Result.filename << ":" << Result.lineno << "\n");
88   return Result;
89 }
90
91 // Adds the just-emitted function to the symbol table.
92 void OProfileJITEventListener::NotifyFunctionEmitted(
93     const Function &F, void *FnStart, size_t FnSize,
94     const JITEvent_EmittedFunctionDetails &Details) {
95   assert(F.hasName() && FnStart != 0 && "Bad symbol to add");
96   if (Wrapper.op_write_native_code(F.getName().data(),
97                            reinterpret_cast<uint64_t>(FnStart),
98                            FnStart, FnSize) == -1) {
99     DEBUG(dbgs() << "Failed to tell OProfile about native function "
100           << F.getName() << " at ["
101           << FnStart << "-" << ((char*)FnStart + FnSize) << "]\n");
102     return;
103   }
104
105   if (!Details.LineStarts.empty()) {
106     // Now we convert the line number information from the address/DebugLoc
107     // format in Details to the address/filename/lineno format that OProfile
108     // expects.  Note that OProfile 0.9.4 has a bug that causes it to ignore
109     // line numbers for addresses above 4G.
110     FilenameCache Filenames;
111     std::vector<debug_line_info> LineInfo;
112     LineInfo.reserve(1 + Details.LineStarts.size());
113
114     DebugLoc FirstLoc = Details.LineStarts[0].Loc;
115     assert(!FirstLoc.isUnknown()
116            && "LineStarts should not contain unknown DebugLocs");
117     MDNode *FirstLocScope = FirstLoc.getScope(F.getContext());
118     DISubprogram FunctionDI = getDISubprogram(FirstLocScope);
119     if (FunctionDI.Verify()) {
120       // If we have debug info for the function itself, use that as the line
121       // number of the first several instructions.  Otherwise, after filling
122       // LineInfo, we'll adjust the address of the first line number to point at
123       // the start of the function.
124       debug_line_info line_info;
125       line_info.vma = reinterpret_cast<uintptr_t>(FnStart);
126       line_info.lineno = FunctionDI.getLineNumber();
127       line_info.filename = Filenames.getFilename(FirstLocScope);
128       LineInfo.push_back(line_info);
129     }
130
131     for (std::vector<EmittedFunctionDetails::LineStart>::const_iterator
132            I = Details.LineStarts.begin(), E = Details.LineStarts.end();
133          I != E; ++I) {
134       LineInfo.push_back(LineStartToOProfileFormat(
135                            *Details.MF, Filenames, I->Address, I->Loc));
136     }
137
138     // In case the function didn't have line info of its own, adjust the first
139     // line info's address to include the start of the function.
140     LineInfo[0].vma = reinterpret_cast<uintptr_t>(FnStart);
141
142     if (Wrapper.op_write_debug_line_info(FnStart, LineInfo.size(),
143                                       &*LineInfo.begin()) == -1) {
144       DEBUG(dbgs()
145             << "Failed to tell OProfile about line numbers for native function "
146             << F.getName() << " at ["
147             << FnStart << "-" << ((char*)FnStart + FnSize) << "]\n");
148     }
149   }
150 }
151
152 // Removes the being-deleted function from the symbol table.
153 void OProfileJITEventListener::NotifyFreeingMachineCode(void *FnStart) {
154   assert(FnStart && "Invalid function pointer");
155   if (Wrapper.op_unload_native_code(reinterpret_cast<uint64_t>(FnStart)) == -1) {
156     DEBUG(dbgs()
157           << "Failed to tell OProfile about unload of native function at "
158           << FnStart << "\n");
159   }
160 }
161
162 }  // anonymous namespace.
163
164 namespace llvm {
165 JITEventListener *JITEventListener::createOProfileJITEventListener() {
166   static OwningPtr<OProfileWrapper> JITProfilingWrapper(new OProfileWrapper);
167   return new OProfileJITEventListener(*JITProfilingWrapper);
168 }
169
170 // for testing
171 JITEventListener *JITEventListener::createOProfileJITEventListener(
172                                       OProfileWrapper* TestImpl) {
173   return new OProfileJITEventListener(*TestImpl);
174 }
175
176 } // namespace llvm
177