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