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