llvm-extract.cpp revision 2c785880eadb75f821771352ccf4a442a1b05668
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/Bitcode/ReaderWriter.h" 19#include "llvm/Transforms/IPO.h" 20#include "llvm/Target/TargetData.h" 21#include "llvm/Support/CommandLine.h" 22#include "llvm/Support/ManagedStatic.h" 23#include "llvm/Support/MemoryBuffer.h" 24#include "llvm/Support/PrettyStackTrace.h" 25#include "llvm/Support/raw_ostream.h" 26#include "llvm/System/Signals.h" 27#include <memory> 28using namespace llvm; 29 30// InputFilename - The filename to read from. 31static cl::opt<std::string> 32InputFilename(cl::Positional, cl::desc("<input bitcode file>"), 33 cl::init("-"), cl::value_desc("filename")); 34 35static cl::opt<std::string> 36OutputFilename("o", cl::desc("Specify output filename"), 37 cl::value_desc("filename"), cl::init("-")); 38 39static cl::opt<bool> 40Force("f", cl::desc("Overwrite output files")); 41 42static cl::opt<bool> 43DeleteFn("delete", cl::desc("Delete specified Globals from Module")); 44 45static cl::opt<bool> 46Relink("relink", 47 cl::desc("Turn external linkage for callees of function to delete")); 48 49// ExtractFunc - The function to extract from the module... 50static cl::opt<std::string> 51ExtractFunc("func", cl::desc("Specify function to extract"), cl::init(""), 52 cl::value_desc("function")); 53 54// ExtractGlobal - The global to extract from the module... 55static cl::opt<std::string> 56ExtractGlobal("glob", cl::desc("Specify global to extract"), cl::init(""), 57 cl::value_desc("global")); 58 59int main(int argc, char **argv) { 60 // Print a stack trace if we signal out. 61 sys::PrintStackTraceOnErrorSignal(); 62 PrettyStackTraceProgram X(argc, argv); 63 64 LLVMContext &Context = getGlobalContext(); 65 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. 66 cl::ParseCommandLineOptions(argc, argv, "llvm extractor\n"); 67 68 std::auto_ptr<Module> M; 69 70 MemoryBuffer *Buffer = MemoryBuffer::getFileOrSTDIN(InputFilename); 71 if (Buffer == 0) { 72 errs() << argv[0] << ": Error reading file '" + InputFilename + "'\n"; 73 return 1; 74 } else { 75 M.reset(ParseBitcodeFile(Buffer, Context)); 76 } 77 delete Buffer; 78 79 if (M.get() == 0) { 80 errs() << argv[0] << ": bitcode didn't read correctly.\n"; 81 return 1; 82 } 83 84 // Figure out which function we should extract 85 GlobalVariable *G = !ExtractGlobal.empty() ? 86 M.get()->getNamedGlobal(ExtractGlobal) : 0; 87 88 // Figure out which function we should extract 89 if (ExtractFunc.empty() && ExtractGlobal.empty()) ExtractFunc = "main"; 90 Function *F = M.get()->getFunction(ExtractFunc); 91 92 if (F == 0 && G == 0) { 93 errs() << argv[0] << ": program doesn't contain function named '" 94 << ExtractFunc << "' or a global named '" << ExtractGlobal << "'!\n"; 95 return 1; 96 } 97 98 // In addition to deleting all other functions, we also want to spiff it 99 // up a little bit. Do this now. 100 PassManager Passes; 101 Passes.add(new TargetData(M.get())); // Use correct TargetData 102 // Either isolate the function or delete it from the Module 103 std::vector<GlobalValue*> GVs; 104 if (F) GVs.push_back(F); 105 if (G) GVs.push_back(G); 106 107 Passes.add(createGVExtractionPass(GVs, DeleteFn, Relink)); 108 if (!DeleteFn) 109 Passes.add(createGlobalDCEPass()); // Delete unreachable globals 110 Passes.add(createDeadTypeEliminationPass()); // Remove dead types... 111 Passes.add(createStripDeadPrototypesPass()); // Remove dead func decls 112 113 raw_ostream *Out = 0; 114 115 if (OutputFilename != "-") { // Not stdout? 116 std::string ErrorInfo; 117 Out = new raw_fd_ostream(OutputFilename.c_str(), /*Binary=*/true, 118 Force, ErrorInfo); 119 if (!ErrorInfo.empty()) { 120 errs() << ErrorInfo << '\n'; 121 if (!Force) 122 errs() << "Use -f command line argument to force output\n"; 123 delete Out; 124 return 1; 125 } 126 } else { // Specified stdout 127 // FIXME: outs() is not binary! 128 Out = &outs(); 129 } 130 131 Passes.add(createBitcodeWriterPass(*Out)); 132 Passes.run(*M.get()); 133 134 if (Out != &outs()) 135 delete Out; 136 return 0; 137} 138