summaryrefslogtreecommitdiff
path: root/tools/analyze/analyze.cpp
blob: 1542a1a068a17f7a8d2921c8e1b75501439030a4 (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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
//===- analyze.cpp - The LLVM analyze utility -----------------------------===//
// 
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
// 
//===----------------------------------------------------------------------===//
//
// 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/Target/TargetData.h"
#include "llvm/Support/PassNameParser.h"
#include "llvm/System/Signals.h"
#include "llvm/Support/PluginLoader.h"
#include "llvm/Support/Timer.h"
#include <algorithm>

using namespace llvm;

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

  virtual bool run(Module &M) {
    std::cout << "Printing analysis '" << PassToPrint->getPassName() << "':\n";
    getAnalysisID<Pass>(PassToPrint).print(std::cout, &M);
    
    // Get and print pass...
    return false;
  }
  
  virtual const char *getPassName() const { return "'Pass' Printer"; }

  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 '" << PassToPrint->getPassName()
              << "' for function '" << F.getName() << "':\n";
    getAnalysisID<Pass>(PassToPrint).print(std::cout, F.getParent());

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

  virtual const char *getPassName() const { return "FunctionPass Printer"; }

  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 const char *getPassName() const { return "BasicBlockPass Printer"; }

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



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

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

  cl::opt<bool> NoVerify("disable-verify", cl::Hidden,
                         cl::desc("Do not verify input module"));

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

  Timer BytecodeLoadTimer("Bytecode Loader");
}

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

  Module *CurMod = 0;
  try {
#if 0
    TimeRegion RegionTimer(BytecodeLoadTimer);
#endif
    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;

  // Add an appropriate TargetData instance for this module...
  Passes.add(new TargetData("analyze", CurMod));

  // Make sure the input LLVM is well formed.
  if (!NoVerify)
    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;
}