llvm-dis.cpp revision 193323
1189251Ssam//===-- llvm-dis.cpp - The low-level LLVM disassembler --------------------===//
2189251Ssam//
3281806Srpaulo//                     The LLVM Compiler Infrastructure
4189251Ssam//
5252726Srpaulo// This file is distributed under the University of Illinois Open Source
6252726Srpaulo// License. See LICENSE.TXT for details.
7189251Ssam//
8189251Ssam//===----------------------------------------------------------------------===//
9189251Ssam//
10189251Ssam// This utility may be invoked in the following manner:
11189251Ssam//  llvm-dis [options]      - Read LLVM bitcode from stdin, write asm to stdout
12189251Ssam//  llvm-dis [options] x.bc - Read LLVM bitcode from the x.bc file, write asm
13189775Ssam//                            to the x.ll file.
14252726Srpaulo//  Options:
15252726Srpaulo//      --help   - Output information about command line switches
16289549Srpaulo//
17289549Srpaulo//===----------------------------------------------------------------------===//
18289549Srpaulo
19289549Srpaulo#include "llvm/Module.h"
20252726Srpaulo#include "llvm/PassManager.h"
21252726Srpaulo#include "llvm/Bitcode/ReaderWriter.h"
22252726Srpaulo#include "llvm/Assembly/PrintModulePass.h"
23189251Ssam#include "llvm/Support/CommandLine.h"
24214734Srpaulo#include "llvm/Support/ManagedStatic.h"
25214734Srpaulo#include "llvm/Support/MemoryBuffer.h"
26214734Srpaulo#include "llvm/Support/PrettyStackTrace.h"
27214734Srpaulo#include "llvm/Support/Streams.h"
28189251Ssam#include "llvm/Support/raw_ostream.h"
29189251Ssam#include "llvm/System/Signals.h"
30189251Ssam#include <iostream>
31189251Ssam#include <fstream>
32189251Ssam#include <memory>
33189251Ssamusing namespace llvm;
34189251Ssam
35189251Ssamstatic cl::opt<std::string>
36189251SsamInputFilename(cl::Positional, cl::desc("<input bitcode>"), cl::init("-"));
37189251Ssam
38189251Ssamstatic cl::opt<std::string>
39189251SsamOutputFilename("o", cl::desc("Override output filename"),
40189251Ssam               cl::value_desc("filename"));
41189251Ssam
42214734Srpaulostatic cl::opt<bool>
43189251SsamForce("f", cl::desc("Overwrite output files"));
44189251Ssam
45189251Ssamstatic cl::opt<bool>
46189251SsamDontPrint("disable-output", cl::desc("Don't output the .ll file"), cl::Hidden);
47189251Ssam
48189251Ssamint main(int argc, char **argv) {
49189251Ssam  // Print a stack trace if we signal out.
50189251Ssam  sys::PrintStackTraceOnErrorSignal();
51189251Ssam  PrettyStackTraceProgram X(argc, argv);
52189251Ssam
53214734Srpaulo  llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.
54281806Srpaulo  try {
55189251Ssam    cl::ParseCommandLineOptions(argc, argv, "llvm .bc -> .ll disassembler\n");
56189251Ssam
57189251Ssam    std::ostream *Out = &std::cout;  // Default to printing to stdout.
58281806Srpaulo    std::string ErrorMessage;
59281806Srpaulo
60281806Srpaulo    std::auto_ptr<Module> M;
61281806Srpaulo
62281806Srpaulo    if (MemoryBuffer *Buffer
63281806Srpaulo           = MemoryBuffer::getFileOrSTDIN(InputFilename, &ErrorMessage)) {
64281806Srpaulo      M.reset(ParseBitcodeFile(Buffer, &ErrorMessage));
65281806Srpaulo      delete Buffer;
66281806Srpaulo    }
67281806Srpaulo
68281806Srpaulo    if (M.get() == 0) {
69189251Ssam      cerr << argv[0] << ": ";
70281806Srpaulo      if (ErrorMessage.size())
71281806Srpaulo        cerr << ErrorMessage << "\n";
72281806Srpaulo      else
73281806Srpaulo        cerr << "bitcode didn't read correctly.\n";
74281806Srpaulo      return 1;
75281806Srpaulo    }
76281806Srpaulo
77189251Ssam    if (DontPrint) {
78189251Ssam      // Just use stdout.  We won't actually print anything on it.
79289549Srpaulo    } else if (OutputFilename != "") {   // Specified an output filename?
80289549Srpaulo      if (OutputFilename != "-") { // Not stdout?
81289549Srpaulo        if (!Force && std::ifstream(OutputFilename.c_str())) {
82289549Srpaulo          // If force is not specified, make sure not to overwrite a file!
83289549Srpaulo          cerr << argv[0] << ": error opening '" << OutputFilename
84289549Srpaulo               << "': file exists! Sending to standard output.\n";
85289549Srpaulo        } else {
86289549Srpaulo          Out = new std::ofstream(OutputFilename.c_str());
87289549Srpaulo        }
88289549Srpaulo      }
89289549Srpaulo    } else {
90289549Srpaulo      if (InputFilename == "-") {
91289549Srpaulo        OutputFilename = "-";
92289549Srpaulo      } else {
93289549Srpaulo        std::string IFN = InputFilename;
94289549Srpaulo        int Len = IFN.length();
95289549Srpaulo        if (IFN[Len-3] == '.' && IFN[Len-2] == 'b' && IFN[Len-1] == 'c') {
96289549Srpaulo          // Source ends in .bc
97289549Srpaulo          OutputFilename = std::string(IFN.begin(), IFN.end()-3)+".ll";
98289549Srpaulo        } else {
99289549Srpaulo          OutputFilename = IFN+".ll";
100289549Srpaulo        }
101289549Srpaulo
102289549Srpaulo        if (!Force && std::ifstream(OutputFilename.c_str())) {
103289549Srpaulo          // If force is not specified, make sure not to overwrite a file!
104289549Srpaulo          cerr << argv[0] << ": error opening '" << OutputFilename
105281806Srpaulo               << "': file exists! Sending to standard output.\n";
106189251Ssam        } else {
107281806Srpaulo          Out = new std::ofstream(OutputFilename.c_str());
108189251Ssam
109189251Ssam          // Make sure that the Out file gets unlinked from the disk if we get a
110281806Srpaulo          // SIGINT
111189251Ssam          sys::RemoveFileOnSignal(sys::Path(OutputFilename));
112189251Ssam        }
113189251Ssam      }
114189251Ssam    }
115189251Ssam
116189251Ssam    if (!Out->good()) {
117189251Ssam      cerr << argv[0] << ": error opening " << OutputFilename
118281806Srpaulo           << ": sending to stdout instead!\n";
119281806Srpaulo      Out = &std::cout;
120281806Srpaulo    }
121281806Srpaulo
122281806Srpaulo    // All that llvm-dis does is write the assembly to a file.
123281806Srpaulo    if (!DontPrint) {
124189251Ssam      PassManager Passes;
125189251Ssam      raw_os_ostream L(*Out);
126189251Ssam      Passes.add(createPrintModulePass(&L));
127189251Ssam      Passes.run(*M.get());
128281806Srpaulo    }
129189251Ssam
130189251Ssam    if (Out != &std::cout) {
131189251Ssam      ((std::ofstream*)Out)->close();
132214734Srpaulo      delete Out;
133189251Ssam    }
134281806Srpaulo    return 0;
135189251Ssam  } catch (const std::string& msg) {
136189251Ssam    cerr << argv[0] << ": " << msg << "\n";
137209158Srpaulo  } catch (...) {
138209158Srpaulo    cerr << argv[0] << ": Unexpected unknown exception occurred.\n";
139281806Srpaulo  }
140281806Srpaulo
141281806Srpaulo  return 1;
142281806Srpaulo}
143281806Srpaulo
144281806Srpaulo