llvm-dis.cpp revision 224133
1275970Scy//===-- llvm-dis.cpp - The low-level LLVM disassembler --------------------===// 2275970Scy// 3275970Scy// The LLVM Compiler Infrastructure 4275970Scy// 5285169Scy// This file is distributed under the University of Illinois Open Source 6275970Scy// License. See LICENSE.TXT for details. 7275970Scy// 8275970Scy//===----------------------------------------------------------------------===// 9275970Scy// 10275970Scy// This utility may be invoked in the following manner: 11275970Scy// llvm-dis [options] - Read LLVM bitcode from stdin, write asm to stdout 12275970Scy// llvm-dis [options] x.bc - Read LLVM bitcode from the x.bc file, write asm 13275970Scy// to the x.ll file. 14275970Scy// Options: 15275970Scy// --help - Output information about command line switches 16275970Scy// 17275970Scy//===----------------------------------------------------------------------===// 18275970Scy 19275970Scy#include "llvm/LLVMContext.h" 20275970Scy#include "llvm/Module.h" 21275970Scy#include "llvm/Type.h" 22275970Scy#include "llvm/IntrinsicInst.h" 23275970Scy#include "llvm/Bitcode/ReaderWriter.h" 24275970Scy#include "llvm/Analysis/DebugInfo.h" 25275970Scy#include "llvm/Assembly/AssemblyAnnotationWriter.h" 26275970Scy#include "llvm/Support/CommandLine.h" 27275970Scy#include "llvm/Support/FormattedStream.h" 28275970Scy#include "llvm/Support/ManagedStatic.h" 29275970Scy#include "llvm/Support/MemoryBuffer.h" 30275970Scy#include "llvm/Support/PrettyStackTrace.h" 31275970Scy#include "llvm/Support/ToolOutputFile.h" 32275970Scy#include "llvm/Support/Signals.h" 33275970Scy#include "llvm/Support/system_error.h" 34285169Scyusing namespace llvm; 35275970Scy 36275970Scystatic cl::opt<std::string> 37275970ScyInputFilename(cl::Positional, cl::desc("<input bitcode>"), cl::init("-")); 38275970Scy 39275970Scystatic cl::opt<std::string> 40275970ScyOutputFilename("o", cl::desc("Override output filename"), 41275970Scy cl::value_desc("filename")); 42275970Scy 43275970Scystatic cl::opt<bool> 44275970ScyForce("f", cl::desc("Enable binary output on terminals")); 45275970Scy 46275970Scystatic cl::opt<bool> 47275970ScyDontPrint("disable-output", cl::desc("Don't output the .ll file"), cl::Hidden); 48275970Scy 49275970Scystatic cl::opt<bool> 50275970ScyShowAnnotations("show-annotations", 51275970Scy cl::desc("Add informational comments to the .ll file")); 52275970Scy 53275970Scynamespace { 54275970Scy 55275970Scystatic void printDebugLoc(const DebugLoc &DL, formatted_raw_ostream &OS) { 56275970Scy OS << DL.getLine() << ":" << DL.getCol(); 57275970Scy if (MDNode *N = DL.getInlinedAt(getGlobalContext())) { 58275970Scy DebugLoc IDL = DebugLoc::getFromDILocation(N); 59275970Scy if (!IDL.isUnknown()) { 60275970Scy OS << "@"; 61275970Scy printDebugLoc(IDL,OS); 62275970Scy } 63275970Scy } 64275970Scy} 65275970Scyclass CommentWriter : public AssemblyAnnotationWriter { 66275970Scypublic: 67275970Scy void emitFunctionAnnot(const Function *F, 68275970Scy formatted_raw_ostream &OS) { 69275970Scy OS << "; [#uses=" << F->getNumUses() << ']'; // Output # uses 70275970Scy OS << '\n'; 71275970Scy } 72275970Scy void printInfoComment(const Value &V, formatted_raw_ostream &OS) { 73275970Scy bool Padded = false; 74275970Scy if (!V.getType()->isVoidTy()) { 75275970Scy OS.PadToColumn(50); 76275970Scy Padded = true; 77275970Scy OS << "; [#uses=" << V.getNumUses() << " type=" << *V.getType() << "]"; // Output # uses and type 78275970Scy } 79275970Scy if (const Instruction *I = dyn_cast<Instruction>(&V)) { 80275970Scy const DebugLoc &DL = I->getDebugLoc(); 81275970Scy if (!DL.isUnknown()) { 82275970Scy if (!Padded) { 83275970Scy OS.PadToColumn(50); 84275970Scy Padded = true; 85275970Scy OS << ";"; 86275970Scy } 87275970Scy OS << " [debug line = "; 88275970Scy printDebugLoc(DL,OS); 89275970Scy OS << "]"; 90275970Scy } 91275970Scy if (const DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(I)) { 92275970Scy DIVariable Var(DDI->getVariable()); 93275970Scy if (!Padded) { 94275970Scy OS.PadToColumn(50); 95275970Scy Padded = true; 96275970Scy OS << ";"; 97275970Scy } 98275970Scy OS << " [debug variable = " << Var.getName() << "]"; 99275970Scy } 100275970Scy else if (const DbgValueInst *DVI = dyn_cast<DbgValueInst>(I)) { 101275970Scy DIVariable Var(DVI->getVariable()); 102275970Scy if (!Padded) { 103275970Scy OS.PadToColumn(50); 104275970Scy Padded = true; 105275970Scy OS << ";"; 106275970Scy } 107275970Scy OS << " [debug variable = " << Var.getName() << "]"; 108275970Scy } 109275970Scy } 110275970Scy } 111275970Scy}; 112275970Scy 113275970Scy} // end anon namespace 114275970Scy 115275970Scyint main(int argc, char **argv) { 116275970Scy // Print a stack trace if we signal out. 117275970Scy sys::PrintStackTraceOnErrorSignal(); 118275970Scy PrettyStackTraceProgram X(argc, argv); 119275970Scy 120275970Scy LLVMContext &Context = getGlobalContext(); 121275970Scy llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. 122275970Scy 123275970Scy 124275970Scy cl::ParseCommandLineOptions(argc, argv, "llvm .bc -> .ll disassembler\n"); 125275970Scy 126275970Scy std::string ErrorMessage; 127275970Scy std::auto_ptr<Module> M; 128275970Scy 129275970Scy { 130275970Scy OwningPtr<MemoryBuffer> BufferPtr; 131275970Scy if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFilename, BufferPtr)) 132275970Scy ErrorMessage = ec.message(); 133275970Scy else 134275970Scy M.reset(ParseBitcodeFile(BufferPtr.get(), Context, &ErrorMessage)); 135275970Scy } 136275970Scy 137275970Scy if (M.get() == 0) { 138275970Scy errs() << argv[0] << ": "; 139275970Scy if (ErrorMessage.size()) 140275970Scy errs() << ErrorMessage << "\n"; 141275970Scy else 142275970Scy errs() << "bitcode didn't read correctly.\n"; 143275970Scy return 1; 144275970Scy } 145275970Scy 146275970Scy // Just use stdout. We won't actually print anything on it. 147275970Scy if (DontPrint) 148275970Scy OutputFilename = "-"; 149275970Scy 150275970Scy if (OutputFilename.empty()) { // Unspecified output, infer it. 151275970Scy if (InputFilename == "-") { 152275970Scy OutputFilename = "-"; 153275970Scy } else { 154275970Scy const std::string &IFN = InputFilename; 155275970Scy int Len = IFN.length(); 156275970Scy // 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