llvm-dis.cpp revision 249423
1230557Sjimharris//===-- llvm-dis.cpp - The low-level LLVM disassembler --------------------===//
2230557Sjimharris//
3230557Sjimharris//                     The LLVM Compiler Infrastructure
4230557Sjimharris//
5230557Sjimharris// This file is distributed under the University of Illinois Open Source
6230557Sjimharris// License. See LICENSE.TXT for details.
7230557Sjimharris//
8230557Sjimharris//===----------------------------------------------------------------------===//
9230557Sjimharris//
10230557Sjimharris// This utility may be invoked in the following manner:
11230557Sjimharris//  llvm-dis [options]      - Read LLVM bitcode from stdin, write asm to stdout
12230557Sjimharris//  llvm-dis [options] x.bc - Read LLVM bitcode from the x.bc file, write asm
13230557Sjimharris//                            to the x.ll file.
14230557Sjimharris//  Options:
15230557Sjimharris//      --help   - Output information about command line switches
16230557Sjimharris//
17230557Sjimharris//===----------------------------------------------------------------------===//
18230557Sjimharris
19230557Sjimharris#include "llvm/IR/LLVMContext.h"
20230557Sjimharris#include "llvm/Assembly/AssemblyAnnotationWriter.h"
21230557Sjimharris#include "llvm/Bitcode/ReaderWriter.h"
22230557Sjimharris#include "llvm/DebugInfo.h"
23230557Sjimharris#include "llvm/IR/IntrinsicInst.h"
24230557Sjimharris#include "llvm/IR/Module.h"
25230557Sjimharris#include "llvm/IR/Type.h"
26230557Sjimharris#include "llvm/Support/CommandLine.h"
27230557Sjimharris#include "llvm/Support/DataStream.h"
28230557Sjimharris#include "llvm/Support/FormattedStream.h"
29230557Sjimharris#include "llvm/Support/ManagedStatic.h"
30230557Sjimharris#include "llvm/Support/MemoryBuffer.h"
31230557Sjimharris#include "llvm/Support/PrettyStackTrace.h"
32230557Sjimharris#include "llvm/Support/Signals.h"
33230557Sjimharris#include "llvm/Support/ToolOutputFile.h"
34230557Sjimharris#include "llvm/Support/system_error.h"
35230557Sjimharrisusing namespace llvm;
36230557Sjimharris
37230557Sjimharrisstatic cl::opt<std::string>
38230557SjimharrisInputFilename(cl::Positional, cl::desc("<input bitcode>"), cl::init("-"));
39230557Sjimharris
40230557Sjimharrisstatic cl::opt<std::string>
41230557SjimharrisOutputFilename("o", cl::desc("Override output filename"),
42230557Sjimharris               cl::value_desc("filename"));
43230557Sjimharris
44230557Sjimharrisstatic cl::opt<bool>
45230557SjimharrisForce("f", cl::desc("Enable binary output on terminals"));
46230557Sjimharris
47230557Sjimharrisstatic cl::opt<bool>
48230557SjimharrisDontPrint("disable-output", cl::desc("Don't output the .ll file"), cl::Hidden);
49230557Sjimharris
50230557Sjimharrisstatic cl::opt<bool>
51230557SjimharrisShowAnnotations("show-annotations",
52230557Sjimharris                cl::desc("Add informational comments to the .ll file"));
53230557Sjimharris
54230557Sjimharrisnamespace {
55230557Sjimharris
56230557Sjimharrisstatic void printDebugLoc(const DebugLoc &DL, formatted_raw_ostream &OS) {
57230557Sjimharris  OS << DL.getLine() << ":" << DL.getCol();
58230557Sjimharris  if (MDNode *N = DL.getInlinedAt(getGlobalContext())) {
59230557Sjimharris    DebugLoc IDL = DebugLoc::getFromDILocation(N);
60230557Sjimharris    if (!IDL.isUnknown()) {
61230557Sjimharris      OS << "@";
62230557Sjimharris      printDebugLoc(IDL,OS);
63230557Sjimharris    }
64230557Sjimharris  }
65230557Sjimharris}
66230557Sjimharrisclass CommentWriter : public AssemblyAnnotationWriter {
67230557Sjimharrispublic:
68230557Sjimharris  void emitFunctionAnnot(const Function *F,
69230557Sjimharris                         formatted_raw_ostream &OS) {
70230557Sjimharris    OS << "; [#uses=" << F->getNumUses() << ']';  // Output # uses
71230557Sjimharris    OS << '\n';
72230557Sjimharris  }
73230557Sjimharris  void printInfoComment(const Value &V, formatted_raw_ostream &OS) {
74230557Sjimharris    bool Padded = false;
75230557Sjimharris    if (!V.getType()->isVoidTy()) {
76230557Sjimharris      OS.PadToColumn(50);
77230557Sjimharris      Padded = true;
78230557Sjimharris      OS << "; [#uses=" << V.getNumUses() << " type=" << *V.getType() << "]";  // Output # uses and type
79230557Sjimharris    }
80230557Sjimharris    if (const Instruction *I = dyn_cast<Instruction>(&V)) {
81230557Sjimharris      const DebugLoc &DL = I->getDebugLoc();
82230557Sjimharris      if (!DL.isUnknown()) {
83230557Sjimharris        if (!Padded) {
84230557Sjimharris          OS.PadToColumn(50);
85230557Sjimharris          Padded = true;
86230557Sjimharris          OS << ";";
87230557Sjimharris        }
88230557Sjimharris        OS << " [debug line = ";
89230557Sjimharris        printDebugLoc(DL,OS);
90230557Sjimharris        OS << "]";
91230557Sjimharris      }
92230557Sjimharris      if (const DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(I)) {
93230557Sjimharris        DIVariable Var(DDI->getVariable());
94230557Sjimharris        if (!Padded) {
95230557Sjimharris          OS.PadToColumn(50);
96230557Sjimharris          OS << ";";
97230557Sjimharris        }
98230557Sjimharris        OS << " [debug variable = " << Var.getName() << "]";
99230557Sjimharris      }
100230557Sjimharris      else if (const DbgValueInst *DVI = dyn_cast<DbgValueInst>(I)) {
101230557Sjimharris        DIVariable Var(DVI->getVariable());
102230557Sjimharris        if (!Padded) {
103230557Sjimharris          OS.PadToColumn(50);
104230557Sjimharris          OS << ";";
105230557Sjimharris        }
106230557Sjimharris        OS << " [debug variable = " << Var.getName() << "]";
107230557Sjimharris      }
108230557Sjimharris    }
109230557Sjimharris  }
110230557Sjimharris};
111230557Sjimharris
112230557Sjimharris} // end anon namespace
113230557Sjimharris
114230557Sjimharrisint main(int argc, char **argv) {
115230557Sjimharris  // Print a stack trace if we signal out.
116230557Sjimharris  sys::PrintStackTraceOnErrorSignal();
117230557Sjimharris  PrettyStackTraceProgram X(argc, argv);
118230557Sjimharris
119230557Sjimharris  LLVMContext &Context = getGlobalContext();
120230557Sjimharris  llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.
121230557Sjimharris
122230557Sjimharris
123230557Sjimharris  cl::ParseCommandLineOptions(argc, argv, "llvm .bc -> .ll disassembler\n");
124230557Sjimharris
125230557Sjimharris  std::string ErrorMessage;
126230557Sjimharris  std::auto_ptr<Module> M;
127230557Sjimharris
128230557Sjimharris  // Use the bitcode streaming interface
129230557Sjimharris  DataStreamer *streamer = getDataFileStreamer(InputFilename, &ErrorMessage);
130230557Sjimharris  if (streamer) {
131230557Sjimharris    std::string DisplayFilename;
132230557Sjimharris    if (InputFilename == "-")
133230557Sjimharris      DisplayFilename = "<stdin>";
134230557Sjimharris    else
135230557Sjimharris      DisplayFilename = InputFilename;
136230557Sjimharris    M.reset(getStreamedBitcodeModule(DisplayFilename, streamer, Context,
137230557Sjimharris                                     &ErrorMessage));
138230557Sjimharris    if(M.get() != 0 && M->MaterializeAllPermanently(&ErrorMessage)) {
139230557Sjimharris      M.reset();
140230557Sjimharris    }
141230557Sjimharris  }
142230557Sjimharris
143230557Sjimharris  if (M.get() == 0) {
144230557Sjimharris    errs() << argv[0] << ": ";
145230557Sjimharris    if (ErrorMessage.size())
146230557Sjimharris      errs() << ErrorMessage << "\n";
147230557Sjimharris    else
148230557Sjimharris      errs() << "bitcode didn't read correctly.\n";
149230557Sjimharris    return 1;
150230557Sjimharris  }
151230557Sjimharris
152230557Sjimharris  // Just use stdout.  We won't actually print anything on it.
153230557Sjimharris  if (DontPrint)
154230557Sjimharris    OutputFilename = "-";
155230557Sjimharris
156230557Sjimharris  if (OutputFilename.empty()) { // Unspecified output, infer it.
157230557Sjimharris    if (InputFilename == "-") {
158230557Sjimharris      OutputFilename = "-";
159230557Sjimharris    } else {
160230557Sjimharris      const std::string &IFN = InputFilename;
161230557Sjimharris      int Len = IFN.length();
162230557Sjimharris      // If the source ends in .bc, strip it off.
163230557Sjimharris      if (IFN[Len-3] == '.' && IFN[Len-2] == 'b' && IFN[Len-1] == 'c')
164230557Sjimharris        OutputFilename = std::string(IFN.begin(), IFN.end()-3)+".ll";
165230557Sjimharris      else
166230557Sjimharris        OutputFilename = IFN+".ll";
167230557Sjimharris    }
168230557Sjimharris  }
169230557Sjimharris
170230557Sjimharris  std::string ErrorInfo;
171230557Sjimharris  OwningPtr<tool_output_file>
172230557Sjimharris  Out(new tool_output_file(OutputFilename.c_str(), ErrorInfo,
173230557Sjimharris                           raw_fd_ostream::F_Binary));
174230557Sjimharris  if (!ErrorInfo.empty()) {
175230557Sjimharris    errs() << ErrorInfo << '\n';
176230557Sjimharris    return 1;
177230557Sjimharris  }
178230557Sjimharris
179230557Sjimharris  OwningPtr<AssemblyAnnotationWriter> Annotator;
180230557Sjimharris  if (ShowAnnotations)
181230557Sjimharris    Annotator.reset(new CommentWriter());
182230557Sjimharris
183230557Sjimharris  // All that llvm-dis does is write the assembly to a file.
184230557Sjimharris  if (!DontPrint)
185230557Sjimharris    M->print(Out->os(), Annotator.get());
186230557Sjimharris
187230557Sjimharris  // Declare success.
188230557Sjimharris  Out->keep();
189230557Sjimharris
190230557Sjimharris  return 0;
191230557Sjimharris}
192230557Sjimharris