summaryrefslogtreecommitdiff
path: root/tools/analyze/analyze.cpp
blob: eb78d915b449096bd81826f543d83b6ad35fda3a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
//===----------------------------------------------------------------------===//
// The LLVM analyze utility
//
// This utility is designed to print out the results of running various analysis
// passes on a program.  This is useful for understanding a program, or for 
// debugging an analysis pass.
//
//  analyze --help           - Output information about command line switches
//  analyze --quiet          - Do not print analysis name before output
//
//===----------------------------------------------------------------------===//

#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Bytecode/Reader.h"
#include "llvm/Assembly/Parser.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Support/PassNameParser.h"
#include <algorithm>


struct ModulePassPrinter : public Pass {
  const PassInfo *PassToPrint;
  ModulePassPrinter(const PassInfo *PI) : PassToPrint(PI) {}

  virtual bool run(Module &M) {
    std::cout << "Printing Analysis info for Pass "
              << PassToPrint->getPassName() << ":\n";
    getAnalysisID<Pass>(PassToPrint).print(std::cout, &M);
    
    // Get and print pass...
    return false;
  }

  virtual void getAnalysisUsage(AnalysisUsage &AU) const {
    AU.addRequiredID(PassToPrint);
    AU.setPreservesAll();
  }
};

struct FunctionPassPrinter : public FunctionPass {
  const PassInfo *PassToPrint;
  FunctionPassPrinter(const PassInfo *PI) : PassToPrint(PI) {}

  virtual bool runOnFunction(Function &F) {
    std::cout << "Printing Analysis info for function '" << F.getName()
              << "': Pass " << PassToPrint->getPassName() << ":\n";
    getAnalysisID<Pass>(PassToPrint).print(std::cout, F.getParent());

    // Get and print pass...
    return false;
  }

  virtual void getAnalysisUsage(AnalysisUsage &AU) const {
    AU.addRequiredID(PassToPrint);
    AU.setPreservesAll();
  }
};

struct BasicBlockPassPrinter : public BasicBlockPass {
  const PassInfo *PassToPrint;
  BasicBlockPassPrinter(const PassInfo *PI) : PassToPrint(PI) {}

  virtual bool runOnBasicBlock(BasicBlock &BB) {
    std::cout << "Printing Analysis info for BasicBlock '" << BB.getName()
              << "': Pass " << PassToPrint->getPassName() << ":\n";
    getAnalysisID<Pass>(PassToPrint).print(std::cout, BB.getParent()->getParent());

    // Get and print pass...
    return false;
  }

  virtual void getAnalysisUsage(AnalysisUsage &AU) const {
    AU.addRequiredID(PassToPrint);
    AU.setPreservesAll();
  }
};




static cl::opt<std::string>
InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-"),
              cl::value_desc("filename"));

static cl::opt<bool> Quiet("q", cl::desc("Don't print analysis pass names"));
static cl::alias    QuietA("quiet", cl::desc("Alias for -q"),
                           cl::aliasopt(Quiet));

// The AnalysesList is automatically populated with registered Passes by the
// PassNameParser.
//
static cl::list<const PassInfo*, bool,
                FilteredPassNameParser<PassInfo::Analysis> >
AnalysesList(cl::desc("Analyses available:"));


int main(int argc, char **argv) {
  cl::ParseCommandLineOptions(argc, argv, " llvm analysis printer tool\n");

  Module *CurMod = 0;
  try {
    CurMod = ParseBytecodeFile(InputFilename);
    if (!CurMod && !(CurMod = ParseAssemblyFile(InputFilename))){
      std::cerr << argv[0] << ": input file didn't read correctly.\n";
      return 1;
    }
  } catch (const ParseException &E) {
    std::cerr << argv[0] << ": " << E.getMessage() << "\n";
    return 1;
  }

  // Create a PassManager to hold and optimize the collection of passes we are
  // about to build...
  //
  PassManager Passes;

  // Make sure the input LLVM is well formed.
  Passes.add(createVerifierPass());

  // Create a new optimization pass for each one specified on the command line
  for (unsigned i = 0; i < AnalysesList.size(); ++i) {
    const PassInfo *Analysis = AnalysesList[i];
    
    if (Analysis->getNormalCtor()) {
      Pass *P = Analysis->getNormalCtor()();
      Passes.add(P);

      if (BasicBlockPass *BBP = dynamic_cast<BasicBlockPass*>(P))
        Passes.add(new BasicBlockPassPrinter(Analysis));
      else if (FunctionPass *FP = dynamic_cast<FunctionPass*>(P))
        Passes.add(new FunctionPassPrinter(Analysis));
      else
        Passes.add(new ModulePassPrinter(Analysis));

    } else
      std::cerr << argv[0] << ": cannot create pass: "
                << Analysis->getPassName() << "\n";
  }

  Passes.run(*CurMod);

  delete CurMod;
  return 0;
}