Index: tools/llvm-extract/llvm-extract.cpp =================================================================== --- tools/llvm-extract/llvm-extract.cpp +++ tools/llvm-extract/llvm-extract.cpp @@ -17,10 +17,11 @@ #include "llvm/Bitcode/BitcodeWriterPass.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/IRPrintingPasses.h" +#include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" #include "llvm/IRReader/IRReader.h" -#include "llvm/IR/LegacyPassManager.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Error.h" #include "llvm/Support/FileSystem.h" @@ -50,6 +51,10 @@ static cl::opt DeleteFn("delete", cl::desc("Delete specified Globals from Module")); +static cl::opt + Recursive("recursive", + cl::desc("Recursively extract all called functions")); + // ExtractFuncs - The functions to extract from the module. static cl::list ExtractFuncs("func", cl::desc("Specify function to extract"), @@ -226,6 +231,32 @@ // Use *argv instead of argv[0] to work around a wrong GCC warning. ExitOnError ExitOnErr(std::string(*argv) + ": error reading input: "); + if (Recursive) { + std::vector Workqueue; + for (auto *GV : GVs) { + if (Function *F = dyn_cast(GV)) { + Workqueue.push_back(F); + } + } + while (!Workqueue.empty()) { + Function *F = &*Workqueue.back(); + Workqueue.pop_back(); + ExitOnErr(F->materialize()); + for (auto &BB : *F) { + for (auto &I : BB) { + if (CallInst *CI = dyn_cast(&I)) { + if (Function *CF = CI->getCalledFunction()) { + if (!CF->isDeclaration() && !GVs.count(CF)) { + GVs.insert(CF); + Workqueue.push_back(CF); + } + } + } + } + } + } + } + auto Materialize = [&](GlobalValue &GV) { ExitOnErr(GV.materialize()); }; // Materialize requisite global values.