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