[PowerPC] Use VSX vector load/stores for v2[fi]64
[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/IR/DebugInfo.h"
20 #include "llvm/IR/Function.h"
21 #include "llvm/CodeGen/MachineFunction.h"
22 #include "llvm/ExecutionEngine/ObjectImage.h"
23 #include "llvm/ExecutionEngine/OProfileWrapper.h"
24 #include "llvm/Object/ObjectFile.h"
25 #include "llvm/Support/Debug.h"
26 #include "llvm/Support/raw_ostream.h"
27 #include "llvm/Support/Errno.h"
28 #include "EventListenerCommon.h"
29
30 #include <dirent.h>
31 #include <fcntl.h>
32
33 using namespace llvm;
34 using namespace llvm::jitprofiling;
35
36 namespace {
37
38 class OProfileJITEventListener : public JITEventListener {
39   OProfileWrapper& Wrapper;
40
41   void initialize();
42
43 public:
44   OProfileJITEventListener(OProfileWrapper& LibraryWrapper)
45   : Wrapper(LibraryWrapper) {
46     initialize();
47   }
48
49   ~OProfileJITEventListener();
50
51   virtual void NotifyFunctionEmitted(const Function &F,
52                                 void *FnStart, size_t FnSize,
53                                 const JITEvent_EmittedFunctionDetails &Details);
54
55   virtual void NotifyFreeingMachineCode(void *OldPtr);
56
57   virtual void NotifyObjectEmitted(const ObjectImage &Obj);
58
59   virtual void NotifyFreeingObject(const ObjectImage &Obj);
60 };
61
62 void OProfileJITEventListener::initialize() {
63   if (!Wrapper.op_open_agent()) {
64     const std::string err_str = sys::StrError();
65     DEBUG(dbgs() << "Failed to connect to OProfile agent: " << err_str << "\n");
66   } else {
67     DEBUG(dbgs() << "Connected to OProfile agent.\n");
68   }
69 }
70
71 OProfileJITEventListener::~OProfileJITEventListener() {
72   if (Wrapper.isAgentAvailable()) {
73     if (Wrapper.op_close_agent() == -1) {
74       const std::string err_str = sys::StrError();
75       DEBUG(dbgs() << "Failed to disconnect from OProfile agent: "
76                    << err_str << "\n");
77     } else {
78       DEBUG(dbgs() << "Disconnected from OProfile agent.\n");
79     }
80   }
81 }
82
83 static debug_line_info LineStartToOProfileFormat(
84     const MachineFunction &MF, FilenameCache &Filenames,
85     uintptr_t Address, DebugLoc Loc) {
86   debug_line_info Result;
87   Result.vma = Address;
88   Result.lineno = Loc.getLine();
89   Result.filename = Filenames.getFilename(
90     Loc.getScope(MF.getFunction()->getContext()));
91   DEBUG(dbgs() << "Mapping " << reinterpret_cast<void*>(Result.vma) << " to "
92                << Result.filename << ":" << Result.lineno << "\n");
93   return Result;
94 }
95
96 // Adds the just-emitted function to the symbol table.
97 void OProfileJITEventListener::NotifyFunctionEmitted(
98     const Function &F, void *FnStart, size_t FnSize,
99     const JITEvent_EmittedFunctionDetails &Details) {
100   assert(F.hasName() && FnStart != 0 && "Bad symbol to add");
101   if (Wrapper.op_write_native_code(F.getName().data(),
102                            reinterpret_cast<uint64_t>(FnStart),
103                            FnStart, FnSize) == -1) {
104     DEBUG(dbgs() << "Failed to tell OProfile about native function "
105           << F.getName() << " at ["
106           << FnStart << "-" << ((char*)FnStart + FnSize) << "]\n");
107     return;
108   }
109
110   if (!Details.LineStarts.empty()) {
111     // Now we convert the line number information from the address/DebugLoc
112     // format in Details to the address/filename/lineno format that OProfile
113     // expects.  Note that OProfile 0.9.4 has a bug that causes it to ignore
114     // line numbers for addresses above 4G.
115     FilenameCache Filenames;
116     std::vector<debug_line_info> LineInfo;
117     LineInfo.reserve(1 + Details.LineStarts.size());
118
119     DebugLoc FirstLoc = Details.LineStarts[0].Loc;
120     assert(!FirstLoc.isUnknown()
121            && "LineStarts should not contain unknown DebugLocs");
122     MDNode *FirstLocScope = FirstLoc.getScope(F.getContext());
123     DISubprogram FunctionDI = getDISubprogram(FirstLocScope);
124     if (FunctionDI.Verify()) {
125       // If we have debug info for the function itself, use that as the line
126       // number of the first several instructions.  Otherwise, after filling
127       // LineInfo, we'll adjust the address of the first line number to point at
128       // the start of the function.
129       debug_line_info line_info;
130       line_info.vma = reinterpret_cast<uintptr_t>(FnStart);
131       line_info.lineno = FunctionDI.getLineNumber();
132       line_info.filename = Filenames.getFilename(FirstLocScope);
133       LineInfo.push_back(line_info);
134     }
135
136     for (std::vector<EmittedFunctionDetails::LineStart>::const_iterator
137            I = Details.LineStarts.begin(), E = Details.LineStarts.end();
138          I != E; ++I) {
139       LineInfo.push_back(LineStartToOProfileFormat(
140                            *Details.MF, Filenames, I->Address, I->Loc));
141     }
142
143     // In case the function didn't have line info of its own, adjust the first
144     // line info's address to include the start of the function.
145     LineInfo[0].vma = reinterpret_cast<uintptr_t>(FnStart);
146
147     if (Wrapper.op_write_debug_line_info(FnStart, LineInfo.size(),
148                                       &*LineInfo.begin()) == -1) {
149       DEBUG(dbgs()
150             << "Failed to tell OProfile about line numbers for native function "
151             << F.getName() << " at ["
152             << FnStart << "-" << ((char*)FnStart + FnSize) << "]\n");
153     }
154   }
155 }
156
157 // Removes the being-deleted function from the symbol table.
158 void OProfileJITEventListener::NotifyFreeingMachineCode(void *FnStart) {
159   assert(FnStart && "Invalid function pointer");
160   if (Wrapper.op_unload_native_code(reinterpret_cast<uint64_t>(FnStart)) == -1) {
161     DEBUG(dbgs()
162           << "Failed to tell OProfile about unload of native function at "
163           << FnStart << "\n");
164   }
165 }
166
167 void OProfileJITEventListener::NotifyObjectEmitted(const ObjectImage &Obj) {
168   if (!Wrapper.isAgentAvailable()) {
169     return;
170   }
171
172   // Use symbol info to iterate functions in the object.
173   error_code ec;
174   for (object::symbol_iterator I = Obj.begin_symbols(),
175                                E = Obj.end_symbols();
176                         I != E && !ec;
177                         I.increment(ec)) {
178     object::SymbolRef::Type SymType;
179     if (I->getType(SymType)) continue;
180     if (SymType == object::SymbolRef::ST_Function) {
181       StringRef  Name;
182       uint64_t   Addr;
183       uint64_t   Size;
184       if (I->getName(Name)) continue;
185       if (I->getAddress(Addr)) continue;
186       if (I->getSize(Size)) continue;
187
188       if (Wrapper.op_write_native_code(Name.data(), Addr, (void*)Addr, Size)
189                         == -1) {
190         DEBUG(dbgs() << "Failed to tell OProfile about native function "
191           << Name << " at ["
192           << (void*)Addr << "-" << ((char*)Addr + Size) << "]\n");
193         continue;
194       }
195       // TODO: support line number info (similar to IntelJITEventListener.cpp)
196     }
197   }
198 }
199
200 void OProfileJITEventListener::NotifyFreeingObject(const ObjectImage &Obj) {
201   if (!Wrapper.isAgentAvailable()) {
202     return;
203   }
204
205   // Use symbol info to iterate functions in the object.
206   error_code ec;
207   for (object::symbol_iterator I = Obj.begin_symbols(),
208                                E = Obj.end_symbols();
209                         I != E && !ec;
210                         I.increment(ec)) {
211     object::SymbolRef::Type SymType;
212     if (I->getType(SymType)) continue;
213     if (SymType == object::SymbolRef::ST_Function) {
214       uint64_t   Addr;
215       if (I->getAddress(Addr)) continue;
216
217       if (Wrapper.op_unload_native_code(Addr) == -1) {
218         DEBUG(dbgs()
219           << "Failed to tell OProfile about unload of native function at "
220           << (void*)Addr << "\n");
221         continue;
222       }
223     }
224   }
225 }
226
227 }  // anonymous namespace.
228
229 namespace llvm {
230 JITEventListener *JITEventListener::createOProfileJITEventListener() {
231   static std::unique_ptr<OProfileWrapper> JITProfilingWrapper(
232       new OProfileWrapper);
233   return new OProfileJITEventListener(*JITProfilingWrapper);
234 }
235
236 // for testing
237 JITEventListener *JITEventListener::createOProfileJITEventListener(
238                                       OProfileWrapper* TestImpl) {
239   return new OProfileJITEventListener(*TestImpl);
240 }
241
242 } // namespace llvm
243