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