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