llvm-extract.cpp revision 065344dfd5a7b3502098810b981eb0077e5d81f3
1//===- llvm-extract.cpp - LLVM function extraction utility ----------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file was developed by the LLVM research group and is distributed under
6// the University of Illinois Open Source 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/Module.h"
16#include "llvm/PassManager.h"
17#include "llvm/Bitcode/ReaderWriter.h"
18#include "llvm/Transforms/IPO.h"
19#include "llvm/Target/TargetData.h"
20#include "llvm/Support/CommandLine.h"
21#include "llvm/Support/ManagedStatic.h"
22#include "llvm/Support/MemoryBuffer.h"
23#include "llvm/System/Signals.h"
24#include <iostream>
25#include <memory>
26#include <fstream>
27using namespace llvm;
28
29// InputFilename - The filename to read from.
30static cl::opt<std::string>
31InputFilename(cl::Positional, cl::desc("<input bytecode file>"),
32              cl::init("-"), cl::value_desc("filename"));
33
34static cl::opt<std::string>
35OutputFilename("o", cl::desc("Specify output filename"),
36               cl::value_desc("filename"), cl::init("-"));
37
38static cl::opt<bool>
39Force("f", cl::desc("Overwrite output files"));
40
41static cl::opt<bool>
42DeleteFn("delete", cl::desc("Delete specified function from Module"));
43
44static cl::opt<bool>
45Relink("relink",
46       cl::desc("Turn external linkage for callees of function to delete"));
47
48// ExtractFunc - The function to extract from the module... defaults to main.
49static cl::opt<std::string>
50ExtractFunc("func", cl::desc("Specify function to extract"), cl::init("main"),
51            cl::value_desc("function"));
52
53int main(int argc, char **argv) {
54  llvm_shutdown_obj X;  // Call llvm_shutdown() on exit.
55  cl::ParseCommandLineOptions(argc, argv, " llvm extractor\n");
56  sys::PrintStackTraceOnErrorSignal();
57
58  std::auto_ptr<Module> M;
59
60  MemoryBuffer *Buffer = MemoryBuffer::getFileOrSTDIN(InputFilename);
61  if (Buffer == 0) {
62    cerr << "Error reading file '" + InputFilename + "'";
63    return 1;
64  } else {
65    M.reset(ParseBitcodeFile(Buffer));
66  }
67  delete Buffer;
68
69  if (M.get() == 0) {
70    cerr << argv[0] << ": bytecode didn't read correctly.\n";
71    return 1;
72  }
73
74  // Figure out which function we should extract
75  Function *F = M.get()->getFunction(ExtractFunc);
76  if (F == 0) {
77    cerr << argv[0] << ": program doesn't contain function named '"
78         << ExtractFunc << "'!\n";
79    return 1;
80  }
81
82  // In addition to deleting all other functions, we also want to spiff it
83  // up a little bit.  Do this now.
84  PassManager Passes;
85  Passes.add(new TargetData(M.get())); // Use correct TargetData
86  // Either isolate the function or delete it from the Module
87  Passes.add(createFunctionExtractionPass(F, DeleteFn, Relink));
88  if (!DeleteFn)
89    Passes.add(createGlobalDCEPass());           // Delete unreachable globals
90  Passes.add(createDeadTypeEliminationPass());   // Remove dead types...
91  Passes.add(createStripDeadPrototypesPass());   // Remove dead func decls
92
93  std::ostream *Out = 0;
94
95  if (OutputFilename != "-") {  // Not stdout?
96    if (!Force && std::ifstream(OutputFilename.c_str())) {
97      // If force is not specified, make sure not to overwrite a file!
98      cerr << argv[0] << ": error opening '" << OutputFilename
99           << "': file exists!\n"
100           << "Use -f command line argument to force output\n";
101      return 1;
102    }
103    std::ios::openmode io_mode = std::ios::out | std::ios::trunc |
104                                 std::ios::binary;
105    Out = new std::ofstream(OutputFilename.c_str(), io_mode);
106  } else {                      // Specified stdout
107    // FIXME: cout is not binary!
108    Out = &std::cout;
109  }
110
111  Passes.add(CreateBitcodeWriterPass(*Out));
112  Passes.run(*M.get());
113
114  if (Out != &std::cout)
115    delete Out;
116  return 0;
117}
118