/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/Analysis/ModuleDebugInfoPrinter.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===-- ModuleDebugInfoPrinter.cpp - Prints module debug info metadata ----===// |
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 pass decodes the debug info metadata in a module and prints in a |
11 | | // (sufficiently-prepared-) human-readable form. |
12 | | // |
13 | | // For example, run this pass from opt along with the -analyze option, and |
14 | | // it'll print to standard output. |
15 | | // |
16 | | //===----------------------------------------------------------------------===// |
17 | | |
18 | | #include "llvm/ADT/Statistic.h" |
19 | | #include "llvm/Analysis/Passes.h" |
20 | | #include "llvm/IR/DebugInfo.h" |
21 | | #include "llvm/IR/Function.h" |
22 | | #include "llvm/Pass.h" |
23 | | #include "llvm/Support/ErrorHandling.h" |
24 | | #include "llvm/Support/raw_ostream.h" |
25 | | using namespace llvm; |
26 | | |
27 | | namespace { |
28 | | class ModuleDebugInfoPrinter : public ModulePass { |
29 | | DebugInfoFinder Finder; |
30 | | public: |
31 | | static char ID; // Pass identification, replacement for typeid |
32 | 3 | ModuleDebugInfoPrinter() : ModulePass(ID) { |
33 | 3 | initializeModuleDebugInfoPrinterPass(*PassRegistry::getPassRegistry()); |
34 | 3 | } |
35 | | |
36 | | bool runOnModule(Module &M) override; |
37 | | |
38 | 3 | void getAnalysisUsage(AnalysisUsage &AU) const override { |
39 | 3 | AU.setPreservesAll(); |
40 | 3 | } |
41 | | void print(raw_ostream &O, const Module *M) const override; |
42 | | }; |
43 | | } |
44 | | |
45 | | char ModuleDebugInfoPrinter::ID = 0; |
46 | | INITIALIZE_PASS(ModuleDebugInfoPrinter, "module-debuginfo", |
47 | | "Decodes module-level debug info", false, true) |
48 | | |
49 | 0 | ModulePass *llvm::createModuleDebugInfoPrinterPass() { |
50 | 0 | return new ModuleDebugInfoPrinter(); |
51 | 0 | } |
52 | | |
53 | 3 | bool ModuleDebugInfoPrinter::runOnModule(Module &M) { |
54 | 3 | Finder.processModule(M); |
55 | 3 | return false; |
56 | 3 | } |
57 | | |
58 | | static void printFile(raw_ostream &O, StringRef Filename, StringRef Directory, |
59 | 16 | unsigned Line = 0) { |
60 | 16 | if (Filename.empty()) |
61 | 3 | return; |
62 | 13 | |
63 | 13 | O << " from "; |
64 | 13 | if (!Directory.empty()) |
65 | 13 | O << Directory << "/"; |
66 | 13 | O << Filename; |
67 | 13 | if (Line) |
68 | 8 | O << ":" << Line; |
69 | 16 | } |
70 | | |
71 | 3 | void ModuleDebugInfoPrinter::print(raw_ostream &O, const Module *M) const { |
72 | 3 | // Printing the nodes directly isn't particularly helpful (since they |
73 | 3 | // reference other nodes that won't be printed, particularly for the |
74 | 3 | // filenames), so just print a few useful things. |
75 | 5 | for (DICompileUnit *CU : Finder.compile_units()) { |
76 | 5 | O << "Compile unit: "; |
77 | 5 | auto Lang = dwarf::LanguageString(CU->getSourceLanguage()); |
78 | 5 | if (!Lang.empty()) |
79 | 5 | O << Lang; |
80 | 5 | else |
81 | 0 | O << "unknown-language(" << CU->getSourceLanguage() << ")"; |
82 | 5 | printFile(O, CU->getFilename(), CU->getDirectory()); |
83 | 5 | O << '\n'; |
84 | 5 | } |
85 | 3 | |
86 | 4 | for (DISubprogram *S : Finder.subprograms()) { |
87 | 4 | O << "Subprogram: " << S->getName(); |
88 | 4 | printFile(O, S->getFilename(), S->getDirectory(), S->getLine()); |
89 | 4 | if (!S->getLinkageName().empty()) |
90 | 0 | O << " ('" << S->getLinkageName() << "')"; |
91 | 4 | O << '\n'; |
92 | 4 | } |
93 | 3 | |
94 | 1 | for (auto GVU : Finder.global_variables()) { |
95 | 1 | const auto *GV = GVU->getVariable(); |
96 | 1 | O << "Global variable: " << GV->getName(); |
97 | 1 | printFile(O, GV->getFilename(), GV->getDirectory(), GV->getLine()); |
98 | 1 | if (!GV->getLinkageName().empty()) |
99 | 0 | O << " ('" << GV->getLinkageName() << "')"; |
100 | 1 | O << '\n'; |
101 | 1 | } |
102 | 3 | |
103 | 6 | for (const DIType *T : Finder.types()) { |
104 | 6 | O << "Type:"; |
105 | 6 | if (!T->getName().empty()) |
106 | 3 | O << ' ' << T->getName(); |
107 | 6 | printFile(O, T->getFilename(), T->getDirectory(), T->getLine()); |
108 | 6 | if (auto *BT6 = dyn_cast<DIBasicType>(T)) { |
109 | 0 | O << " "; |
110 | 0 | auto Encoding = dwarf::AttributeEncodingString(BT->getEncoding()); |
111 | 0 | if (!Encoding.empty()) |
112 | 0 | O << Encoding; |
113 | 0 | else |
114 | 0 | O << "unknown-encoding(" << BT->getEncoding() << ')'; |
115 | 6 | } else { |
116 | 6 | O << ' '; |
117 | 6 | auto Tag = dwarf::TagString(T->getTag()); |
118 | 6 | if (!Tag.empty()) |
119 | 6 | O << Tag; |
120 | 6 | else |
121 | 0 | O << "unknown-tag(" << T->getTag() << ")"; |
122 | 6 | } |
123 | 6 | if (auto *CT6 = dyn_cast<DICompositeType>(T)) { |
124 | 2 | if (auto *S = CT->getRawIdentifier()) |
125 | 0 | O << " (identifier: '" << S->getString() << "')"; |
126 | 2 | } |
127 | 6 | O << '\n'; |
128 | 6 | } |
129 | 3 | } |