1 //===-- ModuleDebugInfoPrinter.cpp - Prints module debug info metadata ----===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This pass decodes the debug info metadata in a module and prints in a
11 // (sufficiently-prepared-) human-readable form.
13 // For example, run this pass from opt along with the -analyze option, and
14 // it'll print to standard output.
16 //===----------------------------------------------------------------------===//
18 #include "llvm/ADT/Statistic.h"
19 #include "llvm/Analysis/Passes.h"
20 #include "llvm/IR/DebugInfo.h"
21 #include "llvm/Pass.h"
22 #include "llvm/Support/ErrorHandling.h"
23 #include "llvm/Support/raw_ostream.h"
27 class ModuleDebugInfoPrinter
: public ModulePass
{
28 DebugInfoFinder Finder
;
30 static char ID
; // Pass identification, replacement for typeid
31 ModuleDebugInfoPrinter() : ModulePass(ID
) {
32 initializeModuleDebugInfoPrinterPass(*PassRegistry::getPassRegistry());
35 bool runOnModule(Module
&M
) override
;
37 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
40 void print(raw_ostream
&O
, const Module
*M
) const override
;
44 char ModuleDebugInfoPrinter::ID
= 0;
45 INITIALIZE_PASS(ModuleDebugInfoPrinter
, "module-debuginfo",
46 "Decodes module-level debug info", false, true)
48 ModulePass
*llvm::createModuleDebugInfoPrinterPass() {
49 return new ModuleDebugInfoPrinter();
52 bool ModuleDebugInfoPrinter::runOnModule(Module
&M
) {
53 Finder
.processModule(M
);
57 static void printFile(raw_ostream
&O
, StringRef Filename
, StringRef Directory
,
63 if (!Directory
.empty())
64 O
<< Directory
<< "/";
70 void ModuleDebugInfoPrinter::print(raw_ostream
&O
, const Module
*M
) const {
71 // Printing the nodes directly isn't particularly helpful (since they
72 // reference other nodes that won't be printed, particularly for the
73 // filenames), so just print a few useful things.
74 for (DICompileUnit
*CU
: Finder
.compile_units()) {
75 O
<< "Compile unit: ";
76 auto Lang
= dwarf::LanguageString(CU
->getSourceLanguage());
80 O
<< "unknown-language(" << CU
->getSourceLanguage() << ")";
81 printFile(O
, CU
->getFilename(), CU
->getDirectory());
85 for (DISubprogram
*S
: Finder
.subprograms()) {
86 O
<< "Subprogram: " << S
->getName();
87 printFile(O
, S
->getFilename(), S
->getDirectory(), S
->getLine());
88 if (!S
->getLinkageName().empty())
89 O
<< " ('" << S
->getLinkageName() << "')";
93 for (auto GVU
: Finder
.global_variables()) {
94 const auto *GV
= GVU
->getVariable();
95 O
<< "Global variable: " << GV
->getName();
96 printFile(O
, GV
->getFilename(), GV
->getDirectory(), GV
->getLine());
97 if (!GV
->getLinkageName().empty())
98 O
<< " ('" << GV
->getLinkageName() << "')";
102 for (const DIType
*T
: Finder
.types()) {
104 if (!T
->getName().empty())
105 O
<< ' ' << T
->getName();
106 printFile(O
, T
->getFilename(), T
->getDirectory(), T
->getLine());
107 if (auto *BT
= dyn_cast
<DIBasicType
>(T
)) {
109 auto Encoding
= dwarf::AttributeEncodingString(BT
->getEncoding());
110 if (!Encoding
.empty())
113 O
<< "unknown-encoding(" << BT
->getEncoding() << ')';
116 auto Tag
= dwarf::TagString(T
->getTag());
120 O
<< "unknown-tag(" << T
->getTag() << ")";
122 if (auto *CT
= dyn_cast
<DICompositeType
>(T
)) {
123 if (auto *S
= CT
->getRawIdentifier())
124 O
<< " (identifier: '" << S
->getString() << "')";