summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/ELF/Driver.cpp22
-rw-r--r--lld/test/ELF/lto/Inputs/libcall-archive.ll6
-rw-r--r--lld/test/ELF/lto/libcall-archive.ll20
3 files changed, 45 insertions, 3 deletions
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 7794abce85e..50555fb1cd2 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -1313,6 +1313,12 @@ static void findKeepUniqueSections(opt::InputArgList &Args) {
}
}
+static const char *LibcallRoutineNames[] = {
+#define HANDLE_LIBCALL(code, name) name,
+#include "llvm/IR/RuntimeLibcalls.def"
+#undef HANDLE_LIBCALL
+};
+
// Do actual linking. Note that when this function is called,
// all linker scripts have already been parsed.
template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
@@ -1379,11 +1385,21 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
for (StringRef S : Config->Undefined)
handleUndefined<ELFT>(S);
- // If an entry symbol is in a static archive, pull out that file now
- // to complete the symbol table. After this, no new names except a
- // few linker-synthesized ones will be added to the symbol table.
+ // If an entry symbol is in a static archive, pull out that file now.
handleUndefined<ELFT>(Config->Entry);
+ // If any of our inputs are bitcode files, the LTO code generator may create
+ // references to certain library functions that might not be explicit in the
+ // bitcode file's symbol table. If any of those library functions are defined
+ // in a bitcode file in an archive member, we need to arrange to use LTO to
+ // compile those archive members by adding them to the link beforehand.
+ //
+ // With this the symbol table should be complete. After this, no new names
+ // except a few linker-synthesized ones will be added to the symbol table.
+ if (!BitcodeFiles.empty())
+ for (const char *S : LibcallRoutineNames)
+ handleUndefined<ELFT>(S);
+
// Return if there were name resolution errors.
if (errorCount())
return;
diff --git a/lld/test/ELF/lto/Inputs/libcall-archive.ll b/lld/test/ELF/lto/Inputs/libcall-archive.ll
new file mode 100644
index 00000000000..4e6421c3020
--- /dev/null
+++ b/lld/test/ELF/lto/Inputs/libcall-archive.ll
@@ -0,0 +1,6 @@
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @memcpy() {
+ ret void
+}
diff --git a/lld/test/ELF/lto/libcall-archive.ll b/lld/test/ELF/lto/libcall-archive.ll
new file mode 100644
index 00000000000..731e25938bd
--- /dev/null
+++ b/lld/test/ELF/lto/libcall-archive.ll
@@ -0,0 +1,20 @@
+; RUN: rm -f %t.a
+; RUN: llvm-as -o %t.o %s
+; RUN: llvm-as -o %t2.o %S/Inputs/libcall-archive.ll
+; RUN: llvm-ar rcs %t.a %t2.o
+; RUN: ld.lld -o %t %t.o %t.a
+; RUN: llvm-nm %t | FileCheck %s
+
+; CHECK: T _start
+; CHECK: T memcpy
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @_start(i8* %a, i8* %b) {
+entry:
+ call void @llvm.memcpy.p0i8.p0i8.i64(i8* %a, i8* %b, i64 1024, i1 false)
+ ret void
+}
+
+declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i1)
OpenPOWER on IntegriCloud