Reordered link line for correct static linking.
[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::iterator I = C->begin(), End = C->end(); I != End; ++I) {
98       Method *M = *I;
99       (*Out) << "-------------- Method: " << M->getName() << " -------------\n";
100
101       switch (WriteMode) {
102       case DepthFirst:                   // Depth First ordering
103         copy(cfg::df_begin(M), cfg::df_end(M),
104              ostream_iterator<BasicBlock*>(*Out, "\n"));
105         break;
106       case ReverseDepthFirst:            // Reverse Depth First ordering
107         copy(cfg::df_begin(M, true), cfg::df_end(M),
108              ostream_iterator<BasicBlock*>(*Out, "\n"));
109         break;
110       case PostOrder:                    // Post Order
111         copy(cfg::po_begin(M), cfg::po_end(M),
112              ostream_iterator<BasicBlock*>(*Out, "\n"));
113         break;
114       case ReversePostOrder: {           // Reverse Post Order
115         cfg::ReversePostOrderTraversal RPOT(M);
116         copy(RPOT.begin(), RPOT.end(),
117              ostream_iterator<BasicBlock*>(*Out, "\n"));
118         break;
119       }
120       default:
121         abort();
122         break;
123       }
124     }
125   }
126   delete C;
127
128   if (Out != &cout) delete Out;
129   return 0;
130 }