408153f34eb5ad6de471577fbb1c36a37d72835d
[oota-llvm.git] / lib / VMCore / DebugInfoProbe.cpp
1 //===-- DebugInfoProbe.cpp - DebugInfo Probe ------------------------------===//
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 implements DebugInfoProbe. This probe can be used by a pass
11 // manager to analyze how optimizer is treating debugging information.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #define DEBUG_TYPE "debuginfoprobe"
16 #include "llvm/DebugInfoProbe.h"
17 #include "llvm/Function.h"
18 #include "llvm/IntrinsicInst.h"
19 #include "llvm/Metadata.h"
20 #include "llvm/PassManager.h"
21 #include "llvm/Support/CommandLine.h"
22 #include "llvm/Support/Debug.h"
23 #include "llvm/Support/DebugLoc.h"
24 #include "llvm/Support/raw_ostream.h"
25 #include "llvm/ADT/StringRef.h"
26 #include <set>
27 #include <string>
28
29 using namespace llvm;
30
31 static cl::opt<bool>
32 EnableDebugInfoProbe("enable-debug-info-probe", cl::Hidden,
33                      cl::desc("Enable debug info probe"));
34
35 // CreateInfoOutputFile - Return a file stream to print our output on.
36 namespace llvm { extern raw_ostream *CreateInfoOutputFile(); }
37
38 //===----------------------------------------------------------------------===//
39 // DebugInfoProbeImpl - This class implements a interface to monitor
40 // how an optimization pass is preserving debugging information.
41
42 namespace llvm {
43
44   class DebugInfoProbeImpl {
45   public:
46     DebugInfoProbeImpl() : NumDbgLineLost(0),NumDbgValueLost(0) {}
47     void initialize(StringRef PName, Function &F);
48     void finalize(Function &F);
49     void report();
50   private:
51     unsigned NumDbgLineLost, NumDbgValueLost;
52     std::string PassName;
53     Function *TheFn;
54     std::set<unsigned> LineNos;
55     std::set<MDNode *> DbgVariables;
56   };
57 }
58
59 //===----------------------------------------------------------------------===//
60 // DebugInfoProbeImpl
61
62 static void collect(Function &F, std::set<unsigned> &Lines) {
63   for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI)
64     for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); 
65          BI != BE; ++BI) {
66       const DebugLoc &DL = BI->getDebugLoc();
67       unsigned LineNo = 0;
68       if (!DL.isUnknown()) {
69         if (MDNode *N = DL.getInlinedAt(F.getContext()))
70           LineNo = DebugLoc::getFromDILocation(N).getLine();
71         else
72           LineNo = DL.getLine();
73
74         Lines.insert(LineNo);
75       }
76     }
77 }
78
79 /// initialize - Collect information before running an optimization pass.
80 void DebugInfoProbeImpl::initialize(StringRef PName, Function &F) {
81   if (!EnableDebugInfoProbe) return;
82   PassName = PName;
83
84   LineNos.clear();
85   DbgVariables.clear();
86   TheFn = &F;
87   collect(F, LineNos);
88
89   for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI)
90     for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); 
91          BI != BE; ++BI) {
92       if (!isa<DbgInfoIntrinsic>(BI)) continue;
93       Value *Addr = NULL;
94       MDNode *Node = NULL;
95       if (DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(BI)) {
96         Addr = DDI->getAddress();
97         Node = DDI->getVariable();
98       } else if (DbgValueInst *DVI = dyn_cast<DbgValueInst>(BI)) {
99         Addr = DVI->getValue();
100         Node = DVI->getVariable();
101       }
102       if (Addr)
103         DbgVariables.insert(Node);
104     }
105 }
106
107 /// report - Report findings. This should be invoked after finalize.
108 void DebugInfoProbeImpl::report() {
109   if (!EnableDebugInfoProbe) return;
110   if (NumDbgLineLost || NumDbgValueLost) {
111     raw_ostream *OutStream = CreateInfoOutputFile();
112     if (NumDbgLineLost)
113       *OutStream << NumDbgLineLost
114                  << "\t times line number info lost by "
115                  << PassName << "\n";
116     if (NumDbgValueLost)
117       *OutStream << NumDbgValueLost
118                  << "\t times variable info lost by    "
119                  << PassName << "\n";
120     delete OutStream;
121   }
122   NumDbgLineLost = 0;
123   NumDbgValueLost = 0;
124 }
125
126 /// finalize - Collect information after running an optimization pass. This
127 /// must be used after initialization.
128 void DebugInfoProbeImpl::finalize(Function &F) {
129   if (!EnableDebugInfoProbe) return;
130   std::set<unsigned> LineNos2;
131   collect(F, LineNos2);
132   assert (TheFn == &F && "Invalid function to measure!");
133
134   for (std::set<unsigned>::iterator I = LineNos.begin(),
135          E = LineNos.end(); I != E; ++I) {
136     unsigned LineNo = *I;
137     if (LineNos2.count(LineNo) == 0) {
138       DEBUG(dbgs() 
139             << "DebugInfoProbe: Losing dbg info for source line " 
140             << LineNo << "\n");
141       ++NumDbgLineLost;
142     }
143   }
144
145   std::set<MDNode *>DbgVariables2;
146   for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI)
147     for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); 
148          BI != BE; ++BI) {
149       if (!isa<DbgInfoIntrinsic>(BI)) continue;
150       Value *Addr = NULL;
151       MDNode *Node = NULL;
152       if (DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(BI)) {
153         Addr = DDI->getAddress();
154         Node = DDI->getVariable();
155       } else if (DbgValueInst *DVI = dyn_cast<DbgValueInst>(BI)) {
156         Addr = DVI->getValue();
157         Node = DVI->getVariable();
158       }
159       if (Addr)
160         DbgVariables2.insert(Node);
161     }
162
163   for (std::set<MDNode *>::iterator I = DbgVariables.begin(), 
164          E = DbgVariables.end(); I != E; ++I) {
165     if (DbgVariables2.count(*I) == 0) {
166       DEBUG(dbgs() << "DebugInfoProbe: Losing dbg info for variable: ");
167       DEBUG((*I)->print(dbgs()));
168       ++NumDbgValueLost;
169     }
170   }
171 }
172
173 //===----------------------------------------------------------------------===//
174 // DebugInfoProbe
175
176 DebugInfoProbe::DebugInfoProbe() {
177   pImpl = new DebugInfoProbeImpl();
178 }
179
180 DebugInfoProbe::~DebugInfoProbe() {
181   delete pImpl;
182 }
183
184 /// initialize - Collect information before running an optimization pass.
185 void DebugInfoProbe::initialize(StringRef PName, Function &F) {
186   pImpl->initialize(PName, F);
187 }
188
189 /// finalize - Collect information after running an optimization pass. This
190 /// must be used after initialization.
191 void DebugInfoProbe::finalize(Function &F) {
192   pImpl->finalize(F);
193 }
194
195 /// report - Report findings. This should be invoked after finalize.
196 void DebugInfoProbe::report() {
197   pImpl->report();
198 }
199
200 //===----------------------------------------------------------------------===//
201 // DebugInfoProbeInfo
202
203 /// ~DebugInfoProbeInfo - Report data collected by all probes before deleting
204 /// them.
205 DebugInfoProbeInfo::~DebugInfoProbeInfo() {
206   if (!EnableDebugInfoProbe) return;
207     for (StringMap<DebugInfoProbe*>::iterator I = Probes.begin(),
208            E = Probes.end(); I != E; ++I) {
209       I->second->report();
210       delete I->second;
211     }
212   }
213
214 /// initialize - Collect information before running an optimization pass.
215 void DebugInfoProbeInfo::initialize(Pass *P, Function &F) {
216   if (!EnableDebugInfoProbe) return;
217   if (P->getAsPMDataManager())
218     return;
219
220   StringMapEntry<DebugInfoProbe *> &Entry =
221     Probes.GetOrCreateValue(P->getPassName());
222   DebugInfoProbe *&Probe = Entry.getValue();
223   if (!Probe)
224     Probe = new DebugInfoProbe();
225   Probe->initialize(P->getPassName(), F);
226 }
227
228 /// finalize - Collect information after running an optimization pass. This
229 /// must be used after initialization.
230 void DebugInfoProbeInfo::finalize(Pass *P, Function &F) {
231   if (!EnableDebugInfoProbe) return;
232   if (P->getAsPMDataManager())
233     return;
234   StringMapEntry<DebugInfoProbe *> &Entry =
235     Probes.GetOrCreateValue(P->getPassName());
236   DebugInfoProbe *&Probe = Entry.getValue();
237   assert (Probe && "DebugInfoProbe is not initialized!");
238   Probe->finalize(F);
239 }