summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Transforms/IPO/FunctionImport.cpp38
-rw-r--r--llvm/test/Transforms/FunctionImport/funcimport.ll10
2 files changed, 46 insertions, 2 deletions
diff --git a/llvm/lib/Transforms/IPO/FunctionImport.cpp b/llvm/lib/Transforms/IPO/FunctionImport.cpp
index c874e4f5da7..bd6eb8391dc 100644
--- a/llvm/lib/Transforms/IPO/FunctionImport.cpp
+++ b/llvm/lib/Transforms/IPO/FunctionImport.cpp
@@ -131,10 +131,24 @@ bool FunctionImporter::importFunctions(Module &M) {
// The function that we will import!
GlobalValue *SGV = Module.getNamedValue(CalledFunctionName);
+ StringRef ImportFunctionName = CalledFunctionName;
+ if (!SGV) {
+ // Might be local in source Module, promoted/renamed in dest Module M.
+ std::pair<StringRef, StringRef> Split =
+ CalledFunctionName.split(".llvm.");
+ SGV = Module.getNamedValue(Split.first);
+#ifndef NDEBUG
+ // Assert that Split.second is module id
+ uint64_t ModuleId;
+ assert(!Split.second.getAsInteger(10, ModuleId));
+ assert(ModuleId == Index.getModuleId(FileName));
+#endif
+ }
Function *F = dyn_cast<Function>(SGV);
if (!F && isa<GlobalAlias>(SGV)) {
auto *SGA = dyn_cast<GlobalAlias>(SGV);
F = dyn_cast<Function>(SGA->getBaseObject());
+ ImportFunctionName = F->getName();
}
if (!F) {
errs() << "Can't load function '" << CalledFunctionName << "' in Module '"
@@ -156,8 +170,28 @@ bool FunctionImporter::importFunctions(Module &M) {
if (L.linkInModule(&Module, Linker::Flags::None, &Index, F))
report_fatal_error("Function Import: link error");
- // TODO: Process the newly imported function and add callees to the
- // worklist.
+ // Process the newly imported function and add callees to the worklist.
+ GlobalValue *NewGV = M.getNamedValue(ImportFunctionName);
+ assert(NewGV);
+ Function *NewF = dyn_cast<Function>(NewGV);
+ assert(NewF);
+
+ for (auto &BB : *NewF) {
+ for (auto &I : BB) {
+ if (isa<CallInst>(I)) {
+ DEBUG(dbgs() << "Found a call: '" << I << "'\n");
+ auto CalledFunction = cast<CallInst>(I).getCalledFunction();
+ // Insert any new external calls that have not already been
+ // added to set/worklist.
+ if (CalledFunction && CalledFunction->hasName() &&
+ CalledFunction->isDeclaration() &&
+ !CalledFunctions.count(CalledFunction->getName())) {
+ CalledFunctions.insert(CalledFunction->getName());
+ Worklist.push_back(CalledFunction->getName());
+ }
+ }
+ }
+ }
Changed = true;
}
diff --git a/llvm/test/Transforms/FunctionImport/funcimport.ll b/llvm/test/Transforms/FunctionImport/funcimport.ll
index 43b2fb7919d..553d05bfcf3 100644
--- a/llvm/test/Transforms/FunctionImport/funcimport.ll
+++ b/llvm/test/Transforms/FunctionImport/funcimport.ll
@@ -31,9 +31,19 @@ declare void @analias(...) #1
; CHECK-DAG: define available_externally i32 @referencestatics(i32 %i)
declare i32 @referencestatics(...) #1
+; The import of referencestatics will expose call to staticfunc that
+; should in turn be imported as a promoted/renamed and hidden function.
+; Ensure that the call is to the properly-renamed function.
+; CHECK-DAG: %call = call i32 @staticfunc.llvm.2()
+; CHECK-DAG: define available_externally hidden i32 @staticfunc.llvm.2()
+
; CHECK-DAG: define available_externally i32 @referenceglobals(i32 %i)
declare i32 @referenceglobals(...) #1
+; The import of referenceglobals will expose call to globalfunc1 that
+; should in turn be imported.
+; CHECK-DAG: define available_externally void @globalfunc1()
+
; CHECK-DAG: define available_externally i32 @referencecommon(i32 %i)
declare i32 @referencecommon(...) #1
OpenPOWER on IntegriCloud