Index: llvm/trunk/test/tools/llvm-extract/recursive.ll =================================================================== --- llvm/trunk/test/tools/llvm-extract/recursive.ll +++ llvm/trunk/test/tools/llvm-extract/recursive.ll @@ -0,0 +1,32 @@ +; RUN: llvm-extract -func=a --recursive %s -S | FileCheck --check-prefix=CHECK-AB %s +; RUN: llvm-extract -func=a --recursive --delete %s -S | FileCheck --check-prefix=CHECK-CD %s +; RUN: llvm-extract -func=d --recursive %s -S | FileCheck --check-prefix=CHECK-CD %s + +; CHECK-AB: define void @a +; CHECK-AB: define void @b +; CHECK-AB-NOT: define void @c +; CHECK-AB-NOT: define void @d + +; CHECK-CD-NOT: define void @a +; CHECK-CD-NOT: define void @b +; CHECK-CD: define void @c +; CHECK-CD: define void @d + +define void @a() { + call void @b() + ret void +} + +define void @b() { + ret void +} + +define void @c() { + call void @d() + ret void +} + +define void @d() { + call void @c() + ret void +} Index: llvm/trunk/tools/llvm-extract/llvm-extract.cpp =================================================================== --- llvm/trunk/tools/llvm-extract/llvm-extract.cpp +++ llvm/trunk/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,34 @@ // 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 (GlobalValue *GV : GVs) { + if (auto *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) { + auto *CI = dyn_cast(&I); + if (!CI) + continue; + Function *CF = CI->getCalledFunction(); + if (!CF) + continue; + if (CF->isDeclaration() || GVs.count(CF)) + continue; + GVs.insert(CF); + Workqueue.push_back(CF); + } + } + } + } + auto Materialize = [&](GlobalValue &GV) { ExitOnErr(GV.materialize()); }; // Materialize requisite global values.