uselistorder: Pull bit through BitcodeWriterPass
[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/ADT/SetVector.h"
16 #include "llvm/ADT/SmallPtrSet.h"
17 #include "llvm/Bitcode/BitcodeWriterPass.h"
18 #include "llvm/IR/DataLayout.h"
19 #include "llvm/IR/IRPrintingPasses.h"
20 #include "llvm/IR/LLVMContext.h"
21 #include "llvm/IR/Module.h"
22 #include "llvm/IR/UseListOrder.h"
23 #include "llvm/IRReader/IRReader.h"
24 #include "llvm/IR/LegacyPassManager.h"
25 #include "llvm/Support/CommandLine.h"
26 #include "llvm/Support/FileSystem.h"
27 #include "llvm/Support/ManagedStatic.h"
28 #include "llvm/Support/PrettyStackTrace.h"
29 #include "llvm/Support/Regex.h"
30 #include "llvm/Support/Signals.h"
31 #include "llvm/Support/SourceMgr.h"
32 #include "llvm/Support/SystemUtils.h"
33 #include "llvm/Support/ToolOutputFile.h"
34 #include "llvm/Transforms/IPO.h"
35 #include <memory>
36 using namespace llvm;
37
38 // InputFilename - The filename to read from.
39 static cl::opt<std::string>
40 InputFilename(cl::Positional, cl::desc("<input bitcode file>"),
41               cl::init("-"), cl::value_desc("filename"));
42
43 static cl::opt<std::string>
44 OutputFilename("o", cl::desc("Specify output filename"),
45                cl::value_desc("filename"), cl::init("-"));
46
47 static cl::opt<bool>
48 Force("f", cl::desc("Enable binary output on terminals"));
49
50 static cl::opt<bool>
51 DeleteFn("delete", cl::desc("Delete specified Globals from Module"));
52
53 // ExtractFuncs - The functions to extract from the module.
54 static cl::list<std::string>
55 ExtractFuncs("func", cl::desc("Specify function to extract"),
56              cl::ZeroOrMore, cl::value_desc("function"));
57
58 // ExtractRegExpFuncs - The functions, matched via regular expression, to
59 // extract from the module.
60 static cl::list<std::string>
61 ExtractRegExpFuncs("rfunc", cl::desc("Specify function(s) to extract using a "
62                                      "regular expression"),
63                    cl::ZeroOrMore, cl::value_desc("rfunction"));
64
65 // ExtractAlias - The alias to extract from the module.
66 static cl::list<std::string>
67 ExtractAliases("alias", cl::desc("Specify alias to extract"),
68                cl::ZeroOrMore, cl::value_desc("alias"));
69
70
71 // ExtractRegExpAliases - The aliases, matched via regular expression, to
72 // extract from the module.
73 static cl::list<std::string>
74 ExtractRegExpAliases("ralias", cl::desc("Specify alias(es) to extract using a "
75                                         "regular expression"),
76                      cl::ZeroOrMore, cl::value_desc("ralias"));
77
78 // ExtractGlobals - The globals to extract from the module.
79 static cl::list<std::string>
80 ExtractGlobals("glob", cl::desc("Specify global to extract"),
81                cl::ZeroOrMore, cl::value_desc("global"));
82
83 // ExtractRegExpGlobals - The globals, matched via regular expression, to
84 // extract from the module...
85 static cl::list<std::string>
86 ExtractRegExpGlobals("rglob", cl::desc("Specify global(s) to extract using a "
87                                        "regular expression"),
88                      cl::ZeroOrMore, cl::value_desc("rglobal"));
89
90 static cl::opt<bool>
91 OutputAssembly("S",
92                cl::desc("Write output as LLVM assembly"), cl::Hidden);
93
94 int main(int argc, char **argv) {
95   // Print a stack trace if we signal out.
96   sys::PrintStackTraceOnErrorSignal();
97   PrettyStackTraceProgram X(argc, argv);
98
99   LLVMContext &Context = getGlobalContext();
100   llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.
101
102   // Turn on -preserve-bc-uselistorder by default, but let the command-line
103   // override it.
104   setPreserveBitcodeUseListOrder(true);
105
106   cl::ParseCommandLineOptions(argc, argv, "llvm extractor\n");
107
108   // Use lazy loading, since we only care about selected global values.
109   SMDiagnostic Err;
110   std::unique_ptr<Module> M = getLazyIRFileModule(InputFilename, Err, Context);
111
112   if (!M.get()) {
113     Err.print(argv[0], errs());
114     return 1;
115   }
116
117   // Use SetVector to avoid duplicates.
118   SetVector<GlobalValue *> GVs;
119
120   // Figure out which aliases we should extract.
121   for (size_t i = 0, e = ExtractAliases.size(); i != e; ++i) {
122     GlobalAlias *GA = M->getNamedAlias(ExtractAliases[i]);
123     if (!GA) {
124       errs() << argv[0] << ": program doesn't contain alias named '"
125              << ExtractAliases[i] << "'!\n";
126       return 1;
127     }
128     GVs.insert(GA);
129   }
130
131   // Extract aliases via regular expression matching.
132   for (size_t i = 0, e = ExtractRegExpAliases.size(); i != e; ++i) {
133     std::string Error;
134     Regex RegEx(ExtractRegExpAliases[i]);
135     if (!RegEx.isValid(Error)) {
136       errs() << argv[0] << ": '" << ExtractRegExpAliases[i] << "' "
137         "invalid regex: " << Error;
138     }
139     bool match = false;
140     for (Module::alias_iterator GA = M->alias_begin(), E = M->alias_end();
141          GA != E; GA++) {
142       if (RegEx.match(GA->getName())) {
143         GVs.insert(&*GA);
144         match = true;
145       }
146     }
147     if (!match) {
148       errs() << argv[0] << ": program doesn't contain global named '"
149              << ExtractRegExpAliases[i] << "'!\n";
150       return 1;
151     }
152   }
153
154   // Figure out which globals we should extract.
155   for (size_t i = 0, e = ExtractGlobals.size(); i != e; ++i) {
156     GlobalValue *GV = M->getNamedGlobal(ExtractGlobals[i]);
157     if (!GV) {
158       errs() << argv[0] << ": program doesn't contain global named '"
159              << ExtractGlobals[i] << "'!\n";
160       return 1;
161     }
162     GVs.insert(GV);
163   }
164
165   // Extract globals via regular expression matching.
166   for (size_t i = 0, e = ExtractRegExpGlobals.size(); i != e; ++i) {
167     std::string Error;
168     Regex RegEx(ExtractRegExpGlobals[i]);
169     if (!RegEx.isValid(Error)) {
170       errs() << argv[0] << ": '" << ExtractRegExpGlobals[i] << "' "
171         "invalid regex: " << Error;
172     }
173     bool match = false;
174     for (auto &GV : M->globals()) {
175       if (RegEx.match(GV.getName())) {
176         GVs.insert(&GV);
177         match = true;
178       }
179     }
180     if (!match) {
181       errs() << argv[0] << ": program doesn't contain global named '"
182              << ExtractRegExpGlobals[i] << "'!\n";
183       return 1;
184     }
185   }
186
187   // Figure out which functions we should extract.
188   for (size_t i = 0, e = ExtractFuncs.size(); i != e; ++i) {
189     GlobalValue *GV = M->getFunction(ExtractFuncs[i]);
190     if (!GV) {
191       errs() << argv[0] << ": program doesn't contain function named '"
192              << ExtractFuncs[i] << "'!\n";
193       return 1;
194     }
195     GVs.insert(GV);
196   }
197   // Extract functions via regular expression matching.
198   for (size_t i = 0, e = ExtractRegExpFuncs.size(); i != e; ++i) {
199     std::string Error;
200     StringRef RegExStr = ExtractRegExpFuncs[i];
201     Regex RegEx(RegExStr);
202     if (!RegEx.isValid(Error)) {
203       errs() << argv[0] << ": '" << ExtractRegExpFuncs[i] << "' "
204         "invalid regex: " << Error;
205     }
206     bool match = false;
207     for (Module::iterator F = M->begin(), E = M->end(); F != E;
208          F++) {
209       if (RegEx.match(F->getName())) {
210         GVs.insert(&*F);
211         match = true;
212       }
213     }
214     if (!match) {
215       errs() << argv[0] << ": program doesn't contain global named '"
216              << ExtractRegExpFuncs[i] << "'!\n";
217       return 1;
218     }
219   }
220
221   // Materialize requisite global values.
222   if (!DeleteFn)
223     for (size_t i = 0, e = GVs.size(); i != e; ++i) {
224       GlobalValue *GV = GVs[i];
225       if (std::error_code EC = GV->materialize()) {
226         errs() << argv[0] << ": error reading input: " << EC.message() << "\n";
227         return 1;
228       }
229     }
230   else {
231     // Deleting. Materialize every GV that's *not* in GVs.
232     SmallPtrSet<GlobalValue *, 8> GVSet(GVs.begin(), GVs.end());
233     for (auto &G : M->globals()) {
234       if (!GVSet.count(&G)) {
235         if (std::error_code EC = G.materialize()) {
236           errs() << argv[0] << ": error reading input: " << EC.message()
237                  << "\n";
238           return 1;
239         }
240       }
241     }
242     for (auto &F : *M) {
243       if (!GVSet.count(&F)) {
244         if (std::error_code EC = F.materialize()) {
245           errs() << argv[0] << ": error reading input: " << EC.message()
246                  << "\n";
247           return 1;
248         }
249       }
250     }
251   }
252
253   // In addition to deleting all other functions, we also want to spiff it
254   // up a little bit.  Do this now.
255   legacy::PassManager Passes;
256
257   std::vector<GlobalValue*> Gvs(GVs.begin(), GVs.end());
258
259   Passes.add(createGVExtractionPass(Gvs, DeleteFn));
260   if (!DeleteFn)
261     Passes.add(createGlobalDCEPass());           // Delete unreachable globals
262   Passes.add(createStripDeadDebugInfoPass());    // Remove dead debug info
263   Passes.add(createStripDeadPrototypesPass());   // Remove dead func decls
264
265   std::error_code EC;
266   tool_output_file Out(OutputFilename, EC, sys::fs::F_None);
267   if (EC) {
268     errs() << EC.message() << '\n';
269     return 1;
270   }
271
272   if (OutputAssembly)
273     Passes.add(createPrintModulePass(Out.os()));
274   else if (Force || !CheckBitcodeOutputToConsole(Out.os(), true))
275     Passes.add(
276         createBitcodeWriterPass(Out.os(), shouldPreserveBitcodeUseListOrder()));
277
278   Passes.run(*M.get());
279
280   // Declare success.
281   Out.keep();
282
283   return 0;
284 }