llvm-extract.cpp revision 2df9504fec1ddf198321c7fe8c968154b4edbff3
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> 30using namespace llvm; 31 32// InputFilename - The filename to read from. 33static cl::opt<std::string> 34InputFilename(cl::Positional, cl::desc("<input bitcode file>"), 35 cl::init("-"), cl::value_desc("filename")); 36 37static cl::opt<std::string> 38OutputFilename("o", cl::desc("Specify output filename"), 39 cl::value_desc("filename"), cl::init("-")); 40 41static cl::opt<bool> 42Force("f", cl::desc("Enable binary output on terminals")); 43 44static cl::opt<bool> 45DeleteFn("delete", cl::desc("Delete specified Globals from Module")); 46 47static cl::opt<bool> 48Relink("relink", 49 cl::desc("Turn external linkage for callees of function to delete")); 50 51// ExtractFuncs - The functions to extract from the module... 52static cl::list<std::string> 53ExtractFuncs("func", cl::desc("Specify function to extract"), 54 cl::ZeroOrMore, cl::value_desc("function")); 55 56// ExtractGlobals - The globals to extract from the module... 57static cl::list<std::string> 58ExtractGlobals("glob", cl::desc("Specify global to extract"), 59 cl::ZeroOrMore, cl::value_desc("global")); 60 61static cl::opt<bool> 62OutputAssembly("S", 63 cl::desc("Write output as LLVM assembly"), cl::Hidden); 64 65int main(int argc, char **argv) { 66 // Print a stack trace if we signal out. 67 sys::PrintStackTraceOnErrorSignal(); 68 PrettyStackTraceProgram X(argc, argv); 69 70 LLVMContext &Context = getGlobalContext(); 71 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. 72 cl::ParseCommandLineOptions(argc, argv, "llvm extractor\n"); 73 74 SMDiagnostic Err; 75 std::auto_ptr<Module> M; 76 M.reset(ParseIRFile(InputFilename, Err, Context)); 77 78 if (M.get() == 0) { 79 Err.Print(argv[0], errs()); 80 return 1; 81 } 82 83 std::vector<GlobalValue *> GVs; 84 85 // Figure out which globals we should extract. 86 for (size_t i = 0, e = ExtractGlobals.size(); i != e; ++i) { 87 GlobalValue *GV = M.get()->getNamedGlobal(ExtractGlobals[i]); 88 if (!GV) { 89 errs() << argv[0] << ": program doesn't contain global named '" 90 << ExtractGlobals[i] << "'!\n"; 91 return 1; 92 } 93 GVs.push_back(GV); 94 } 95 96 // Figure out which functions we should extract. 97 for (size_t i = 0, e = ExtractFuncs.size(); i != e; ++i) { 98 GlobalValue *GV = M.get()->getFunction(ExtractFuncs[i]); 99 if (!GV) { 100 errs() << argv[0] << ": program doesn't contain function named '" 101 << ExtractFuncs[i] << "'!\n"; 102 return 1; 103 } 104 GVs.push_back(GV); 105 } 106 107 // In addition to deleting all other functions, we also want to spiff it 108 // up a little bit. Do this now. 109 PassManager Passes; 110 Passes.add(new TargetData(M.get())); // Use correct TargetData 111 112 Passes.add(createGVExtractionPass(GVs, DeleteFn, Relink)); 113 if (!DeleteFn) 114 Passes.add(createGlobalDCEPass()); // Delete unreachable globals 115 Passes.add(createStripDeadDebugInfoPass()); // Remove dead debug info 116 Passes.add(createDeadTypeEliminationPass()); // Remove dead types... 117 Passes.add(createStripDeadPrototypesPass()); // Remove dead func decls 118 119 std::string ErrorInfo; 120 tool_output_file Out(OutputFilename.c_str(), ErrorInfo, 121 raw_fd_ostream::F_Binary); 122 if (!ErrorInfo.empty()) { 123 errs() << ErrorInfo << '\n'; 124 return 1; 125 } 126 127 if (OutputAssembly) 128 Passes.add(createPrintModulePass(&Out)); 129 else if (Force || !CheckBitcodeOutputToConsole(Out, true)) 130 Passes.add(createBitcodeWriterPass(Out)); 131 132 Passes.run(*M.get()); 133 134 // Declare success. 135 Out.keep(); 136 137 return 0; 138} 139