summaryrefslogtreecommitdiff
path: root/gnu/llvm/tools/llvm-extract
diff options
context:
space:
mode:
authorPatrick Wildt <patrick@cvs.openbsd.org>2017-10-04 20:28:12 +0000
committerPatrick Wildt <patrick@cvs.openbsd.org>2017-10-04 20:28:12 +0000
commitce4942c67154008535160eec8b913fb008038b6b (patch)
treea80e1a407d28d61e22be5dd84b73c4cc51ade54a /gnu/llvm/tools/llvm-extract
parent92440caccb2098ea0dd638dc607065155340d940 (diff)
Import LLVM 5.0.0 release including clang, lld and lldb.
Diffstat (limited to 'gnu/llvm/tools/llvm-extract')
-rw-r--r--gnu/llvm/tools/llvm-extract/llvm-extract.cpp35
1 files changed, 34 insertions, 1 deletions
diff --git a/gnu/llvm/tools/llvm-extract/llvm-extract.cpp b/gnu/llvm/tools/llvm-extract/llvm-extract.cpp
index aa1eda2f094..d868db7f78a 100644
--- a/gnu/llvm/tools/llvm-extract/llvm-extract.cpp
+++ b/gnu/llvm/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 @@ Force("f", cl::desc("Enable binary output on terminals"));
static cl::opt<bool>
DeleteFn("delete", cl::desc("Delete specified Globals from Module"));
+static cl::opt<bool>
+ Recursive("recursive",
+ cl::desc("Recursively extract all called functions"));
+
// ExtractFuncs - The functions to extract from the module.
static cl::list<std::string>
ExtractFuncs("func", cl::desc("Specify function to extract"),
@@ -226,6 +231,34 @@ int main(int argc, char **argv) {
// 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<llvm::Function *> Workqueue;
+ for (GlobalValue *GV : GVs) {
+ if (auto *F = dyn_cast<Function>(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<CallInst>(&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.