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/Analysis/ModuleDebugInfoPrinter.h"
18 #include "llvm/Analysis/Passes.h"
19 #include "llvm/BinaryFormat/Dwarf.h"
20 #include "llvm/IR/DebugInfo.h"
21 #include "llvm/IR/PassManager.h"
22 #include "llvm/InitializePasses.h"
23 #include "llvm/Pass.h"
24 #include "llvm/Support/ErrorHandling.h"
25 #include "llvm/Support/raw_ostream.h"
28 static void printFile(raw_ostream
&O
, StringRef Filename
, StringRef Directory
,
34 if (!Directory
.empty())
35 O
<< Directory
<< "/";
41 static void printModuleDebugInfo(raw_ostream
&O
, const Module
*M
,
42 const DebugInfoFinder
&Finder
) {
43 // Printing the nodes directly isn't particularly helpful (since they
44 // reference other nodes that won't be printed, particularly for the
45 // filenames), so just print a few useful things.
46 for (DICompileUnit
*CU
: Finder
.compile_units()) {
47 O
<< "Compile unit: ";
48 auto Lang
= dwarf::LanguageString(CU
->getSourceLanguage());
52 O
<< "unknown-language(" << CU
->getSourceLanguage() << ")";
53 printFile(O
, CU
->getFilename(), CU
->getDirectory());
57 for (DISubprogram
*S
: Finder
.subprograms()) {
58 O
<< "Subprogram: " << S
->getName();
59 printFile(O
, S
->getFilename(), S
->getDirectory(), S
->getLine());
60 if (!S
->getLinkageName().empty())
61 O
<< " ('" << S
->getLinkageName() << "')";
65 for (auto *GVU
: Finder
.global_variables()) {
66 const auto *GV
= GVU
->getVariable();
67 O
<< "Global variable: " << GV
->getName();
68 printFile(O
, GV
->getFilename(), GV
->getDirectory(), GV
->getLine());
69 if (!GV
->getLinkageName().empty())
70 O
<< " ('" << GV
->getLinkageName() << "')";
74 for (const DIType
*T
: Finder
.types()) {
76 if (!T
->getName().empty())
77 O
<< ' ' << T
->getName();
78 printFile(O
, T
->getFilename(), T
->getDirectory(), T
->getLine());
79 if (auto *BT
= dyn_cast
<DIBasicType
>(T
)) {
81 auto Encoding
= dwarf::AttributeEncodingString(BT
->getEncoding());
82 if (!Encoding
.empty())
85 O
<< "unknown-encoding(" << BT
->getEncoding() << ')';
88 auto Tag
= dwarf::TagString(T
->getTag());
92 O
<< "unknown-tag(" << T
->getTag() << ")";
94 if (auto *CT
= dyn_cast
<DICompositeType
>(T
)) {
95 if (auto *S
= CT
->getRawIdentifier())
96 O
<< " (identifier: '" << S
->getString() << "')";
102 ModuleDebugInfoPrinterPass::ModuleDebugInfoPrinterPass(raw_ostream
&OS
)
105 PreservedAnalyses
ModuleDebugInfoPrinterPass::run(Module
&M
,
106 ModuleAnalysisManager
&AM
) {
107 Finder
.processModule(M
);
108 printModuleDebugInfo(OS
, &M
, Finder
);
109 return PreservedAnalyses::all();