xref: /minix3/external/bsd/llvm/dist/llvm/tools/llvm-dis/llvm-dis.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1f4a2713aSLionel Sambuc //===-- llvm-dis.cpp - The low-level LLVM disassembler --------------------===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc //                     The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc // This utility may be invoked in the following manner:
11f4a2713aSLionel Sambuc //  llvm-dis [options]      - Read LLVM bitcode from stdin, write asm to stdout
12f4a2713aSLionel Sambuc //  llvm-dis [options] x.bc - Read LLVM bitcode from the x.bc file, write asm
13f4a2713aSLionel Sambuc //                            to the x.ll file.
14f4a2713aSLionel Sambuc //  Options:
15f4a2713aSLionel Sambuc //      --help   - Output information about command line switches
16f4a2713aSLionel Sambuc //
17f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
18f4a2713aSLionel Sambuc 
19f4a2713aSLionel Sambuc #include "llvm/IR/LLVMContext.h"
20f4a2713aSLionel Sambuc #include "llvm/Bitcode/ReaderWriter.h"
21*0a6a1f1dSLionel Sambuc #include "llvm/IR/AssemblyAnnotationWriter.h"
22*0a6a1f1dSLionel Sambuc #include "llvm/IR/DebugInfo.h"
23*0a6a1f1dSLionel Sambuc #include "llvm/IR/DiagnosticInfo.h"
24*0a6a1f1dSLionel Sambuc #include "llvm/IR/DiagnosticPrinter.h"
25f4a2713aSLionel Sambuc #include "llvm/IR/IntrinsicInst.h"
26f4a2713aSLionel Sambuc #include "llvm/IR/Module.h"
27f4a2713aSLionel Sambuc #include "llvm/IR/Type.h"
28f4a2713aSLionel Sambuc #include "llvm/Support/CommandLine.h"
29f4a2713aSLionel Sambuc #include "llvm/Support/DataStream.h"
30*0a6a1f1dSLionel Sambuc #include "llvm/Support/FileSystem.h"
31f4a2713aSLionel Sambuc #include "llvm/Support/FormattedStream.h"
32f4a2713aSLionel Sambuc #include "llvm/Support/ManagedStatic.h"
33f4a2713aSLionel Sambuc #include "llvm/Support/MemoryBuffer.h"
34f4a2713aSLionel Sambuc #include "llvm/Support/PrettyStackTrace.h"
35f4a2713aSLionel Sambuc #include "llvm/Support/Signals.h"
36f4a2713aSLionel Sambuc #include "llvm/Support/ToolOutputFile.h"
37*0a6a1f1dSLionel Sambuc #include <system_error>
38f4a2713aSLionel Sambuc using namespace llvm;
39f4a2713aSLionel Sambuc 
40f4a2713aSLionel Sambuc static cl::opt<std::string>
41f4a2713aSLionel Sambuc InputFilename(cl::Positional, cl::desc("<input bitcode>"), cl::init("-"));
42f4a2713aSLionel Sambuc 
43f4a2713aSLionel Sambuc static cl::opt<std::string>
44f4a2713aSLionel Sambuc OutputFilename("o", cl::desc("Override output filename"),
45f4a2713aSLionel Sambuc                cl::value_desc("filename"));
46f4a2713aSLionel Sambuc 
47f4a2713aSLionel Sambuc static cl::opt<bool>
48f4a2713aSLionel Sambuc Force("f", cl::desc("Enable binary output on terminals"));
49f4a2713aSLionel Sambuc 
50f4a2713aSLionel Sambuc static cl::opt<bool>
51f4a2713aSLionel Sambuc DontPrint("disable-output", cl::desc("Don't output the .ll file"), cl::Hidden);
52f4a2713aSLionel Sambuc 
53f4a2713aSLionel Sambuc static cl::opt<bool>
54f4a2713aSLionel Sambuc ShowAnnotations("show-annotations",
55f4a2713aSLionel Sambuc                 cl::desc("Add informational comments to the .ll file"));
56f4a2713aSLionel Sambuc 
57f4a2713aSLionel Sambuc namespace {
58f4a2713aSLionel Sambuc 
printDebugLoc(const DebugLoc & DL,formatted_raw_ostream & OS)59f4a2713aSLionel Sambuc static void printDebugLoc(const DebugLoc &DL, formatted_raw_ostream &OS) {
60f4a2713aSLionel Sambuc   OS << DL.getLine() << ":" << DL.getCol();
61f4a2713aSLionel Sambuc   if (MDNode *N = DL.getInlinedAt(getGlobalContext())) {
62f4a2713aSLionel Sambuc     DebugLoc IDL = DebugLoc::getFromDILocation(N);
63f4a2713aSLionel Sambuc     if (!IDL.isUnknown()) {
64f4a2713aSLionel Sambuc       OS << "@";
65f4a2713aSLionel Sambuc       printDebugLoc(IDL,OS);
66f4a2713aSLionel Sambuc     }
67f4a2713aSLionel Sambuc   }
68f4a2713aSLionel Sambuc }
69f4a2713aSLionel Sambuc class CommentWriter : public AssemblyAnnotationWriter {
70f4a2713aSLionel Sambuc public:
emitFunctionAnnot(const Function * F,formatted_raw_ostream & OS)71f4a2713aSLionel Sambuc   void emitFunctionAnnot(const Function *F,
72*0a6a1f1dSLionel Sambuc                          formatted_raw_ostream &OS) override {
73f4a2713aSLionel Sambuc     OS << "; [#uses=" << F->getNumUses() << ']';  // Output # uses
74f4a2713aSLionel Sambuc     OS << '\n';
75f4a2713aSLionel Sambuc   }
printInfoComment(const Value & V,formatted_raw_ostream & OS)76*0a6a1f1dSLionel Sambuc   void printInfoComment(const Value &V, formatted_raw_ostream &OS) override {
77f4a2713aSLionel Sambuc     bool Padded = false;
78f4a2713aSLionel Sambuc     if (!V.getType()->isVoidTy()) {
79f4a2713aSLionel Sambuc       OS.PadToColumn(50);
80f4a2713aSLionel Sambuc       Padded = true;
81f4a2713aSLionel Sambuc       OS << "; [#uses=" << V.getNumUses() << " type=" << *V.getType() << "]";  // Output # uses and type
82f4a2713aSLionel Sambuc     }
83f4a2713aSLionel Sambuc     if (const Instruction *I = dyn_cast<Instruction>(&V)) {
84f4a2713aSLionel Sambuc       const DebugLoc &DL = I->getDebugLoc();
85f4a2713aSLionel Sambuc       if (!DL.isUnknown()) {
86f4a2713aSLionel Sambuc         if (!Padded) {
87f4a2713aSLionel Sambuc           OS.PadToColumn(50);
88f4a2713aSLionel Sambuc           Padded = true;
89f4a2713aSLionel Sambuc           OS << ";";
90f4a2713aSLionel Sambuc         }
91f4a2713aSLionel Sambuc         OS << " [debug line = ";
92f4a2713aSLionel Sambuc         printDebugLoc(DL,OS);
93f4a2713aSLionel Sambuc         OS << "]";
94f4a2713aSLionel Sambuc       }
95f4a2713aSLionel Sambuc       if (const DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(I)) {
96f4a2713aSLionel Sambuc         DIVariable Var(DDI->getVariable());
97f4a2713aSLionel Sambuc         if (!Padded) {
98f4a2713aSLionel Sambuc           OS.PadToColumn(50);
99f4a2713aSLionel Sambuc           OS << ";";
100f4a2713aSLionel Sambuc         }
101f4a2713aSLionel Sambuc         OS << " [debug variable = " << Var.getName() << "]";
102f4a2713aSLionel Sambuc       }
103f4a2713aSLionel Sambuc       else if (const DbgValueInst *DVI = dyn_cast<DbgValueInst>(I)) {
104f4a2713aSLionel Sambuc         DIVariable Var(DVI->getVariable());
105f4a2713aSLionel Sambuc         if (!Padded) {
106f4a2713aSLionel Sambuc           OS.PadToColumn(50);
107f4a2713aSLionel Sambuc           OS << ";";
108f4a2713aSLionel Sambuc         }
109f4a2713aSLionel Sambuc         OS << " [debug variable = " << Var.getName() << "]";
110f4a2713aSLionel Sambuc       }
111f4a2713aSLionel Sambuc     }
112f4a2713aSLionel Sambuc   }
113f4a2713aSLionel Sambuc };
114f4a2713aSLionel Sambuc 
115f4a2713aSLionel Sambuc } // end anon namespace
116f4a2713aSLionel Sambuc 
diagnosticHandler(const DiagnosticInfo & DI,void * Context)117*0a6a1f1dSLionel Sambuc static void diagnosticHandler(const DiagnosticInfo &DI, void *Context) {
118*0a6a1f1dSLionel Sambuc   assert(DI.getSeverity() == DS_Error && "Only expecting errors");
119*0a6a1f1dSLionel Sambuc 
120*0a6a1f1dSLionel Sambuc   raw_ostream &OS = errs();
121*0a6a1f1dSLionel Sambuc   OS << (char *)Context << ": ";
122*0a6a1f1dSLionel Sambuc   DiagnosticPrinterRawOStream DP(OS);
123*0a6a1f1dSLionel Sambuc   DI.print(DP);
124*0a6a1f1dSLionel Sambuc   OS << '\n';
125*0a6a1f1dSLionel Sambuc   exit(1);
126*0a6a1f1dSLionel Sambuc }
127*0a6a1f1dSLionel Sambuc 
main(int argc,char ** argv)128f4a2713aSLionel Sambuc int main(int argc, char **argv) {
129f4a2713aSLionel Sambuc   // Print a stack trace if we signal out.
130f4a2713aSLionel Sambuc   sys::PrintStackTraceOnErrorSignal();
131f4a2713aSLionel Sambuc   PrettyStackTraceProgram X(argc, argv);
132f4a2713aSLionel Sambuc 
133f4a2713aSLionel Sambuc   LLVMContext &Context = getGlobalContext();
134f4a2713aSLionel Sambuc   llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.
135f4a2713aSLionel Sambuc 
136*0a6a1f1dSLionel Sambuc   Context.setDiagnosticHandler(diagnosticHandler, argv[0]);
137f4a2713aSLionel Sambuc 
138f4a2713aSLionel Sambuc   cl::ParseCommandLineOptions(argc, argv, "llvm .bc -> .ll disassembler\n");
139f4a2713aSLionel Sambuc 
140f4a2713aSLionel Sambuc   std::string ErrorMessage;
141*0a6a1f1dSLionel Sambuc   std::unique_ptr<Module> M;
142f4a2713aSLionel Sambuc 
143f4a2713aSLionel Sambuc   // Use the bitcode streaming interface
144*0a6a1f1dSLionel Sambuc   DataStreamer *Streamer = getDataFileStreamer(InputFilename, &ErrorMessage);
145*0a6a1f1dSLionel Sambuc   if (Streamer) {
146f4a2713aSLionel Sambuc     std::string DisplayFilename;
147f4a2713aSLionel Sambuc     if (InputFilename == "-")
148f4a2713aSLionel Sambuc       DisplayFilename = "<stdin>";
149f4a2713aSLionel Sambuc     else
150f4a2713aSLionel Sambuc       DisplayFilename = InputFilename;
151*0a6a1f1dSLionel Sambuc     ErrorOr<std::unique_ptr<Module>> MOrErr =
152*0a6a1f1dSLionel Sambuc         getStreamedBitcodeModule(DisplayFilename, Streamer, Context);
153*0a6a1f1dSLionel Sambuc     M = std::move(*MOrErr);
154*0a6a1f1dSLionel Sambuc     M->materializeAllPermanently();
155f4a2713aSLionel Sambuc   }
156f4a2713aSLionel Sambuc 
157f4a2713aSLionel Sambuc   // Just use stdout.  We won't actually print anything on it.
158f4a2713aSLionel Sambuc   if (DontPrint)
159f4a2713aSLionel Sambuc     OutputFilename = "-";
160f4a2713aSLionel Sambuc 
161f4a2713aSLionel Sambuc   if (OutputFilename.empty()) { // Unspecified output, infer it.
162f4a2713aSLionel Sambuc     if (InputFilename == "-") {
163f4a2713aSLionel Sambuc       OutputFilename = "-";
164f4a2713aSLionel Sambuc     } else {
165f4a2713aSLionel Sambuc       const std::string &IFN = InputFilename;
166f4a2713aSLionel Sambuc       int Len = IFN.length();
167f4a2713aSLionel Sambuc       // If the source ends in .bc, strip it off.
168f4a2713aSLionel Sambuc       if (IFN[Len-3] == '.' && IFN[Len-2] == 'b' && IFN[Len-1] == 'c')
169f4a2713aSLionel Sambuc         OutputFilename = std::string(IFN.begin(), IFN.end()-3)+".ll";
170f4a2713aSLionel Sambuc       else
171f4a2713aSLionel Sambuc         OutputFilename = IFN+".ll";
172f4a2713aSLionel Sambuc     }
173f4a2713aSLionel Sambuc   }
174f4a2713aSLionel Sambuc 
175*0a6a1f1dSLionel Sambuc   std::error_code EC;
176*0a6a1f1dSLionel Sambuc   std::unique_ptr<tool_output_file> Out(
177*0a6a1f1dSLionel Sambuc       new tool_output_file(OutputFilename, EC, sys::fs::F_None));
178*0a6a1f1dSLionel Sambuc   if (EC) {
179*0a6a1f1dSLionel Sambuc     errs() << EC.message() << '\n';
180f4a2713aSLionel Sambuc     return 1;
181f4a2713aSLionel Sambuc   }
182f4a2713aSLionel Sambuc 
183*0a6a1f1dSLionel Sambuc   std::unique_ptr<AssemblyAnnotationWriter> Annotator;
184f4a2713aSLionel Sambuc   if (ShowAnnotations)
185f4a2713aSLionel Sambuc     Annotator.reset(new CommentWriter());
186f4a2713aSLionel Sambuc 
187f4a2713aSLionel Sambuc   // All that llvm-dis does is write the assembly to a file.
188f4a2713aSLionel Sambuc   if (!DontPrint)
189f4a2713aSLionel Sambuc     M->print(Out->os(), Annotator.get());
190f4a2713aSLionel Sambuc 
191f4a2713aSLionel Sambuc   // Declare success.
192f4a2713aSLionel Sambuc   Out->keep();
193f4a2713aSLionel Sambuc 
194f4a2713aSLionel Sambuc   return 0;
195f4a2713aSLionel Sambuc }
196