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