Make tool_output_file's raw_ostream instance a member variable instead
[oota-llvm.git] / tools / llvm-extract / llvm-extract.cpp
1 //===- llvm-extract.cpp - LLVM function extraction utility ----------------===//
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 changes the input module to only contain a single function,
11 // which is primarily used for debugging transformations.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "llvm/LLVMContext.h"
16 #include "llvm/Module.h"
17 #include "llvm/PassManager.h"
18 #include "llvm/Assembly/PrintModulePass.h"
19 #include "llvm/Bitcode/ReaderWriter.h"
20 #include "llvm/Transforms/IPO.h"
21 #include "llvm/Target/TargetData.h"
22 #include "llvm/Support/CommandLine.h"
23 #include "llvm/Support/IRReader.h"
24 #include "llvm/Support/ManagedStatic.h"
25 #include "llvm/Support/PrettyStackTrace.h"
26 #include "llvm/Support/raw_ostream.h"
27 #include "llvm/Support/SystemUtils.h"
28 #include "llvm/System/Signals.h"
29 #include <memory>
30 using namespace llvm;
31
32 // InputFilename - The filename to read from.
33 static cl::opt<std::string>
34 InputFilename(cl::Positional, cl::desc("<input bitcode file>"),
35               cl::init("-"), cl::value_desc("filename"));
36
37 static cl::opt<std::string>
38 OutputFilename("o", cl::desc("Specify output filename"),
39                cl::value_desc("filename"), cl::init("-"));
40
41 static cl::opt<bool>
42 Force("f", cl::desc("Enable binary output on terminals"));
43
44 static cl::opt<bool>
45 DeleteFn("delete", cl::desc("Delete specified Globals from Module"));
46
47 // ExtractFuncs - The functions to extract from the module... 
48 static cl::list<std::string>
49 ExtractFuncs("func", cl::desc("Specify function to extract"),
50              cl::ZeroOrMore, cl::value_desc("function"));
51
52 // ExtractGlobals - The globals to extract from the module...
53 static cl::list<std::string>
54 ExtractGlobals("glob", cl::desc("Specify global to extract"),
55                cl::ZeroOrMore, cl::value_desc("global"));
56
57 static cl::opt<bool>
58 OutputAssembly("S",
59                cl::desc("Write output as LLVM assembly"), cl::Hidden);
60
61 int main(int argc, char **argv) {
62   // Print a stack trace if we signal out.
63   sys::PrintStackTraceOnErrorSignal();
64   PrettyStackTraceProgram X(argc, argv);
65
66   LLVMContext &Context = getGlobalContext();
67   llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.
68   cl::ParseCommandLineOptions(argc, argv, "llvm extractor\n");
69
70   // Use lazy loading, since we only care about selected global values.
71   SMDiagnostic Err;
72   std::auto_ptr<Module> M;
73   M.reset(getLazyIRFileModule(InputFilename, Err, Context));
74
75   if (M.get() == 0) {
76     Err.Print(argv[0], errs());
77     return 1;
78   }
79
80   std::vector<GlobalValue *> GVs;
81
82   // Figure out which globals we should extract.
83   for (size_t i = 0, e = ExtractGlobals.size(); i != e; ++i) {
84     GlobalValue *GV = M.get()->getNamedGlobal(ExtractGlobals[i]);
85     if (!GV) {
86       errs() << argv[0] << ": program doesn't contain global named '"
87              << ExtractGlobals[i] << "'!\n";
88       return 1;
89     }
90     GVs.push_back(GV);
91   }
92
93   // Figure out which functions we should extract.
94   for (size_t i = 0, e = ExtractFuncs.size(); i != e; ++i) {
95     GlobalValue *GV = M.get()->getFunction(ExtractFuncs[i]);
96     if (!GV) {
97       errs() << argv[0] << ": program doesn't contain function named '"
98              << ExtractFuncs[i] << "'!\n";
99       return 1;
100     }
101     GVs.push_back(GV);
102   }
103
104   // Materialize requisite global values.
105   for (size_t i = 0, e = GVs.size(); i != e; ++i) {
106     GlobalValue *GV = GVs[i];
107     if (GV->isMaterializable()) {
108       std::string ErrInfo;
109       if (GV->Materialize(&ErrInfo)) {
110         errs() << argv[0] << ": error reading input: " << ErrInfo << "\n";
111         return 1;
112       }
113     }
114   }
115
116   // In addition to deleting all other functions, we also want to spiff it
117   // up a little bit.  Do this now.
118   PassManager Passes;
119   Passes.add(new TargetData(M.get())); // Use correct TargetData
120
121   Passes.add(createGVExtractionPass(GVs, DeleteFn));
122   if (!DeleteFn)
123     Passes.add(createGlobalDCEPass());           // Delete unreachable globals
124   Passes.add(createStripDeadDebugInfoPass());    // Remove dead debug info
125   Passes.add(createDeadTypeEliminationPass());   // Remove dead types...
126   Passes.add(createStripDeadPrototypesPass());   // Remove dead func decls
127
128   std::string ErrorInfo;
129   tool_output_file Out(OutputFilename.c_str(), ErrorInfo,
130                        raw_fd_ostream::F_Binary);
131   if (!ErrorInfo.empty()) {
132     errs() << ErrorInfo << '\n';
133     return 1;
134   }
135
136   if (OutputAssembly)
137     Passes.add(createPrintModulePass(&Out.os()));
138   else if (Force || !CheckBitcodeOutputToConsole(Out.os(), true))
139     Passes.add(createBitcodeWriterPass(Out.os()));
140
141   Passes.run(*M.get());
142
143   // Declare success.
144   Out.keep();
145
146   return 0;
147 }