aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Wennborg <hans@hanshq.net>2019-08-26 08:36:43 +0000
committerHans Wennborg <hans@hanshq.net>2019-08-26 08:36:43 +0000
commit0bb63f8687ebab457e4e7b89b951e70a95937902 (patch)
tree65a992cde8e1573ed3457fded1deee88acf69c63
parentcc79e7079b75c9cd7e956256798f104f3b51e3d1 (diff)
Merging r369694:
------------------------------------------------------------------------ r369694 | akhuang | 2019-08-22 21:40:07 +0200 (Thu, 22 Aug 2019) | 1 line [COFF] Add libcall symbols to the link when LTO is being used ------------------------------------------------------------------------ git-svn-id: https://llvm.org/svn/llvm-project/lld/branches/release_90@369883 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--COFF/Driver.cpp15
-rw-r--r--COFF/SymbolTable.cpp12
-rw-r--r--COFF/SymbolTable.h1
-rw-r--r--COFF/Symbols.cpp9
-rw-r--r--COFF/Symbols.h2
-rw-r--r--test/COFF/Inputs/libcall-archive.ll6
-rw-r--r--test/COFF/Inputs/libcall-archive.s2
-rw-r--r--test/COFF/libcall-archive.ll22
8 files changed, 69 insertions, 0 deletions
diff --git a/COFF/Driver.cpp b/COFF/Driver.cpp
index d68760e4b..eb3aff1a8 100644
--- a/COFF/Driver.cpp
+++ b/COFF/Driver.cpp
@@ -1055,6 +1055,12 @@ void LinkerDriver::maybeExportMinGWSymbols(const opt::InputArgList &args) {
});
}
+static const char *libcallRoutineNames[] = {
+#define HANDLE_LIBCALL(code, name) name,
+#include "llvm/IR/RuntimeLibcalls.def"
+#undef HANDLE_LIBCALL
+};
+
void LinkerDriver::link(ArrayRef<const char *> argsArr) {
// Needed for LTO.
InitializeAllTargetInfos();
@@ -1757,6 +1763,15 @@ void LinkerDriver::link(ArrayRef<const char *> argsArr) {
u->weakAlias = symtab->addUndefined(to);
}
+ // If any inputs are bitcode files, the LTO code generator may create
+ // references to library functions that are not 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.
+ if (!BitcodeFile::instances.empty())
+ for (const char *s : libcallRoutineNames)
+ symtab->addLibcall(s);
+
// Windows specific -- if __load_config_used can be resolved, resolve it.
if (symtab->findUnderscore("_load_config_used"))
addUndefined(mangle("_load_config_used"));
diff --git a/COFF/SymbolTable.cpp b/COFF/SymbolTable.cpp
index 07ebf6ea5..3f3e66074 100644
--- a/COFF/SymbolTable.cpp
+++ b/COFF/SymbolTable.cpp
@@ -505,6 +505,18 @@ Symbol *SymbolTable::addImportThunk(StringRef name, DefinedImportData *id,
return nullptr;
}
+void SymbolTable::addLibcall(StringRef name) {
+ Symbol *sym = findUnderscore(name);
+ if (!sym)
+ return;
+
+ if (Lazy *l = dyn_cast<Lazy>(sym)) {
+ MemoryBufferRef mb = l->getMemberBuffer();
+ if (identify_magic(mb.getBuffer()) == llvm::file_magic::bitcode)
+ addUndefined(sym->getName());
+ }
+}
+
std::vector<Chunk *> SymbolTable::getChunks() {
std::vector<Chunk *> res;
for (ObjFile *file : ObjFile::instances) {
diff --git a/COFF/SymbolTable.h b/COFF/SymbolTable.h
index 50e7e9ba1..f0a7aaf35 100644
--- a/COFF/SymbolTable.h
+++ b/COFF/SymbolTable.h
@@ -97,6 +97,7 @@ public:
Symbol *addImportData(StringRef n, ImportFile *f);
Symbol *addImportThunk(StringRef name, DefinedImportData *s,
uint16_t machine);
+ void addLibcall(StringRef name);
void reportDuplicate(Symbol *existing, InputFile *newFile);
diff --git a/COFF/Symbols.cpp b/COFF/Symbols.cpp
index acb3b3220..1af11820a 100644
--- a/COFF/Symbols.cpp
+++ b/COFF/Symbols.cpp
@@ -118,5 +118,14 @@ Defined *Undefined::getWeakAlias() {
return d;
return nullptr;
}
+
+MemoryBufferRef Lazy::getMemberBuffer() {
+ Archive::Child c =
+ CHECK(sym.getMember(),
+ "could not get the member for symbol " + toCOFFString(sym));
+ return CHECK(c.getMemoryBufferRef(),
+ "could not get the buffer for the member defining symbol " +
+ toCOFFString(sym));
+}
} // namespace coff
} // namespace lld
diff --git a/COFF/Symbols.h b/COFF/Symbols.h
index 10d2b8149..78c357aa2 100644
--- a/COFF/Symbols.h
+++ b/COFF/Symbols.h
@@ -265,6 +265,8 @@ public:
static bool classof(const Symbol *s) { return s->kind() == LazyKind; }
+ MemoryBufferRef getMemberBuffer();
+
ArchiveFile *file;
private:
diff --git a/test/COFF/Inputs/libcall-archive.ll b/test/COFF/Inputs/libcall-archive.ll
new file mode 100644
index 000000000..3f8a24df4
--- /dev/null
+++ b/test/COFF/Inputs/libcall-archive.ll
@@ -0,0 +1,6 @@
+target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
+target triple = "i686-unknown-windows"
+
+define void @memcpy() {
+ ret void
+}
diff --git a/test/COFF/Inputs/libcall-archive.s b/test/COFF/Inputs/libcall-archive.s
new file mode 100644
index 000000000..487cf2009
--- /dev/null
+++ b/test/COFF/Inputs/libcall-archive.s
@@ -0,0 +1,2 @@
+.globl ___sync_val_compare_and_swap_8
+___sync_val_compare_and_swap_8:
diff --git a/test/COFF/libcall-archive.ll b/test/COFF/libcall-archive.ll
new file mode 100644
index 000000000..631503d0d
--- /dev/null
+++ b/test/COFF/libcall-archive.ll
@@ -0,0 +1,22 @@
+; REQUIRES: x86
+; RUN: rm -f %t.a
+; RUN: llvm-as -o %t.obj %s
+; RUN: llvm-as -o %t2.obj %S/Inputs/libcall-archive.ll
+; RUN: llvm-mc -filetype=obj -triple=i686-unknown-windows -o %t3.obj %S/Inputs/libcall-archive.s
+; RUN: llvm-ar rcs %t.a %t2.obj %t3.obj
+; RUN: lld-link -out:%t.exe -subsystem:console -entry:start -safeseh:no -lldmap:- %t.obj %t.a | FileCheck %s
+
+; CHECK-NOT: ___sync_val_compare_and_swap_8
+; CHECK: _start
+; CHECK: _memcpy
+
+target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
+target triple = "i686-unknown-windows"
+
+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)