1//===-- llvm-dis.cpp - The low-level LLVM disassembler --------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This utility may be invoked in the following manner:
11//  llvm-dis [options]      - Read LLVM bitcode from stdin, write asm to stdout
12//  llvm-dis [options] x.bc - Read LLVM bitcode from the x.bc file, write asm
13//                            to the x.ll file.
14//  Options:
15//      --help   - Output information about command line switches
16//
17//===----------------------------------------------------------------------===//
18
19#include "llvm/LLVMContext.h"
20#include "llvm/DebugInfo.h"
21#include "llvm/Module.h"
22#include "llvm/Type.h"
23#include "llvm/IntrinsicInst.h"
24#include "llvm/Bitcode/ReaderWriter.h"
25#include "llvm/Assembly/AssemblyAnnotationWriter.h"
26#include "llvm/Support/CommandLine.h"
27#include "llvm/Support/DataStream.h"
28#include "llvm/Support/FormattedStream.h"
29#include "llvm/Support/ManagedStatic.h"
30#include "llvm/Support/MemoryBuffer.h"
31#include "llvm/Support/PrettyStackTrace.h"
32#include "llvm/Support/ToolOutputFile.h"
33#include "llvm/Support/Signals.h"
34#include "llvm/Support/system_error.h"
35using namespace llvm;
36
37static cl::opt<std::string>
38InputFilename(cl::Positional, cl::desc("<input bitcode>"), cl::init("-"));
39
40static cl::opt<std::string>
41OutputFilename("o", cl::desc("Override output filename"),
42               cl::value_desc("filename"));
43
44static cl::opt<bool>
45Force("f", cl::desc("Enable binary output on terminals"));
46
47static cl::opt<bool>
48DontPrint("disable-output", cl::desc("Don't output the .ll file"), cl::Hidden);
49
50static cl::opt<bool>
51ShowAnnotations("show-annotations",
52                cl::desc("Add informational comments to the .ll file"));
53
54namespace {
55
56static void printDebugLoc(const DebugLoc &DL, formatted_raw_ostream &OS) {
57  OS << DL.getLine() << ":" << DL.getCol();
58  if (MDNode *N = DL.getInlinedAt(getGlobalContext())) {
59    DebugLoc IDL = DebugLoc::getFromDILocation(N);
60    if (!IDL.isUnknown()) {
61      OS << "@";
62      printDebugLoc(IDL,OS);
63    }
64  }
65}
66class CommentWriter : public AssemblyAnnotationWriter {
67public:
68  void emitFunctionAnnot(const Function *F,
69                         formatted_raw_ostream &OS) {
70    OS << "; [#uses=" << F->getNumUses() << ']';  // Output # uses
71    OS << '\n';
72  }
73  void printInfoComment(const Value &V, formatted_raw_ostream &OS) {
74    bool Padded = false;
75    if (!V.getType()->isVoidTy()) {
76      OS.PadToColumn(50);
77      Padded = true;
78      OS << "; [#uses=" << V.getNumUses() << " type=" << *V.getType() << "]";  // Output # uses and type
79    }
80    if (const Instruction *I = dyn_cast<Instruction>(&V)) {
81      const DebugLoc &DL = I->getDebugLoc();
82      if (!DL.isUnknown()) {
83        if (!Padded) {
84          OS.PadToColumn(50);
85          Padded = true;
86          OS << ";";
87        }
88        OS << " [debug line = ";
89        printDebugLoc(DL,OS);
90        OS << "]";
91      }
92      if (const DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(I)) {
93        DIVariable Var(DDI->getVariable());
94        if (!Padded) {
95          OS.PadToColumn(50);
96          OS << ";";
97        }
98        OS << " [debug variable = " << Var.getName() << "]";
99      }
100      else if (const DbgValueInst *DVI = dyn_cast<DbgValueInst>(I)) {
101        DIVariable Var(DVI->getVariable());
102        if (!Padded) {
103          OS.PadToColumn(50);
104          OS << ";";
105        }
106        OS << " [debug variable = " << Var.getName() << "]";
107      }
108    }
109  }
110};
111
112} // end anon namespace
113
114int main(int argc, char **argv) {
115  // Print a stack trace if we signal out.
116  sys::PrintStackTraceOnErrorSignal();
117  PrettyStackTraceProgram X(argc, argv);
118
119  LLVMContext &Context = getGlobalContext();
120  llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.
121
122
123  cl::ParseCommandLineOptions(argc, argv, "llvm .bc -> .ll disassembler\n");
124
125  std::string ErrorMessage;
126  std::auto_ptr<Module> M;
127
128  // Use the bitcode streaming interface
129  DataStreamer *streamer = getDataFileStreamer(InputFilename, &ErrorMessage);
130  if (streamer) {
131    std::string DisplayFilename;
132    if (InputFilename == "-")
133      DisplayFilename = "<stdin>";
134    else
135      DisplayFilename = InputFilename;
136    M.reset(getStreamedBitcodeModule(DisplayFilename, streamer, Context,
137                                     &ErrorMessage));
138    if(M.get() != 0 && M->MaterializeAllPermanently(&ErrorMessage)) {
139      M.reset();
140    }
141  }
142
143  if (M.get() == 0) {
144    errs() << argv[0] << ": ";
145    if (ErrorMessage.size())
146      errs() << ErrorMessage << "\n";
147    else
148      errs() << "bitcode didn't read correctly.\n";
149    return 1;
150  }
151
152  // Just use stdout.  We won't actually print anything on it.
153  if (DontPrint)
154    OutputFilename = "-";
155
156  if (OutputFilename.empty()) { // Unspecified output, infer it.
157    if (InputFilename == "-") {
158      OutputFilename = "-";
159    } else {
160      const std::string &IFN = InputFilename;
161      int Len = IFN.length();
162      // If the source ends in .bc, strip it off.
163      if (IFN[Len-3] == '.' && IFN[Len-2] == 'b' && IFN[Len-1] == 'c')
164        OutputFilename = std::string(IFN.begin(), IFN.end()-3)+".ll";
165      else
166        OutputFilename = IFN+".ll";
167    }
168  }
169
170  std::string ErrorInfo;
171  OwningPtr<tool_output_file>
172  Out(new tool_output_file(OutputFilename.c_str(), ErrorInfo,
173                           raw_fd_ostream::F_Binary));
174  if (!ErrorInfo.empty()) {
175    errs() << ErrorInfo << '\n';
176    return 1;
177  }
178
179  OwningPtr<AssemblyAnnotationWriter> Annotator;
180  if (ShowAnnotations)
181    Annotator.reset(new CommentWriter());
182
183  // All that llvm-dis does is write the assembly to a file.
184  if (!DontPrint)
185    M->print(Out->os(), Annotator.get());
186
187  // Declare success.
188  Out->keep();
189
190  return 0;
191}
192