]>
Commit | Line | Data |
---|---|---|
223e47cc LB |
1 | //===- DbgInfoPrinter.cpp - Print debug info in a human readable form ------==// |
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 a pass that prints instructions, and associated debug | |
11 | // info: | |
12 | // | |
13 | // - source/line/col information | |
14 | // - original variable name | |
15 | // - original type name | |
16 | // | |
17 | //===----------------------------------------------------------------------===// | |
18 | ||
19 | #include "llvm/DebugInfo.h" | |
20 | #include "llvm/Function.h" | |
21 | #include "llvm/IntrinsicInst.h" | |
22 | #include "llvm/Metadata.h" | |
23 | #include "llvm/Module.h" | |
24 | #include "llvm/Pass.h" | |
25 | #include "llvm/Analysis/Passes.h" | |
26 | #include "llvm/Assembly/Writer.h" | |
27 | #include "llvm/Support/CFG.h" | |
28 | #include "llvm/Support/CommandLine.h" | |
29 | #include "llvm/Support/raw_ostream.h" | |
30 | ||
31 | using namespace llvm; | |
32 | ||
33 | static cl::opt<bool> | |
34 | PrintDirectory("print-fullpath", | |
35 | cl::desc("Print fullpath when printing debug info"), | |
36 | cl::Hidden); | |
37 | ||
38 | namespace { | |
39 | class PrintDbgInfo : public FunctionPass { | |
40 | raw_ostream &Out; | |
41 | void printVariableDeclaration(const Value *V); | |
42 | public: | |
43 | static char ID; // Pass identification | |
44 | PrintDbgInfo() : FunctionPass(ID), Out(errs()) { | |
45 | initializePrintDbgInfoPass(*PassRegistry::getPassRegistry()); | |
46 | } | |
47 | ||
48 | virtual bool runOnFunction(Function &F); | |
49 | virtual void getAnalysisUsage(AnalysisUsage &AU) const { | |
50 | AU.setPreservesAll(); | |
51 | } | |
52 | }; | |
53 | char PrintDbgInfo::ID = 0; | |
54 | } | |
55 | ||
56 | INITIALIZE_PASS(PrintDbgInfo, "print-dbginfo", | |
57 | "Print debug info in human readable form", false, false) | |
58 | ||
59 | FunctionPass *llvm::createDbgInfoPrinterPass() { return new PrintDbgInfo(); } | |
60 | ||
61 | /// Find the debug info descriptor corresponding to this global variable. | |
62 | static Value *findDbgGlobalDeclare(GlobalVariable *V) { | |
63 | const Module *M = V->getParent(); | |
64 | NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.gv"); | |
65 | if (!NMD) | |
66 | return 0; | |
67 | ||
68 | for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) { | |
69 | DIDescriptor DIG(cast<MDNode>(NMD->getOperand(i))); | |
70 | if (!DIG.isGlobalVariable()) | |
71 | continue; | |
72 | if (DIGlobalVariable(DIG).getGlobal() == V) | |
73 | return DIG; | |
74 | } | |
75 | return 0; | |
76 | } | |
77 | ||
78 | /// Find the debug info descriptor corresponding to this function. | |
79 | static Value *findDbgSubprogramDeclare(Function *V) { | |
80 | const Module *M = V->getParent(); | |
81 | NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.sp"); | |
82 | if (!NMD) | |
83 | return 0; | |
84 | ||
85 | for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) { | |
86 | DIDescriptor DIG(cast<MDNode>(NMD->getOperand(i))); | |
87 | if (!DIG.isSubprogram()) | |
88 | continue; | |
89 | if (DISubprogram(DIG).getFunction() == V) | |
90 | return DIG; | |
91 | } | |
92 | return 0; | |
93 | } | |
94 | ||
95 | /// Finds the llvm.dbg.declare intrinsic corresponding to this value if any. | |
96 | /// It looks through pointer casts too. | |
97 | static const DbgDeclareInst *findDbgDeclare(const Value *V) { | |
98 | V = V->stripPointerCasts(); | |
99 | ||
100 | if (!isa<Instruction>(V) && !isa<Argument>(V)) | |
101 | return 0; | |
102 | ||
103 | const Function *F = NULL; | |
104 | if (const Instruction *I = dyn_cast<Instruction>(V)) | |
105 | F = I->getParent()->getParent(); | |
106 | else if (const Argument *A = dyn_cast<Argument>(V)) | |
107 | F = A->getParent(); | |
108 | ||
109 | for (Function::const_iterator FI = F->begin(), FE = F->end(); FI != FE; ++FI) | |
110 | for (BasicBlock::const_iterator BI = (*FI).begin(), BE = (*FI).end(); | |
111 | BI != BE; ++BI) | |
112 | if (const DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(BI)) | |
113 | if (DDI->getAddress() == V) | |
114 | return DDI; | |
115 | ||
116 | return 0; | |
117 | } | |
118 | ||
119 | static bool getLocationInfo(const Value *V, std::string &DisplayName, | |
120 | std::string &Type, unsigned &LineNo, | |
121 | std::string &File, std::string &Dir) { | |
122 | DICompileUnit Unit; | |
123 | DIType TypeD; | |
124 | ||
125 | if (GlobalVariable *GV = dyn_cast<GlobalVariable>(const_cast<Value*>(V))) { | |
126 | Value *DIGV = findDbgGlobalDeclare(GV); | |
127 | if (!DIGV) return false; | |
128 | DIGlobalVariable Var(cast<MDNode>(DIGV)); | |
129 | ||
130 | StringRef D = Var.getDisplayName(); | |
131 | if (!D.empty()) | |
132 | DisplayName = D; | |
133 | LineNo = Var.getLineNumber(); | |
134 | Unit = Var.getCompileUnit(); | |
135 | TypeD = Var.getType(); | |
136 | } else if (Function *F = dyn_cast<Function>(const_cast<Value*>(V))){ | |
137 | Value *DIF = findDbgSubprogramDeclare(F); | |
138 | if (!DIF) return false; | |
139 | DISubprogram Var(cast<MDNode>(DIF)); | |
140 | ||
141 | StringRef D = Var.getDisplayName(); | |
142 | if (!D.empty()) | |
143 | DisplayName = D; | |
144 | LineNo = Var.getLineNumber(); | |
145 | Unit = Var.getCompileUnit(); | |
146 | TypeD = Var.getType(); | |
147 | } else { | |
148 | const DbgDeclareInst *DDI = findDbgDeclare(V); | |
149 | if (!DDI) return false; | |
150 | DIVariable Var(cast<MDNode>(DDI->getVariable())); | |
151 | ||
152 | StringRef D = Var.getName(); | |
153 | if (!D.empty()) | |
154 | DisplayName = D; | |
155 | LineNo = Var.getLineNumber(); | |
156 | Unit = Var.getCompileUnit(); | |
157 | TypeD = Var.getType(); | |
158 | } | |
159 | ||
160 | StringRef T = TypeD.getName(); | |
161 | if (!T.empty()) | |
162 | Type = T; | |
163 | StringRef F = Unit.getFilename(); | |
164 | if (!F.empty()) | |
165 | File = F; | |
166 | StringRef D = Unit.getDirectory(); | |
167 | if (!D.empty()) | |
168 | Dir = D; | |
169 | return true; | |
170 | } | |
171 | ||
172 | void PrintDbgInfo::printVariableDeclaration(const Value *V) { | |
173 | std::string DisplayName, File, Directory, Type; | |
174 | unsigned LineNo = 0; | |
175 | ||
176 | if (!getLocationInfo(V, DisplayName, Type, LineNo, File, Directory)) | |
177 | return; | |
178 | ||
179 | Out << "; "; | |
180 | WriteAsOperand(Out, V, false, 0); | |
181 | if (isa<Function>(V)) | |
182 | Out << " is function " << DisplayName | |
183 | << " of type " << Type << " declared at "; | |
184 | else | |
185 | Out << " is variable " << DisplayName | |
186 | << " of type " << Type << " declared at "; | |
187 | ||
188 | if (PrintDirectory) | |
189 | Out << Directory << "/"; | |
190 | ||
191 | Out << File << ":" << LineNo << "\n"; | |
192 | } | |
193 | ||
194 | bool PrintDbgInfo::runOnFunction(Function &F) { | |
195 | if (F.isDeclaration()) | |
196 | return false; | |
197 | ||
198 | Out << "function " << F.getName() << "\n\n"; | |
199 | ||
200 | for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I) { | |
201 | BasicBlock *BB = I; | |
202 | ||
203 | if (I != F.begin() && (pred_begin(BB) == pred_end(BB))) | |
204 | // Skip dead blocks. | |
205 | continue; | |
206 | ||
207 | Out << BB->getName(); | |
208 | Out << ":"; | |
209 | ||
210 | Out << "\n"; | |
211 | ||
212 | for (BasicBlock::const_iterator i = BB->begin(), e = BB->end(); | |
213 | i != e; ++i) { | |
214 | ||
215 | printVariableDeclaration(i); | |
216 | ||
217 | if (const User *U = dyn_cast<User>(i)) { | |
218 | for(unsigned i=0;i<U->getNumOperands();i++) | |
219 | printVariableDeclaration(U->getOperand(i)); | |
220 | } | |
221 | } | |
222 | } | |
223 | return false; | |
224 | } |