llvm-dis.cpp revision 9bff2e952226a80b65a993a81e87abe5216ffc48
1009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner//===------------------------------------------------------------------------===
2009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner// LLVM 'DIS' UTILITY
3009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner//
4009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner// This utility may be invoked in the following manner:
5009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner//  dis [options]      - Read LLVM bytecode from stdin, write assembly to stdout
6009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner//  dis [options] x.bc - Read LLVM bytecode from the x.bc file, write assembly
7009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner//                       to the x.ll file.
89bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner//  Options:
99bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner//      --help   - Output information about command line switches
109bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner//       -dfo    - Print basic blocks in depth first order
119bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner//       -rdfo   - Print basic blocks in reverse depth first order
129bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner//       -po     - Print basic blocks in post order
139bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner//       -rpo    - Print basic blocks in reverse post order
149bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner//
159bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner// TODO: add -vcg which prints VCG compatible output.
16009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner//
17009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner//===------------------------------------------------------------------------===
18009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner
19009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner#include <iostream.h>
20009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner#include <fstream.h>
21009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner#include "llvm/Module.h"
22009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner#include "llvm/Assembly/Writer.h"
23009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner#include "llvm/Bytecode/Reader.h"
24009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner#include "llvm/Tools/CommandLine.h"
259bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner#include "llvm/Method.h"
269bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner#include "llvm/CFG.h"
27009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner
28009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattnerint main(int argc, char **argv) {
299bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner  // WriteMode - The different orderings to print basic blocks in...
309bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner  enum {
319bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner    Default = 0,                  // Method Order (list order)
329bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner    DepthFirst,                   // Depth First ordering
339bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner    ReverseDepthFirst,            // Reverse Depth First ordering
349bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner    PostOrder,                    // Post Order
359bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner    ReversePostOrder              // Reverse Post Order
369bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner  } WriteMode = Default;
379bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner
38009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner  ToolCommandLine Opts(argc, argv, false);
39009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner
40009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner  // We only support the options that the system parser does... if it left any
41009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner  // then we don't know what to do.
42009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner  //
43009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner  if (argc > 1) {
44009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner    for (int i = 1; i < argc; i++) {
459bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner      if (string(argv[i]) == string("--help")) {
469bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner	cerr << argv[0] << " usage:\n"
479bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner	     << "\tx.bc        - Parse <x.bc> file and output to x.ll\n"
489bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner	     << "\tno .bc file - Parse stdin and write to stdout.\n"
499bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner	     << "\t-dfo        - Write basic blocks in depth first order.\n"
509bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner	     << "\t-rdfo       - Write basic blocks in reverse DFO.\n"
519bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner	     << "\t-po         - Write basic blocks in postorder.\n"
529bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner	     << "\t-rpo        - Write basic blocks in reverse postorder.\n"
539bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner	     << "\t--help      - Print this usage information\n\n";
549bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner	return 1;
559bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner      } else if (string(argv[i]) == string("-dfo")) {
569bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner	WriteMode = DepthFirst;
579bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner      } else if (string(argv[i]) == string("-rdfo")) {
589bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner	WriteMode = ReverseDepthFirst;
599bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner      } else if (string(argv[i]) == string("-po")) {
609bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner	WriteMode = PostOrder;
619bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner      } else if (string(argv[i]) == string("-rpo")) {
629bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner	WriteMode = ReversePostOrder;
639bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner      } else {
64009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner	cerr << argv[0] << ": argument not recognized: '" << argv[i] << "'!\n";
659bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner      }
66009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner    }
67009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner  }
68009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner
69009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner  ostream *Out = &cout;  // Default to printing to stdout...
70009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner
71009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner  Module *C = ParseBytecodeFile(Opts.getInputFilename());
72009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner  if (C == 0) {
73009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner    cerr << "bytecode didn't read correctly.\n";
74009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner    return 1;
75009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner  }
76009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner
77009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner  if (Opts.getOutputFilename() != "-") {
78009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner    Out = new ofstream(Opts.getOutputFilename().c_str(),
79009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner                       (Opts.getForce() ? 0 : ios::noreplace)|ios::out);
80009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner    if (!Out->good()) {
81009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner      cerr << "Error opening " << Opts.getOutputFilename()
82009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner           << ": sending to stdout instead!\n";
83009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner      Out = &cout;
84009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner      }
85009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner  }
86009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner
87009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner  // All that dis does is write the assembly out to a file... which is exactly
88009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner  // what the writer library is supposed to do...
899bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner  //
909bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner  if (WriteMode == Default) {
919bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner    (*Out) << C;           // Print out in list order
929bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner  } else {
939bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner    // TODO: This does not print anything other than the basic blocks in the
949bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner    // methods... more should definately be printed.  It should be valid output
959bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner    // consumable by the assembler.
969bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner    //
979bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner    for (Module::MethodListType::iterator I = C->getMethodList().begin();
989bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner	 I != C->getMethodList().end(); I++) {
999bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner      Method *M = *I;
1009bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner      (*Out) << "-------------- Method: " << M->getName() << " -------------\n";
1019bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner
1029bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner      switch (WriteMode) {
1039bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner      case DepthFirst:                   // Depth First ordering
1049bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner	copy(cfg::df_begin(M), cfg::df_end(M),
1059bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner	     ostream_iterator<BasicBlock*>(*Out, "\n"));
1069bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner	break;
1079bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner      case ReverseDepthFirst:            // Reverse Depth First ordering
1089bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner	copy(cfg::df_begin(M, true), cfg::df_end(M),
1099bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner	     ostream_iterator<BasicBlock*>(*Out, "\n"));
1109bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner	break;
1119bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner      case PostOrder:                    // Post Order
1129bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner	copy(cfg::po_begin(M), cfg::po_end(M),
1139bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner	     ostream_iterator<BasicBlock*>(*Out, "\n"));
1149bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner	break;
1159bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner      case ReversePostOrder: {           // Reverse Post Order
1169bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner	cfg::ReversePostOrderTraversal RPOT(M);
1179bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner	copy(RPOT.begin(), RPOT.end(),
1189bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner	     ostream_iterator<BasicBlock*>(*Out, "\n"));
1199bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner	break;
1209bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner      }
1219bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner      default:
1229bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner	abort();
1239bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner	break;
1249bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner      }
1259bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner    }
1269bff2e952226a80b65a993a81e87abe5216ffc48Chris Lattner  }
127009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner  delete C;
128009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner
129009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner  if (Out != &cout) delete Out;
130009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner  return 0;
131009505452b713ed2e3a8e99c5545a6e721c65495Chris Lattner}
132