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/ADT/Statistic.h"
19 #include "llvm/Analysis/Passes.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"
29 class ModuleDebugInfoLegacyPrinter
: public ModulePass
{
30 DebugInfoFinder Finder
;
33 static char ID
; // Pass identification, replacement for typeid
34 ModuleDebugInfoLegacyPrinter() : ModulePass(ID
) {
35 initializeModuleDebugInfoLegacyPrinterPass(
36 *PassRegistry::getPassRegistry());
39 bool runOnModule(Module
&M
) override
;
41 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
44 void print(raw_ostream
&O
, const Module
*M
) const override
;
48 char ModuleDebugInfoLegacyPrinter::ID
= 0;
49 INITIALIZE_PASS(ModuleDebugInfoLegacyPrinter
, "module-debuginfo",
50 "Decodes module-level debug info", false, true)
52 ModulePass
*llvm::createModuleDebugInfoPrinterPass() {
53 return new ModuleDebugInfoLegacyPrinter();
56 bool ModuleDebugInfoLegacyPrinter::runOnModule(Module
&M
) {
57 Finder
.processModule(M
);
61 static void printFile(raw_ostream
&O
, StringRef Filename
, StringRef Directory
,
67 if (!Directory
.empty())
68 O
<< Directory
<< "/";
74 static void printModuleDebugInfo(raw_ostream
&O
, const Module
*M
,
75 const DebugInfoFinder
&Finder
) {
76 // Printing the nodes directly isn't particularly helpful (since they
77 // reference other nodes that won't be printed, particularly for the
78 // filenames), so just print a few useful things.
79 for (DICompileUnit
*CU
: Finder
.compile_units()) {
80 O
<< "Compile unit: ";
81 auto Lang
= dwarf::LanguageString(CU
->getSourceLanguage());
85 O
<< "unknown-language(" << CU
->getSourceLanguage() << ")";
86 printFile(O
, CU
->getFilename(), CU
->getDirectory());
90 for (DISubprogram
*S
: Finder
.subprograms()) {
91 O
<< "Subprogram: " << S
->getName();
92 printFile(O
, S
->getFilename(), S
->getDirectory(), S
->getLine());
93 if (!S
->getLinkageName().empty())
94 O
<< " ('" << S
->getLinkageName() << "')";
98 for (auto GVU
: Finder
.global_variables()) {
99 const auto *GV
= GVU
->getVariable();
100 O
<< "Global variable: " << GV
->getName();
101 printFile(O
, GV
->getFilename(), GV
->getDirectory(), GV
->getLine());
102 if (!GV
->getLinkageName().empty())
103 O
<< " ('" << GV
->getLinkageName() << "')";
107 for (const DIType
*T
: Finder
.types()) {
109 if (!T
->getName().empty())
110 O
<< ' ' << T
->getName();
111 printFile(O
, T
->getFilename(), T
->getDirectory(), T
->getLine());
112 if (auto *BT
= dyn_cast
<DIBasicType
>(T
)) {
114 auto Encoding
= dwarf::AttributeEncodingString(BT
->getEncoding());
115 if (!Encoding
.empty())
118 O
<< "unknown-encoding(" << BT
->getEncoding() << ')';
121 auto Tag
= dwarf::TagString(T
->getTag());
125 O
<< "unknown-tag(" << T
->getTag() << ")";
127 if (auto *CT
= dyn_cast
<DICompositeType
>(T
)) {
128 if (auto *S
= CT
->getRawIdentifier())
129 O
<< " (identifier: '" << S
->getString() << "')";
135 void ModuleDebugInfoLegacyPrinter::print(raw_ostream
&O
,
136 const Module
*M
) const {
137 printModuleDebugInfo(O
, M
, Finder
);
140 ModuleDebugInfoPrinterPass::ModuleDebugInfoPrinterPass(raw_ostream
&OS
)
143 PreservedAnalyses
ModuleDebugInfoPrinterPass::run(Module
&M
,
144 ModuleAnalysisManager
&AM
) {
145 Finder
.processModule(M
);
146 printModuleDebugInfo(OS
, &M
, Finder
);
147 return PreservedAnalyses::all();