diff --git a/llvm/lib/Linker/LinkModules.cpp b/llvm/lib/Linker/LinkModules.cpp --- a/llvm/lib/Linker/LinkModules.cpp +++ b/llvm/lib/Linker/LinkModules.cpp @@ -526,6 +526,10 @@ if (linkIfNeeded(GA)) return true; + for (GlobalIFunc &GI : SrcM->ifuncs()) + if (linkIfNeeded(GI)) + return true; + for (unsigned I = 0; I < ValuesToLink.size(); ++I) { GlobalValue *GV = ValuesToLink[I]; const Comdat *SC = GV->getComdat(); diff --git a/llvm/test/Linker/ifunc.ll b/llvm/test/Linker/ifunc.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Linker/ifunc.ll @@ -0,0 +1,25 @@ +; RUN: split-file %s %t +; RUN: llvm-link %t/a.ll %t/b.ll -S -o - | FileCheck %s + +;; Check that ifuncs are linked in properly. + +; CHECK-DAG: @foo = ifunc void (), bitcast (void ()* ()* @foo_resolve to void ()*) +; CHECK-DAG: define internal void ()* @foo_resolve() { + +; CHECK-DAG: @bar = ifunc void (), bitcast (void ()* ()* @bar_resolve to void ()*) +; CHECK-DAG: define internal void ()* @bar_resolve() { + +;--- a.ll +declare void @bar() + +;--- b.ll +@foo = ifunc void (), bitcast (void ()* ()* @foo_resolve to void ()*) +@bar = ifunc void (), bitcast (void ()* ()* @bar_resolve to void ()*) + +define internal void ()* @foo_resolve() { + ret void ()* null +} + +define internal void ()* @bar_resolve() { + ret void ()* null +}