Large scale changes to implement new command line argument facility
[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 <iostream>
14 #include "llvm/Instruction.h"
15 #include "llvm/Module.h"
16 #include "llvm/Method.h"
17 #include "llvm/Bytecode/Reader.h"
18 #include "llvm/Assembly/Parser.h"
19 #include "llvm/Tools/CommandLine.h"
20 #include "llvm/Analysis/Writer.h"
21
22 #include "llvm/Analysis/Dominators.h"
23 #include "llvm/Analysis/IntervalPartition.h"
24 #include "llvm/Analysis/Expressions.h"
25
26 static void PrintMethod(Method *M) {
27   cout << M;
28 }
29
30 static void PrintIntervalPartition(Method *M) {
31   cout << cfg::IntervalPartition(M);
32 }
33
34 static void PrintClassifiedExprs(Method *M) {
35   cout << "Classified expressions for: " << M->getName() << endl;
36   Method::inst_iterator I = M->inst_begin(), E = M->inst_end();
37   for (; I != E; ++I) {
38     cout << *I;
39
40     if ((*I)->getType() == Type::VoidTy) continue;
41     analysis::ExprType R = analysis::ClassifyExpression(*I);
42     if (R.Var == *I) continue;  // Doesn't tell us anything
43
44     cout << "\t\tExpr =";
45     switch (R.ExprTy) {
46     case analysis::ExprType::ScaledLinear:
47       WriteAsOperand(cout, (Value*)R.Scale) << " *";
48       // fall through
49     case analysis::ExprType::Linear:
50       WriteAsOperand(cout, R.Var);
51       if (R.Offset == 0) break;
52       else cout << " +";
53       // fall through
54     case analysis::ExprType::Constant:
55       if (R.Offset) WriteAsOperand(cout, (Value*)R.Offset); else cout << " 0";
56       break;
57     }
58     cout << endl << endl;
59   }
60 }
61
62
63 static void PrintDominatorSets(Method *M) {
64   cout << cfg::DominatorSet(M);
65 }
66 static void PrintImmediateDominators(Method *M) {
67   cout << cfg::ImmediateDominators(M);
68 }
69 static void PrintDominatorTree(Method *M) {
70   cout << cfg::DominatorTree(M);
71 }
72 static void PrintDominanceFrontier(Method *M) {
73   cout << cfg::DominanceFrontier(M);
74 }
75
76 static void PrintPostDominatorSets(Method *M) {
77   cout << cfg::DominatorSet(M, true);
78 }
79 static void PrintImmediatePostDoms(Method *M) {
80   cout << cfg::ImmediateDominators(cfg::DominatorSet(M, true));
81 }
82 static void PrintPostDomTree(Method *M) {
83   cout << cfg::DominatorTree(cfg::DominatorSet(M, true));
84 }
85 static void PrintPostDomFrontier(Method *M) {
86   cout << cfg::DominanceFrontier(cfg::DominatorSet(M, true));
87 }
88
89 enum Ans {
90   print, intervals, exprclassify,
91   domset, idom, domtree, domfrontier,
92   postdomset, postidom, postdomtree, postdomfrontier,
93 };
94
95 cl::String InputFilename ("", "Load <arg> file to analyze", 0, "-");
96 cl::Flag   Quiet         ("q", "Don't print analysis pass names", 0, false);
97 cl::EnumList<enum Ans> AnalysesList(cl::NoFlags,
98   clEnumVal(print          , "Print each Method"),
99   clEnumVal(intervals      , "Print Interval Partitions"),
100   clEnumVal(exprclassify   , "Classify Expressions"),
101
102   clEnumVal(domset         , "Print Dominator Sets"),
103   clEnumVal(idom           , "Print Immediate Dominators"),
104   clEnumVal(domtree        , "Print Dominator Tree"),
105   clEnumVal(domfrontier    , "Print Dominance Frontier"),
106
107   clEnumVal(postdomset     , "Print Postdominator Sets"),
108   clEnumVal(postidom       , "Print Immediate Postdominators"),
109   clEnumVal(postdomtree    , "Print Post Dominator Tree"),
110   clEnumVal(postdomfrontier, "Print Postdominance Frontier"),
111 0);
112
113 struct {
114   enum Ans AnID;
115   void (*AnPtr)(Method *M);
116 } AnTable[] = {
117   { print          , PrintMethod              },
118   { intervals      , PrintIntervalPartition   },
119   { exprclassify   , PrintClassifiedExprs     },
120
121   { domset         , PrintDominatorSets       },
122   { idom           , PrintImmediateDominators },
123   { domtree        , PrintDominatorTree       },
124   { domfrontier    , PrintDominanceFrontier   },
125
126   { postdomset     , PrintPostDominatorSets   },
127   { postidom       , PrintImmediatePostDoms   },
128   { postdomtree    , PrintPostDomTree         },
129   { postdomfrontier, PrintPostDomFrontier     },
130 };
131
132 int main(int argc, char **argv) {
133   cl::ParseCommandLineOptions(argc, argv, " llvm analysis printer tool\n");
134
135   Module *C = ParseBytecodeFile(InputFilename.getValue());
136   if (!C && !(C = ParseAssemblyFile(InputFilename.getValue()))) {
137     cerr << "Input file didn't read correctly.\n";
138     return 1;
139   }
140
141   // Loop over all of the methods in the module...
142   for (Module::iterator I = C->begin(), E = C->end(); I != E; ++I) {
143     Method *M = *I;
144     if (M->isExternal()) continue;
145
146     for (unsigned i = 0; i < AnalysesList.size(); ++i) {
147       enum Ans AnalysisPass = AnalysesList[i];
148
149       // Loop over all of the analyses to be run...
150       unsigned j;
151       for (j = 0; j < sizeof(AnTable)/sizeof(AnTable[0]); ++j) {
152         if (AnalysisPass == AnTable[j].AnID) {
153           if (!Quiet)
154             cerr << "Running: " << AnalysesList.getArgDescription(AnalysisPass) 
155                  << " analysis on '" << ((Value*)M)->getName() << "'!\n";
156           AnTable[j].AnPtr(M);
157           break;
158         }
159       }
160       if (j == sizeof(AnTable)/sizeof(AnTable[0])) 
161         cerr << "Analysis tables inconsistent!\n";
162     }
163   }
164
165   delete C;
166   return 0;
167 }