Pull callgraph out of Cfg namespace
[oota-llvm.git] / tools / analyze / analyze.cpp
1 //===----------------------------------------------------------------------===//
2 // LLVM 'Analyze' UTILITY 
3 //
4 // This utility is designed to print out the results of running various analysis
5 // passes on a program.  This is useful for understanding a program, or for 
6 // debugging an analysis pass.
7 //
8 //  analyze --help           - Output information about command line switches
9 //  analyze --quiet          - Do not print analysis name before output
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "llvm/Instruction.h"
14 #include "llvm/Module.h"
15 #include "llvm/Method.h"
16 #include "llvm/iPHINode.h"
17 #include "llvm/PassManager.h"
18 #include "llvm/Bytecode/Reader.h"
19 #include "llvm/Assembly/Parser.h"
20 #include "llvm/Assembly/PrintModulePass.h"
21 #include "llvm/Analysis/Writer.h"
22 #include "llvm/Analysis/InstForest.h"
23 #include "llvm/Analysis/Dominators.h"
24 #include "llvm/Analysis/IntervalPartition.h"
25 #include "llvm/Analysis/Expressions.h"
26 #include "llvm/Analysis/InductionVariable.h"
27 #include "llvm/Analysis/CallGraph.h"
28 #include "llvm/Analysis/LoopInfo.h"
29 #include "llvm/Analysis/FindUnsafePointerTypes.h"
30 #include "llvm/Analysis/FindUsedTypes.h"
31 #include "llvm/Support/InstIterator.h"
32 #include "Support/CommandLine.h"
33 #include <algorithm>
34 #include <iostream>
35
36 using std::cout;
37 using std::ostream;
38 using std::string;
39
40 static Module *CurrentModule;
41
42 static void operator<<(ostream &O, const FindUsedTypes &FUT) {
43   FUT.printTypes(cout, CurrentModule);
44 }
45
46 static void operator<<(ostream &O, const FindUnsafePointerTypes &FUPT) {
47   FUPT.printResults(CurrentModule, cout);
48 }
49
50
51
52 template <class PassType, class PassName>
53 class PassPrinter;  // Do not implement
54
55 template <class PassName>
56 class PassPrinter<Pass, PassName> : public Pass {
57   const string Message;
58   const AnalysisID ID;
59 public:
60   PassPrinter(const string &M, AnalysisID id) : Message(M), ID(id) {}
61   
62   virtual bool run(Module *M) {
63     cout << Message << "\n" << getAnalysis<PassName>(ID);
64     return false;
65   }
66
67   virtual void getAnalysisUsageInfo(Pass::AnalysisSet &Required,
68                                     Pass::AnalysisSet &Destroyed,
69                                     Pass::AnalysisSet &Provided) {
70     Required.push_back(ID);
71   }
72 };
73
74 template <class PassName>
75 class PassPrinter<MethodPass, PassName> : public MethodPass {
76   const string Message;
77   const AnalysisID ID;
78 public:
79   PassPrinter(const string &M, AnalysisID id) : Message(M), ID(id) {}
80   
81   virtual bool runOnMethod(Method *M) {
82     cout << Message << " on method '" << M->getName() << "'\n"
83          << getAnalysis<PassName>(ID);
84     return false;
85   }
86
87   virtual void getAnalysisUsageInfo(Pass::AnalysisSet &Required,
88                                     Pass::AnalysisSet &Destroyed,
89                                     Pass::AnalysisSet &Provided) {
90     Required.push_back(ID);
91   }
92 };
93
94
95
96 template <class PassType, class PassName, AnalysisID &ID>
97 Pass *New(const string &Message) {
98   return new PassPrinter<PassType, PassName>(Message, ID);
99 }
100 template <class PassType, class PassName>
101 Pass *New(const string &Message) {
102   return new PassPrinter<PassType, PassName>(Message, PassName::ID);
103 }
104
105
106
107 Pass *NewPrintMethod(const string &Message) {
108   return new PrintMethodPass(Message, &std::cout);
109 }
110 Pass *NewPrintModule(const string &Message) {
111   return new PrintModulePass(&std::cout);
112 }
113
114 struct InstForest : public MethodPass {
115   void doit(Method *M) {
116     cout << analysis::InstForest<char>(M);
117   }
118 };
119
120 struct IndVars : public MethodPass {
121   void doit(Method *M) {
122     cfg::LoopInfo &LI = getAnalysis<cfg::LoopInfo>();
123     for (inst_iterator I = inst_begin(M), E = inst_end(M); I != E; ++I)
124       if (PHINode *PN = dyn_cast<PHINode>(*I)) {
125         InductionVariable IV(PN, &LI);
126         if (IV.InductionType != InductionVariable::Unknown)
127           cout << IV;
128       }
129   }
130
131   void getAnalysisUsageInfo(Pass::AnalysisSet &Req,
132                             Pass::AnalysisSet &, Pass::AnalysisSet &) {
133     Req.push_back(cfg::LoopInfo::ID);
134   }
135 };
136
137 struct Exprs : public MethodPass {
138   static void doit(Method *M) {
139     cout << "Classified expressions for: " << M->getName() << "\n";
140     for (inst_iterator I = inst_begin(M), E = inst_end(M); I != E; ++I) {
141       cout << *I;
142       
143       if ((*I)->getType() == Type::VoidTy) continue;
144       analysis::ExprType R = analysis::ClassifyExpression(*I);
145       if (R.Var == *I) continue;  // Doesn't tell us anything
146       
147       cout << "\t\tExpr =";
148       switch (R.ExprTy) {
149       case analysis::ExprType::ScaledLinear:
150         WriteAsOperand(cout << "(", (Value*)R.Scale) << " ) *";
151         // fall through
152       case analysis::ExprType::Linear:
153         WriteAsOperand(cout << "(", R.Var) << " )";
154         if (R.Offset == 0) break;
155         else cout << " +";
156         // fall through
157       case analysis::ExprType::Constant:
158         if (R.Offset) WriteAsOperand(cout, (Value*)R.Offset); else cout << " 0";
159         break;
160       }
161       cout << "\n\n";
162     }
163   }
164 };
165
166
167 template<class TraitClass>
168 class PrinterPass : public TraitClass {
169   const string Message;
170 public:
171   PrinterPass(const string &M) : Message(M) {}
172   
173   virtual bool runOnMethod(Method *M) {
174     cout << Message << " on method '" << M->getName() << "'\n";
175
176     TraitClass::doit(M);
177     return false;
178   }
179 };
180
181
182 template<class PassClass>
183 Pass *Create(const string &Message) {
184   return new PassClass(Message);
185 }
186
187
188
189 enum Ans {
190   // global analyses
191   print, intervals, exprs, instforest, loops, indvars,
192
193   // ip analyses
194   printmodule, callgraph, printusedtypes, unsafepointertypes,
195
196   domset, idom, domtree, domfrontier,
197   postdomset, postidom, postdomtree, postdomfrontier,
198 };
199
200 cl::String InputFilename ("", "Load <arg> file to analyze", cl::NoFlags, "-");
201 cl::Flag   Quiet         ("q", "Don't print analysis pass names");
202 cl::Alias  QuietA        ("quiet", "Alias for -q", cl::NoFlags, Quiet);
203 cl::EnumList<enum Ans> AnalysesList(cl::NoFlags,
204   clEnumVal(print          , "Print each method"),
205   clEnumVal(intervals      , "Print Interval Partitions"),
206   clEnumVal(exprs          , "Classify Expressions"),
207   clEnumVal(instforest     , "Print Instruction Forest"),
208   clEnumVal(loops          , "Print Loops"),
209   clEnumVal(indvars        , "Print Induction Variables"),
210
211   clEnumVal(printmodule    , "Print entire module"),
212   clEnumVal(callgraph      , "Print Call Graph"),
213   clEnumVal(printusedtypes , "Print Types Used by Module"),
214   clEnumVal(unsafepointertypes, "Print Unsafe Pointer Types"),
215
216   clEnumVal(domset         , "Print Dominator Sets"),
217   clEnumVal(idom           , "Print Immediate Dominators"),
218   clEnumVal(domtree        , "Print Dominator Tree"),
219   clEnumVal(domfrontier    , "Print Dominance Frontier"),
220
221   clEnumVal(postdomset     , "Print Postdominator Sets"),
222   clEnumVal(postidom       , "Print Immediate Postdominators"),
223   clEnumVal(postdomtree    , "Print Post Dominator Tree"),
224   clEnumVal(postdomfrontier, "Print Postdominance Frontier"),
225 0);
226
227
228 struct {
229   enum Ans AnID;
230   Pass *(*PassConstructor)(const string &Message);
231 } AnTable[] = {
232   // Global analyses
233   { print             , NewPrintMethod                          },
234   { intervals         , New<MethodPass, cfg::IntervalPartition> },
235   { loops             , New<MethodPass, cfg::LoopInfo>          },
236   { instforest        , Create<PrinterPass<InstForest> >        },
237   { indvars           , Create<PrinterPass<IndVars> >           },
238   { exprs             , Create<PrinterPass<Exprs> >             },
239
240   // IP Analyses...
241   { printmodule       , NewPrintModule                    },
242   { printusedtypes    , New<Pass, FindUsedTypes>          },
243   { callgraph         , New<Pass, CallGraph>              },
244   { unsafepointertypes, New<Pass, FindUnsafePointerTypes> },
245
246   // Dominator analyses
247   { domset            , New<MethodPass, cfg::DominatorSet>        },
248   { idom              , New<MethodPass, cfg::ImmediateDominators> },
249   { domtree           , New<MethodPass, cfg::DominatorTree>       },
250   { domfrontier       , New<MethodPass, cfg::DominanceFrontier>   },
251
252   { postdomset        , New<MethodPass, cfg::DominatorSet, cfg::DominatorSet::PostDomID> },
253   { postidom          , New<MethodPass, cfg::ImmediateDominators, cfg::ImmediateDominators::PostDomID> },
254   { postdomtree       , New<MethodPass, cfg::DominatorTree, cfg::DominatorTree::PostDomID> },
255   { postdomfrontier   , New<MethodPass, cfg::DominanceFrontier, cfg::DominanceFrontier::PostDomID> },
256 };
257
258 int main(int argc, char **argv) {
259   cl::ParseCommandLineOptions(argc, argv, " llvm analysis printer tool\n");
260
261   try {
262     CurrentModule = ParseBytecodeFile(InputFilename);
263     if (!CurrentModule && !(CurrentModule = ParseAssemblyFile(InputFilename))){
264       std::cerr << "Input file didn't read correctly.\n";
265       return 1;
266     }
267   } catch (const ParseException &E) {
268     std::cerr << E.getMessage() << "\n";
269     return 1;
270   }
271
272   // Create a PassManager to hold and optimize the collection of passes we are
273   // about to build...
274   //
275   PassManager Analyses;
276
277   // Loop over all of the analyses looking for analyses to run...
278   for (unsigned i = 0; i < AnalysesList.size(); ++i) {
279     enum Ans AnalysisPass = AnalysesList[i];
280
281     for (unsigned j = 0; j < sizeof(AnTable)/sizeof(AnTable[0]); ++j) {
282       if (AnTable[j].AnID == AnalysisPass) {
283         string Message;
284         if (!Quiet)
285           Message = "\nRunning: '" + 
286             string(AnalysesList.getArgDescription(AnalysisPass)) + "' analysis";
287         Analyses.add(AnTable[j].PassConstructor(Message));
288         break;                       // get an error later
289       }
290     }
291   }  
292
293   Analyses.run(CurrentModule);
294
295   delete CurrentModule;
296   return 0;
297 }