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> 28 using namespace llvm; 29 30 // InputFilename - The filename to read from. 31 static cl::opt<std::string> 32 InputFilename(cl::Positional, cl::desc("<input bitcode file>"), 33 cl::init("-"), cl::value_desc("filename")); 34 35 static cl::opt<std::string> 36 OutputFilename("o", cl::desc("Specify output filename"), 37 cl::value_desc("filename"), cl::init("-")); 38 39 static cl::opt<bool> 40 Force("f", cl::desc("Overwrite output files")); 41 42 static cl::opt<bool> 43 DeleteFn("delete", cl::desc("Delete specified Globals from Module")); 44 45 static cl::opt<bool> 46 Relink("relink", 47 cl::desc("Turn external linkage for callees of function to delete")); 48 49 // ExtractFunc - The function to extract from the module... 50 static cl::opt<std::string> 51 ExtractFunc("func", cl::desc("Specify function to extract"), cl::init(""), 52 cl::value_desc("function")); 53 54 // ExtractGlobal - The global to extract from the module... 55 static cl::opt<std::string> 56 ExtractGlobal("glob", cl::desc("Specify global to extract"), cl::init(""), 57 cl::value_desc("global")); 58 59 int 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 std::string ErrorInfo; 114 std::auto_ptr<raw_fd_ostream> 115 Out(new raw_fd_ostream(OutputFilename.c_str(), ErrorInfo, 116 raw_fd_ostream::F_Binary | 117 (Force ? raw_fd_ostream::F_Force : 0))); 118 if (!ErrorInfo.empty()) { 119 errs() << ErrorInfo << '\n'; 120 if (!Force) 121 errs() << "Use -f command line argument to force output\n"; 122 return 1; 123 } 124 125 Passes.add(createBitcodeWriterPass(*Out)); 126 Passes.run(*M.get()); 127 128 return 0; 129 } 130