1193323Sed//===-- llvm-dis.cpp - The low-level LLVM disassembler --------------------===//
2193323Sed//
3193323Sed//                     The LLVM Compiler Infrastructure
4193323Sed//
5193323Sed// This file is distributed under the University of Illinois Open Source
6193323Sed// License. See LICENSE.TXT for details.
7193323Sed//
8193323Sed//===----------------------------------------------------------------------===//
9193323Sed//
10193323Sed// This utility may be invoked in the following manner:
11193323Sed//  llvm-dis [options]      - Read LLVM bitcode from stdin, write asm to stdout
12193323Sed//  llvm-dis [options] x.bc - Read LLVM bitcode from the x.bc file, write asm
13193323Sed//                            to the x.ll file.
14193323Sed//  Options:
15193323Sed//      --help   - Output information about command line switches
16193323Sed//
17193323Sed//===----------------------------------------------------------------------===//
18193323Sed
19249423Sdim#include "llvm/IR/LLVMContext.h"
20249423Sdim#include "llvm/Assembly/AssemblyAnnotationWriter.h"
21249423Sdim#include "llvm/Bitcode/ReaderWriter.h"
22239462Sdim#include "llvm/DebugInfo.h"
23249423Sdim#include "llvm/IR/IntrinsicInst.h"
24249423Sdim#include "llvm/IR/Module.h"
25249423Sdim#include "llvm/IR/Type.h"
26193323Sed#include "llvm/Support/CommandLine.h"
27234353Sdim#include "llvm/Support/DataStream.h"
28212793Sdim#include "llvm/Support/FormattedStream.h"
29193323Sed#include "llvm/Support/ManagedStatic.h"
30193323Sed#include "llvm/Support/MemoryBuffer.h"
31193323Sed#include "llvm/Support/PrettyStackTrace.h"
32249423Sdim#include "llvm/Support/Signals.h"
33218885Sdim#include "llvm/Support/ToolOutputFile.h"
34218885Sdim#include "llvm/Support/system_error.h"
35193323Sedusing namespace llvm;
36193323Sed
37193323Sedstatic cl::opt<std::string>
38193323SedInputFilename(cl::Positional, cl::desc("<input bitcode>"), cl::init("-"));
39193323Sed
40193323Sedstatic cl::opt<std::string>
41193323SedOutputFilename("o", cl::desc("Override output filename"),
42193323Sed               cl::value_desc("filename"));
43193323Sed
44193323Sedstatic cl::opt<bool>
45198090SrdivackyForce("f", cl::desc("Enable binary output on terminals"));
46193323Sed
47193323Sedstatic cl::opt<bool>
48193323SedDontPrint("disable-output", cl::desc("Don't output the .ll file"), cl::Hidden);
49193323Sed
50212793Sdimstatic cl::opt<bool>
51212793SdimShowAnnotations("show-annotations",
52212793Sdim                cl::desc("Add informational comments to the .ll file"));
53212793Sdim
54212793Sdimnamespace {
55218885Sdim
56221337Sdimstatic void printDebugLoc(const DebugLoc &DL, formatted_raw_ostream &OS) {
57221337Sdim  OS << DL.getLine() << ":" << DL.getCol();
58221337Sdim  if (MDNode *N = DL.getInlinedAt(getGlobalContext())) {
59221337Sdim    DebugLoc IDL = DebugLoc::getFromDILocation(N);
60221337Sdim    if (!IDL.isUnknown()) {
61221337Sdim      OS << "@";
62221337Sdim      printDebugLoc(IDL,OS);
63221337Sdim    }
64221337Sdim  }
65221337Sdim}
66212793Sdimclass CommentWriter : public AssemblyAnnotationWriter {
67212793Sdimpublic:
68212793Sdim  void emitFunctionAnnot(const Function *F,
69212793Sdim                         formatted_raw_ostream &OS) {
70212793Sdim    OS << "; [#uses=" << F->getNumUses() << ']';  // Output # uses
71212793Sdim    OS << '\n';
72212793Sdim  }
73212793Sdim  void printInfoComment(const Value &V, formatted_raw_ostream &OS) {
74221337Sdim    bool Padded = false;
75221337Sdim    if (!V.getType()->isVoidTy()) {
76221337Sdim      OS.PadToColumn(50);
77221337Sdim      Padded = true;
78224133Sdim      OS << "; [#uses=" << V.getNumUses() << " type=" << *V.getType() << "]";  // Output # uses and type
79221337Sdim    }
80221337Sdim    if (const Instruction *I = dyn_cast<Instruction>(&V)) {
81221337Sdim      const DebugLoc &DL = I->getDebugLoc();
82221337Sdim      if (!DL.isUnknown()) {
83221337Sdim        if (!Padded) {
84221337Sdim          OS.PadToColumn(50);
85221337Sdim          Padded = true;
86221337Sdim          OS << ";";
87221337Sdim        }
88221337Sdim        OS << " [debug line = ";
89221337Sdim        printDebugLoc(DL,OS);
90221337Sdim        OS << "]";
91221337Sdim      }
92221337Sdim      if (const DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(I)) {
93221337Sdim        DIVariable Var(DDI->getVariable());
94221337Sdim        if (!Padded) {
95221337Sdim          OS.PadToColumn(50);
96221337Sdim          OS << ";";
97221337Sdim        }
98221337Sdim        OS << " [debug variable = " << Var.getName() << "]";
99221337Sdim      }
100221337Sdim      else if (const DbgValueInst *DVI = dyn_cast<DbgValueInst>(I)) {
101221337Sdim        DIVariable Var(DVI->getVariable());
102221337Sdim        if (!Padded) {
103221337Sdim          OS.PadToColumn(50);
104221337Sdim          OS << ";";
105221337Sdim        }
106221337Sdim        OS << " [debug variable = " << Var.getName() << "]";
107221337Sdim      }
108221337Sdim    }
109212793Sdim  }
110212793Sdim};
111218885Sdim
112212793Sdim} // end anon namespace
113212793Sdim
114193323Sedint main(int argc, char **argv) {
115193323Sed  // Print a stack trace if we signal out.
116193323Sed  sys::PrintStackTraceOnErrorSignal();
117193323Sed  PrettyStackTraceProgram X(argc, argv);
118218885Sdim
119198090Srdivacky  LLVMContext &Context = getGlobalContext();
120193323Sed  llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.
121218885Sdim
122218885Sdim
123198090Srdivacky  cl::ParseCommandLineOptions(argc, argv, "llvm .bc -> .ll disassembler\n");
124193323Sed
125198090Srdivacky  std::string ErrorMessage;
126251662Sdim  OwningPtr<Module> M;
127218885Sdim
128234353Sdim  // Use the bitcode streaming interface
129234353Sdim  DataStreamer *streamer = getDataFileStreamer(InputFilename, &ErrorMessage);
130234353Sdim  if (streamer) {
131234353Sdim    std::string DisplayFilename;
132234353Sdim    if (InputFilename == "-")
133234353Sdim      DisplayFilename = "<stdin>";
134218885Sdim    else
135234353Sdim      DisplayFilename = InputFilename;
136234353Sdim    M.reset(getStreamedBitcodeModule(DisplayFilename, streamer, Context,
137234353Sdim                                     &ErrorMessage));
138234353Sdim    if(M.get() != 0 && M->MaterializeAllPermanently(&ErrorMessage)) {
139234353Sdim      M.reset();
140234353Sdim    }
141198090Srdivacky  }
142193323Sed
143198090Srdivacky  if (M.get() == 0) {
144198090Srdivacky    errs() << argv[0] << ": ";
145198090Srdivacky    if (ErrorMessage.size())
146198090Srdivacky      errs() << ErrorMessage << "\n";
147198090Srdivacky    else
148198090Srdivacky      errs() << "bitcode didn't read correctly.\n";
149198090Srdivacky    return 1;
150198090Srdivacky  }
151218885Sdim
152198090Srdivacky  // Just use stdout.  We won't actually print anything on it.
153198090Srdivacky  if (DontPrint)
154198090Srdivacky    OutputFilename = "-";
155218885Sdim
156198090Srdivacky  if (OutputFilename.empty()) { // Unspecified output, infer it.
157198090Srdivacky    if (InputFilename == "-") {
158198090Srdivacky      OutputFilename = "-";
159198090Srdivacky    } else {
160198090Srdivacky      const std::string &IFN = InputFilename;
161198090Srdivacky      int Len = IFN.length();
162198090Srdivacky      // If the source ends in .bc, strip it off.
163198090Srdivacky      if (IFN[Len-3] == '.' && IFN[Len-2] == 'b' && IFN[Len-1] == 'c')
164198090Srdivacky        OutputFilename = std::string(IFN.begin(), IFN.end()-3)+".ll";
165193323Sed      else
166198090Srdivacky        OutputFilename = IFN+".ll";
167193323Sed    }
168198090Srdivacky  }
169193323Sed
170198090Srdivacky  std::string ErrorInfo;
171263508Sdim  OwningPtr<tool_output_file> Out(new tool_output_file(
172263508Sdim      OutputFilename.c_str(), ErrorInfo, sys::fs::F_Binary));
173198090Srdivacky  if (!ErrorInfo.empty()) {
174198090Srdivacky    errs() << ErrorInfo << '\n';
175198090Srdivacky    return 1;
176198090Srdivacky  }
177193323Sed
178212793Sdim  OwningPtr<AssemblyAnnotationWriter> Annotator;
179212793Sdim  if (ShowAnnotations)
180212793Sdim    Annotator.reset(new CommentWriter());
181218885Sdim
182198090Srdivacky  // All that llvm-dis does is write the assembly to a file.
183198090Srdivacky  if (!DontPrint)
184212793Sdim    M->print(Out->os(), Annotator.get());
185193323Sed
186212793Sdim  // Declare success.
187212793Sdim  Out->keep();
188212793Sdim
189198090Srdivacky  return 0;
190193323Sed}
191