1ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman//===-- ModuleDebugInfoPrinter.cpp - Prints module debug info metadata ----===//
2ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman//
3ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman//                     The LLVM Compiler Infrastructure
4ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman//
5ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman// This file is distributed under the University of Illinois Open Source
6ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman// License. See LICENSE.TXT for details.
7ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman//
8ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman//===----------------------------------------------------------------------===//
9ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman//
10ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman// This pass decodes the debug info metadata in a module and prints in a
11ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman// (sufficiently-prepared-) human-readable form.
12ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman//
13ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman// For example, run this pass from opt along with the -analyze option, and
14ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman// it'll print to standard output.
15ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman//
16ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman//===----------------------------------------------------------------------===//
17ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman
18ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman#include "llvm/Analysis/Passes.h"
19d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/ADT/Statistic.h"
2036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/IR/DebugInfo.h"
210b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Function.h"
220bcbd1df7a204e1e512f1a27066d725309de1b13Bill Wendling#include "llvm/Pass.h"
23ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman#include "llvm/Support/ErrorHandling.h"
24ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman#include "llvm/Support/raw_ostream.h"
25ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohmanusing namespace llvm;
26ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman
27ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohmannamespace {
28ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman  class ModuleDebugInfoPrinter : public ModulePass {
29ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman    DebugInfoFinder Finder;
30ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman  public:
31ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman    static char ID; // Pass identification, replacement for typeid
32081c34b725980f995be9080eaec24cd3dfaaf065Owen Anderson    ModuleDebugInfoPrinter() : ModulePass(ID) {
33081c34b725980f995be9080eaec24cd3dfaaf065Owen Anderson      initializeModuleDebugInfoPrinterPass(*PassRegistry::getPassRegistry());
34081c34b725980f995be9080eaec24cd3dfaaf065Owen Anderson    }
35ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman
3636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    bool runOnModule(Module &M) override;
37ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman
3836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    void getAnalysisUsage(AnalysisUsage &AU) const override {
39ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman      AU.setPreservesAll();
40ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman    }
4136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    void print(raw_ostream &O, const Module *M) const override;
42ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman  };
43ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman}
44ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman
45ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohmanchar ModuleDebugInfoPrinter::ID = 0;
46d13db2c59cc94162d6cf0a04187d408bfef6d4a7Owen AndersonINITIALIZE_PASS(ModuleDebugInfoPrinter, "module-debuginfo",
47ce665bd2e2b581ab0858d1afe359192bac96b868Owen Anderson                "Decodes module-level debug info", false, true)
48ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman
49ef0b14593bb8dd5651606925584adb1ac1096ba5Dan GohmanModulePass *llvm::createModuleDebugInfoPrinterPass() {
50ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman  return new ModuleDebugInfoPrinter();
51ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman}
52ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman
53ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohmanbool ModuleDebugInfoPrinter::runOnModule(Module &M) {
54ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman  Finder.processModule(M);
55ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman  return false;
56ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman}
57ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman
584c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainarstatic void printFile(raw_ostream &O, StringRef Filename, StringRef Directory,
594c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar                      unsigned Line = 0) {
604c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar  if (Filename.empty())
614c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar    return;
624c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar
634c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar  O << " from ";
644c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar  if (!Directory.empty())
654c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar    O << Directory << "/";
664c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar  O << Filename;
674c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar  if (Line)
684c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar    O << ":" << Line;
694c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar}
704c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar
71ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohmanvoid ModuleDebugInfoPrinter::print(raw_ostream &O, const Module *M) const {
724c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar  // Printing the nodes directly isn't particularly helpful (since they
734c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar  // reference other nodes that won't be printed, particularly for the
744c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar  // filenames), so just print a few useful things.
756948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar  for (DICompileUnit *CU : Finder.compile_units()) {
764c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar    O << "Compile unit: ";
770c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar    if (const char *Lang = dwarf::LanguageString(CU->getSourceLanguage()))
784c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar      O << Lang;
794c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar    else
800c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar      O << "unknown-language(" << CU->getSourceLanguage() << ")";
810c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar    printFile(O, CU->getFilename(), CU->getDirectory());
82ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman    O << '\n';
83ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman  }
84ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman
856948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar  for (DISubprogram *S : Finder.subprograms()) {
860c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar    O << "Subprogram: " << S->getName();
870c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar    printFile(O, S->getFilename(), S->getDirectory(), S->getLine());
880c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar    if (!S->getLinkageName().empty())
890c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar      O << " ('" << S->getLinkageName() << "')";
90ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman    O << '\n';
91ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman  }
92ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman
936948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar  for (const DIGlobalVariable *GV : Finder.global_variables()) {
940c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar    O << "Global variable: " << GV->getName();
950c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar    printFile(O, GV->getFilename(), GV->getDirectory(), GV->getLine());
960c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar    if (!GV->getLinkageName().empty())
970c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar      O << " ('" << GV->getLinkageName() << "')";
98ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman    O << '\n';
99ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman  }
100ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman
1016948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar  for (const DIType *T : Finder.types()) {
1024c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar    O << "Type:";
1030c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar    if (!T->getName().empty())
1040c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar      O << ' ' << T->getName();
1050c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar    printFile(O, T->getFilename(), T->getDirectory(), T->getLine());
1066948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar    if (auto *BT = dyn_cast<DIBasicType>(T)) {
1074c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar      O << " ";
1084c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar      if (const char *Encoding =
1090c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar              dwarf::AttributeEncodingString(BT->getEncoding()))
1104c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar        O << Encoding;
1114c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar      else
1120c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar        O << "unknown-encoding(" << BT->getEncoding() << ')';
1134c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar    } else {
1144c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar      O << ' ';
1150c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar      if (const char *Tag = dwarf::TagString(T->getTag()))
1164c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar        O << Tag;
1174c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar      else
1180c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar        O << "unknown-tag(" << T->getTag() << ")";
1194c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar    }
1206948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar    if (auto *CT = dyn_cast<DICompositeType>(T)) {
1210c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar      if (auto *S = CT->getRawIdentifier())
1224c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar        O << " (identifier: '" << S->getString() << "')";
1234c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar    }
124ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman    O << '\n';
125ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman  }
126ef0b14593bb8dd5651606925584adb1ac1096ba5Dan Gohman}
127