1 //===- llvm-extract.cpp - LLVM function extraction utility ----------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This utility changes the input module to only contain a single function,
11 // which is primarily used for debugging transformations.
13 //===----------------------------------------------------------------------===//
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/ToolOutputFile.h"
27 #include "llvm/Support/SystemUtils.h"
28 #include "llvm/System/Signals.h"
29 #include "llvm/ADT/SmallPtrSet.h"
33 // InputFilename - The filename to read from.
34 static cl::opt
<std::string
>
35 InputFilename(cl::Positional
, cl::desc("<input bitcode file>"),
36 cl::init("-"), cl::value_desc("filename"));
38 static cl::opt
<std::string
>
39 OutputFilename("o", cl::desc("Specify output filename"),
40 cl::value_desc("filename"), cl::init("-"));
43 Force("f", cl::desc("Enable binary output on terminals"));
46 DeleteFn("delete", cl::desc("Delete specified Globals from Module"));
48 // ExtractFuncs - The functions to extract from the module...
49 static cl::list
<std::string
>
50 ExtractFuncs("func", cl::desc("Specify function to extract"),
51 cl::ZeroOrMore
, cl::value_desc("function"));
53 // ExtractGlobals - The globals to extract from the module...
54 static cl::list
<std::string
>
55 ExtractGlobals("glob", cl::desc("Specify global to extract"),
56 cl::ZeroOrMore
, cl::value_desc("global"));
60 cl::desc("Write output as LLVM assembly"), cl::Hidden
);
62 int main(int argc
, char **argv
) {
63 // Print a stack trace if we signal out.
64 sys::PrintStackTraceOnErrorSignal();
65 PrettyStackTraceProgram
X(argc
, argv
);
67 LLVMContext
&Context
= getGlobalContext();
68 llvm_shutdown_obj Y
; // Call llvm_shutdown() on exit.
69 cl::ParseCommandLineOptions(argc
, argv
, "llvm extractor\n");
71 // Use lazy loading, since we only care about selected global values.
73 std::auto_ptr
<Module
> M
;
74 M
.reset(getLazyIRFileModule(InputFilename
, Err
, Context
));
77 Err
.Print(argv
[0], errs());
81 std::vector
<GlobalValue
*> GVs
;
83 // Figure out which globals we should extract.
84 for (size_t i
= 0, e
= ExtractGlobals
.size(); i
!= e
; ++i
) {
85 GlobalValue
*GV
= M
.get()->getNamedGlobal(ExtractGlobals
[i
]);
87 errs() << argv
[0] << ": program doesn't contain global named '"
88 << ExtractGlobals
[i
] << "'!\n";
94 // Figure out which functions we should extract.
95 for (size_t i
= 0, e
= ExtractFuncs
.size(); i
!= e
; ++i
) {
96 GlobalValue
*GV
= M
.get()->getFunction(ExtractFuncs
[i
]);
98 errs() << argv
[0] << ": program doesn't contain function named '"
99 << ExtractFuncs
[i
] << "'!\n";
105 // Materialize requisite global values.
107 for (size_t i
= 0, e
= GVs
.size(); i
!= e
; ++i
) {
108 GlobalValue
*GV
= GVs
[i
];
109 if (GV
->isMaterializable()) {
111 if (GV
->Materialize(&ErrInfo
)) {
112 errs() << argv
[0] << ": error reading input: " << ErrInfo
<< "\n";
118 // Deleting. Materialize every GV that's *not* in GVs.
119 SmallPtrSet
<GlobalValue
*, 8> GVSet(GVs
.begin(), GVs
.end());
120 for (Module::global_iterator I
= M
->global_begin(), E
= M
->global_end();
122 GlobalVariable
*G
= I
;
123 if (!GVSet
.count(G
) && G
->isMaterializable()) {
125 if (G
->Materialize(&ErrInfo
)) {
126 errs() << argv
[0] << ": error reading input: " << ErrInfo
<< "\n";
131 for (Module::iterator I
= M
->begin(), E
= M
->end(); I
!= E
; ++I
) {
133 if (!GVSet
.count(F
) && F
->isMaterializable()) {
135 if (F
->Materialize(&ErrInfo
)) {
136 errs() << argv
[0] << ": error reading input: " << ErrInfo
<< "\n";
143 // In addition to deleting all other functions, we also want to spiff it
144 // up a little bit. Do this now.
146 Passes
.add(new TargetData(M
.get())); // Use correct TargetData
148 Passes
.add(createGVExtractionPass(GVs
, DeleteFn
));
150 Passes
.add(createGlobalDCEPass()); // Delete unreachable globals
151 Passes
.add(createStripDeadDebugInfoPass()); // Remove dead debug info
152 Passes
.add(createDeadTypeEliminationPass()); // Remove dead types...
153 Passes
.add(createStripDeadPrototypesPass()); // Remove dead func decls
155 std::string ErrorInfo
;
156 tool_output_file
Out(OutputFilename
.c_str(), ErrorInfo
,
157 raw_fd_ostream::F_Binary
);
158 if (!ErrorInfo
.empty()) {
159 errs() << ErrorInfo
<< '\n';
164 Passes
.add(createPrintModulePass(&Out
.os()));
165 else if (Force
|| !CheckBitcodeOutputToConsole(Out
.os(), true))
166 Passes
.add(createBitcodeWriterPass(Out
.os()));
168 Passes
.run(*M
.get());