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