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