Changes to build successfully with GCC 3.02
[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/Bytecode/Reader.h"
18 #include "llvm/Assembly/Parser.h"
19 #include "llvm/Analysis/Writer.h"
20 #include "llvm/Analysis/InstForest.h"
21 #include "llvm/Analysis/Dominators.h"
22 #include "llvm/Analysis/IntervalPartition.h"
23 #include "llvm/Analysis/Expressions.h"
24 #include "llvm/Analysis/InductionVariable.h"
25 #include "llvm/Analysis/CallGraph.h"
26 #include "llvm/Analysis/LoopInfo.h"
27 #include "llvm/Analysis/FindUnsafePointerTypes.h"
28 #include "llvm/Analysis/FindUsedTypes.h"
29 #include "Support/CommandLine.h"
30 #include <algorithm>
31 #include <iostream>
32 using std::cout;
33 using std::cerr;
34 using std::pair;
35
36 static void PrintMethod(Method *M) {
37   cout << M;
38 }
39
40 static void PrintIntervalPartition(Method *M) {
41   cout << cfg::IntervalPartition(M);
42 }
43
44 static void PrintClassifiedExprs(Method *M) {
45   cout << "Classified expressions for: " << M->getName() << "\n";
46   Method::inst_iterator I = M->inst_begin(), E = M->inst_end();
47   for (; I != E; ++I) {
48     cout << *I;
49
50     if ((*I)->getType() == Type::VoidTy) continue;
51     analysis::ExprType R = analysis::ClassifyExpression(*I);
52     if (R.Var == *I) continue;  // Doesn't tell us anything
53
54     cout << "\t\tExpr =";
55     switch (R.ExprTy) {
56     case analysis::ExprType::ScaledLinear:
57       WriteAsOperand(cout << "(", (Value*)R.Scale) << " ) *";
58       // fall through
59     case analysis::ExprType::Linear:
60       WriteAsOperand(cout << "(", R.Var) << " )";
61       if (R.Offset == 0) break;
62       else cout << " +";
63       // fall through
64     case analysis::ExprType::Constant:
65       if (R.Offset) WriteAsOperand(cout, (Value*)R.Offset); else cout << " 0";
66       break;
67     }
68     cout << "\n\n";
69   }
70 }
71
72 static void PrintInductionVariables(Method *M) {
73   cfg::LoopInfo LI(M);
74   for (Method::inst_iterator I = M->inst_begin(), E = M->inst_end();
75        I != E; ++I)
76     if (PHINode *PN = dyn_cast<PHINode>(*I)) {
77       InductionVariable IV(PN, &LI);
78       if (IV.InductionType != InductionVariable::Unknown)
79         cout << IV;
80     }
81 }
82
83
84 static void PrintInstForest(Method *M) {
85   cout << analysis::InstForest<char>(M);
86 }
87 static void PrintLoops(Method *M) {
88   cout << cfg::LoopInfo(M);
89 }
90 static void PrintCallGraph(Module *M) {
91   cout << cfg::CallGraph(M);
92 }
93
94 static void PrintUnsafePtrTypes(Module *M) {
95   FindUnsafePointerTypes FUPT;
96   FUPT.run(M);
97   FUPT.printResults(M, cout);
98 }
99
100 static void PrintUsedTypes(Module *M) {
101   FindUsedTypes FUT;
102   FUT.run(M);
103   FUT.printTypes(cout, M);
104 }
105
106 static void PrintDominatorSets(Method *M) {
107   cout << cfg::DominatorSet(M);
108 }
109 static void PrintImmediateDominators(Method *M) {
110   cout << cfg::ImmediateDominators(M);
111 }
112 static void PrintDominatorTree(Method *M) {
113   cout << cfg::DominatorTree(M);
114 }
115 static void PrintDominanceFrontier(Method *M) {
116   cout << cfg::DominanceFrontier(M);
117 }
118
119 static void PrintPostDominatorSets(Method *M) {
120   cout << cfg::DominatorSet(M, true);
121 }
122 static void PrintImmediatePostDoms(Method *M) {
123   cout << cfg::ImmediateDominators(cfg::DominatorSet(M, true));
124 }
125 static void PrintPostDomTree(Method *M) {
126   cout << cfg::DominatorTree(cfg::DominatorSet(M, true));
127 }
128 static void PrintPostDomFrontier(Method *M) {
129   cout << cfg::DominanceFrontier(cfg::DominatorSet(M, true));
130 }
131
132
133 enum Ans {
134   PassDone,   // Unique Marker
135   print, intervals, exprclassify, instforest, loops, indvars, callgraph,
136   printusedtypes, unsafepointertypes,
137
138   domset, idom, domtree, domfrontier,
139   postdomset, postidom, postdomtree, postdomfrontier,
140 };
141
142 cl::String InputFilename ("", "Load <arg> file to analyze", cl::NoFlags, "-");
143 cl::Flag   Quiet         ("q", "Don't print analysis pass names");
144 cl::Alias  QuietA        ("quiet", "Alias for -q", cl::NoFlags, Quiet);
145 cl::EnumList<enum Ans> AnalysesList(cl::NoFlags,
146   clEnumVal(print          , "Print each Method"),
147   clEnumVal(intervals      , "Print Interval Partitions"),
148   clEnumVal(exprclassify   , "Classify Expressions"),
149   clEnumVal(instforest     , "Print Instruction Forest"),
150   clEnumVal(loops          , "Print Loops"),
151   clEnumVal(indvars        , "Print Induction Variables"),
152   clEnumVal(callgraph      , "Print Call Graph"),
153   clEnumVal(printusedtypes , "Print Types Used by Module"),
154   clEnumVal(unsafepointertypes, "Print Unsafe Pointer Types"),
155
156   clEnumVal(domset         , "Print Dominator Sets"),
157   clEnumVal(idom           , "Print Immediate Dominators"),
158   clEnumVal(domtree        , "Print Dominator Tree"),
159   clEnumVal(domfrontier    , "Print Dominance Frontier"),
160
161   clEnumVal(postdomset     , "Print Postdominator Sets"),
162   clEnumVal(postidom       , "Print Immediate Postdominators"),
163   clEnumVal(postdomtree    , "Print Post Dominator Tree"),
164   clEnumVal(postdomfrontier, "Print Postdominance Frontier"),
165 0);
166
167 struct {
168   enum Ans AnID;
169   void (*AnPtr)(Method *M);
170 } MethAnTable[] = {
171   { print          , PrintMethod              },
172   { intervals      , PrintIntervalPartition   },
173   { exprclassify   , PrintClassifiedExprs     },
174   { instforest     , PrintInstForest          },
175   { loops          , PrintLoops               },
176   { indvars        , PrintInductionVariables  },
177
178   { domset         , PrintDominatorSets       },
179   { idom           , PrintImmediateDominators },
180   { domtree        , PrintDominatorTree       },
181   { domfrontier    , PrintDominanceFrontier   },
182
183   { postdomset     , PrintPostDominatorSets   },
184   { postidom       , PrintImmediatePostDoms   },
185   { postdomtree    , PrintPostDomTree         },
186   { postdomfrontier, PrintPostDomFrontier     },
187 };
188
189 pair<enum Ans, void (*)(Module *)> ModAnTable[] = {
190   pair<enum Ans, void (*)(Module *)>(callgraph         , PrintCallGraph),
191   pair<enum Ans, void (*)(Module *)>(printusedtypes    , PrintUsedTypes),
192   pair<enum Ans, void (*)(Module *)>(unsafepointertypes, PrintUnsafePtrTypes),
193 };
194
195
196
197 int main(int argc, char **argv) {
198   cl::ParseCommandLineOptions(argc, argv, " llvm analysis printer tool\n");
199
200   Module *C = ParseBytecodeFile(InputFilename);
201   if (!C && !(C = ParseAssemblyFile(InputFilename))) {
202     cerr << "Input file didn't read correctly.\n";
203     return 1;
204   }
205
206   // Loop over all of the analyses looking for module level analyses to run...
207   for (unsigned i = 0; i < AnalysesList.size(); ++i) {
208     enum Ans AnalysisPass = AnalysesList[i];
209
210     for (unsigned j = 0; j < sizeof(ModAnTable)/sizeof(ModAnTable[0]); ++j) {
211       if (ModAnTable[j].first == AnalysisPass) {
212         if (!Quiet)
213           cerr << "Running: " << AnalysesList.getArgDescription(AnalysisPass) 
214                << " analysis on module!\n";
215         ModAnTable[j].second(C);
216         AnalysesList[i] = PassDone;  // Mark pass as complete so that we don't
217         break;                       // get an error later
218       }
219     }
220   }  
221
222   // Loop over all of the methods in the module...
223   for (Module::iterator I = C->begin(), E = C->end(); I != E; ++I) {
224     Method *M = *I;
225     if (M->isExternal()) continue;
226
227     for (unsigned i = 0; i < AnalysesList.size(); ++i) {
228       enum Ans AnalysisPass = AnalysesList[i];
229       if (AnalysisPass == PassDone) continue;  // Don't rerun module analyses
230
231       // Loop over all of the analyses to be run...
232       unsigned j;
233       for (j = 0; j < sizeof(MethAnTable)/sizeof(MethAnTable[0]); ++j) {
234         if (AnalysisPass == MethAnTable[j].AnID) {
235           if (!Quiet)
236             cerr << "Running: " << AnalysesList.getArgDescription(AnalysisPass) 
237                  << " analysis on '" << ((Value*)M)->getName() << "'!\n";
238           MethAnTable[j].AnPtr(M);
239           break;
240         }
241       }
242       if (j == sizeof(MethAnTable)/sizeof(MethAnTable[0])) 
243         cerr << "Analysis tables inconsistent!\n";
244     }
245   }
246
247   delete C;
248   return 0;
249 }