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