summaryrefslogtreecommitdiff
path: root/tools/dis/dis.cpp
blob: deaf3a28fd50acdac68eae17535ad20ef43c367c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
//===------------------------------------------------------------------------===
// LLVM 'DIS' UTILITY 
//
// This utility may be invoked in the following manner:
//  dis [options]      - Read LLVM bytecode from stdin, write assembly to stdout
//  dis [options] x.bc - Read LLVM bytecode from the x.bc file, write assembly
//                       to the x.ll file.
//  Options:
//      --help   - Output information about command line switches
//       -dfo    - Print basic blocks in depth first order
//       -rdfo   - Print basic blocks in reverse depth first order
//       -po     - Print basic blocks in post order
//       -rpo    - Print basic blocks in reverse post order
//
// TODO: add -vcg which prints VCG compatible output.
//
//===------------------------------------------------------------------------===

#include <iostream.h>
#include <fstream.h>
#include "llvm/Module.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/Bytecode/Reader.h"
#include "llvm/Tools/CommandLine.h"
#include "llvm/Method.h"
#include "llvm/CFG.h"

int main(int argc, char **argv) {
  // WriteMode - The different orderings to print basic blocks in...
  enum {
    Default = 0,                  // Method Order (list order)
    DepthFirst,                   // Depth First ordering
    ReverseDepthFirst,            // Reverse Depth First ordering
    PostOrder,                    // Post Order
    ReversePostOrder              // Reverse Post Order
  } WriteMode = Default;

  ToolCommandLine Opts(argc, argv, false);

  // We only support the options that the system parser does... if it left any
  // then we don't know what to do.
  //
  if (argc > 1) {
    for (int i = 1; i < argc; i++) {
      if (string(argv[i]) == string("--help")) {
	cerr << argv[0] << " usage:\n"
	     << "\tx.bc        - Parse <x.bc> file and output to x.ll\n"
	     << "\tno .bc file - Parse stdin and write to stdout.\n"
	     << "\t-dfo        - Write basic blocks in depth first order.\n"
	     << "\t-rdfo       - Write basic blocks in reverse DFO.\n"
	     << "\t-po         - Write basic blocks in postorder.\n"
	     << "\t-rpo        - Write basic blocks in reverse postorder.\n"
	     << "\t--help      - Print this usage information\n\n";
	return 1;
      } else if (string(argv[i]) == string("-dfo")) {
	WriteMode = DepthFirst;
      } else if (string(argv[i]) == string("-rdfo")) {
	WriteMode = ReverseDepthFirst;
      } else if (string(argv[i]) == string("-po")) {
	WriteMode = PostOrder;
      } else if (string(argv[i]) == string("-rpo")) {
	WriteMode = ReversePostOrder;
      } else {
	cerr << argv[0] << ": argument not recognized: '" << argv[i] << "'!\n";
      }
    }
  }
  
  ostream *Out = &cout;  // Default to printing to stdout...

  Module *C = ParseBytecodeFile(Opts.getInputFilename());
  if (C == 0) {
    cerr << "bytecode didn't read correctly.\n";
    return 1;
  }
  
  if (Opts.getOutputFilename() != "-") {
    Out = new ofstream(Opts.getOutputFilename().c_str(), 
                       (Opts.getForce() ? 0 : ios::noreplace)|ios::out);
    if (!Out->good()) {
      cerr << "Error opening " << Opts.getOutputFilename() 
           << ": sending to stdout instead!\n";
      Out = &cout;
      }
  }
    
  // All that dis does is write the assembly out to a file... which is exactly
  // what the writer library is supposed to do...
  //
  if (WriteMode == Default) {
    (*Out) << C;           // Print out in list order
  } else {
    // TODO: This does not print anything other than the basic blocks in the
    // methods... more should definately be printed.  It should be valid output
    // consumable by the assembler.
    //
    for (Module::iterator I = C->begin(), End = C->end(); I != End; ++I) {
      Method *M = *I;
      (*Out) << "-------------- Method: " << M->getName() << " -------------\n";

      switch (WriteMode) {
      case DepthFirst:                   // Depth First ordering
	copy(cfg::df_begin(M), cfg::df_end(M),
	     ostream_iterator<BasicBlock*>(*Out, "\n"));
	break;
      case ReverseDepthFirst:            // Reverse Depth First ordering
	copy(cfg::df_begin(M, true), cfg::df_end(M),
	     ostream_iterator<BasicBlock*>(*Out, "\n"));
	break;
      case PostOrder:                    // Post Order
	copy(cfg::po_begin(M), cfg::po_end(M),
	     ostream_iterator<BasicBlock*>(*Out, "\n"));
	break;
      case ReversePostOrder: {           // Reverse Post Order
	cfg::ReversePostOrderTraversal RPOT(M);
	copy(RPOT.begin(), RPOT.end(),
	     ostream_iterator<BasicBlock*>(*Out, "\n"));
	break;
      }
      default:
	abort();
	break;
      }
    }
  }
  delete C;

  if (Out != &cout) delete Out;
  return 0;
}