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