Added options to print out basic blocks in a variety of different orderings
[oota-llvm.git] / tools / llvm-dis / dis.cpp
1 //===------------------------------------------------------------------------===
2 // LLVM 'DIS' UTILITY 
3 //
4 // This utility may be invoked in the following manner:
5 //  dis [options]      - Read LLVM bytecode from stdin, write assembly to stdout
6 //  dis [options] x.bc - Read LLVM bytecode from the x.bc file, write assembly
7 //                       to the x.ll file.
8 //  Options:
9 //      --help   - Output information about command line switches
10 //       -dfo    - Print basic blocks in depth first order
11 //       -rdfo   - Print basic blocks in reverse depth first order
12 //       -po     - Print basic blocks in post order
13 //       -rpo    - Print basic blocks in reverse post order
14 //
15 // TODO: add -vcg which prints VCG compatible output.
16 //
17 //===------------------------------------------------------------------------===
18
19 #include <iostream.h>
20 #include <fstream.h>
21 #include "llvm/Module.h"
22 #include "llvm/Assembly/Writer.h"
23 #include "llvm/Bytecode/Reader.h"
24 #include "llvm/Tools/CommandLine.h"
25 #include "llvm/Method.h"
26 #include "llvm/CFG.h"
27
28 int main(int argc, char **argv) {
29   // WriteMode - The different orderings to print basic blocks in...
30   enum {
31     Default = 0,                  // Method Order (list order)
32     DepthFirst,                   // Depth First ordering
33     ReverseDepthFirst,            // Reverse Depth First ordering
34     PostOrder,                    // Post Order
35     ReversePostOrder              // Reverse Post Order
36   } WriteMode = Default;
37
38   ToolCommandLine Opts(argc, argv, false);
39
40   // We only support the options that the system parser does... if it left any
41   // then we don't know what to do.
42   //
43   if (argc > 1) {
44     for (int i = 1; i < argc; i++) {
45       if (string(argv[i]) == string("--help")) {
46         cerr << argv[0] << " usage:\n"
47              << "\tx.bc        - Parse <x.bc> file and output to x.ll\n"
48              << "\tno .bc file - Parse stdin and write to stdout.\n"
49              << "\t-dfo        - Write basic blocks in depth first order.\n"
50              << "\t-rdfo       - Write basic blocks in reverse DFO.\n"
51              << "\t-po         - Write basic blocks in postorder.\n"
52              << "\t-rpo        - Write basic blocks in reverse postorder.\n"
53              << "\t--help      - Print this usage information\n\n";
54         return 1;
55       } else if (string(argv[i]) == string("-dfo")) {
56         WriteMode = DepthFirst;
57       } else if (string(argv[i]) == string("-rdfo")) {
58         WriteMode = ReverseDepthFirst;
59       } else if (string(argv[i]) == string("-po")) {
60         WriteMode = PostOrder;
61       } else if (string(argv[i]) == string("-rpo")) {
62         WriteMode = ReversePostOrder;
63       } else {
64         cerr << argv[0] << ": argument not recognized: '" << argv[i] << "'!\n";
65       }
66     }
67   }
68   
69   ostream *Out = &cout;  // Default to printing to stdout...
70
71   Module *C = ParseBytecodeFile(Opts.getInputFilename());
72   if (C == 0) {
73     cerr << "bytecode didn't read correctly.\n";
74     return 1;
75   }
76   
77   if (Opts.getOutputFilename() != "-") {
78     Out = new ofstream(Opts.getOutputFilename().c_str(), 
79                        (Opts.getForce() ? 0 : ios::noreplace)|ios::out);
80     if (!Out->good()) {
81       cerr << "Error opening " << Opts.getOutputFilename() 
82            << ": sending to stdout instead!\n";
83       Out = &cout;
84       }
85   }
86     
87   // All that dis does is write the assembly out to a file... which is exactly
88   // what the writer library is supposed to do...
89   //
90   if (WriteMode == Default) {
91     (*Out) << C;           // Print out in list order
92   } else {
93     // TODO: This does not print anything other than the basic blocks in the
94     // methods... more should definately be printed.  It should be valid output
95     // consumable by the assembler.
96     //
97     for (Module::MethodListType::iterator I = C->getMethodList().begin(); 
98          I != C->getMethodList().end(); I++) {
99       Method *M = *I;
100       (*Out) << "-------------- Method: " << M->getName() << " -------------\n";
101
102       switch (WriteMode) {
103       case DepthFirst:                   // Depth First ordering
104         copy(cfg::df_begin(M), cfg::df_end(M),
105              ostream_iterator<BasicBlock*>(*Out, "\n"));
106         break;
107       case ReverseDepthFirst:            // Reverse Depth First ordering
108         copy(cfg::df_begin(M, true), cfg::df_end(M),
109              ostream_iterator<BasicBlock*>(*Out, "\n"));
110         break;
111       case PostOrder:                    // Post Order
112         copy(cfg::po_begin(M), cfg::po_end(M),
113              ostream_iterator<BasicBlock*>(*Out, "\n"));
114         break;
115       case ReversePostOrder: {           // Reverse Post Order
116         cfg::ReversePostOrderTraversal RPOT(M);
117         copy(RPOT.begin(), RPOT.end(),
118              ostream_iterator<BasicBlock*>(*Out, "\n"));
119         break;
120       }
121       default:
122         abort();
123         break;
124       }
125     }
126   }
127   delete C;
128
129   if (Out != &cout) delete Out;
130   return 0;
131 }