1 //===-- ModuleDebugInfoPrinter.cpp - Prints module debug info metadata ----===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This pass decodes the debug info metadata in a module and prints in a
10 // (sufficiently-prepared-) human-readable form.
12 // For example, run this pass from opt along with the -analyze option, and
13 // it'll print to standard output.
15 //===----------------------------------------------------------------------===//
17 #include "llvm/ADT/Statistic.h"
18 #include "llvm/Analysis/Passes.h"
19 #include "llvm/IR/DebugInfo.h"
20 #include "llvm/Pass.h"
21 #include "llvm/Support/ErrorHandling.h"
22 #include "llvm/Support/raw_ostream.h"
26 class ModuleDebugInfoPrinter
: public ModulePass
{
27 DebugInfoFinder Finder
;
29 static char ID
; // Pass identification, replacement for typeid
30 ModuleDebugInfoPrinter() : ModulePass(ID
) {
31 initializeModuleDebugInfoPrinterPass(*PassRegistry::getPassRegistry());
34 bool runOnModule(Module
&M
) override
;
36 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
39 void print(raw_ostream
&O
, const Module
*M
) const override
;
43 char ModuleDebugInfoPrinter::ID
= 0;
44 INITIALIZE_PASS(ModuleDebugInfoPrinter
, "module-debuginfo",
45 "Decodes module-level debug info", false, true)
47 ModulePass
*llvm::createModuleDebugInfoPrinterPass() {
48 return new ModuleDebugInfoPrinter();
51 bool ModuleDebugInfoPrinter::runOnModule(Module
&M
) {
52 Finder
.processModule(M
);
56 static void printFile(raw_ostream
&O
, StringRef Filename
, StringRef Directory
,
62 if (!Directory
.empty())
63 O
<< Directory
<< "/";
69 void ModuleDebugInfoPrinter::print(raw_ostream
&O
, const Module
*M
) const {
70 // Printing the nodes directly isn't particularly helpful (since they
71 // reference other nodes that won't be printed, particularly for the
72 // filenames), so just print a few useful things.
73 for (DICompileUnit
*CU
: Finder
.compile_units()) {
74 O
<< "Compile unit: ";
75 auto Lang
= dwarf::LanguageString(CU
->getSourceLanguage());
79 O
<< "unknown-language(" << CU
->getSourceLanguage() << ")";
80 printFile(O
, CU
->getFilename(), CU
->getDirectory());
84 for (DISubprogram
*S
: Finder
.subprograms()) {
85 O
<< "Subprogram: " << S
->getName();
86 printFile(O
, S
->getFilename(), S
->getDirectory(), S
->getLine());
87 if (!S
->getLinkageName().empty())
88 O
<< " ('" << S
->getLinkageName() << "')";
92 for (auto GVU
: Finder
.global_variables()) {
93 const auto *GV
= GVU
->getVariable();
94 O
<< "Global variable: " << GV
->getName();
95 printFile(O
, GV
->getFilename(), GV
->getDirectory(), GV
->getLine());
96 if (!GV
->getLinkageName().empty())
97 O
<< " ('" << GV
->getLinkageName() << "')";
101 for (const DIType
*T
: Finder
.types()) {
103 if (!T
->getName().empty())
104 O
<< ' ' << T
->getName();
105 printFile(O
, T
->getFilename(), T
->getDirectory(), T
->getLine());
106 if (auto *BT
= dyn_cast
<DIBasicType
>(T
)) {
108 auto Encoding
= dwarf::AttributeEncodingString(BT
->getEncoding());
109 if (!Encoding
.empty())
112 O
<< "unknown-encoding(" << BT
->getEncoding() << ')';
115 auto Tag
= dwarf::TagString(T
->getTag());
119 O
<< "unknown-tag(" << T
->getTag() << ")";
121 if (auto *CT
= dyn_cast
<DICompositeType
>(T
)) {
122 if (auto *S
= CT
->getRawIdentifier())
123 O
<< " (identifier: '" << S
->getString() << "')";