From a1c022c791b506f021a630f6263c14c981b8977b Mon Sep 17 00:00:00 2001 From: Amy Huang Date: Thu, 22 Aug 2019 19:40:07 +0000 Subject: [PATCH] [COFF] Add libcall symbols to the link when LTO is being used llvm-svn: 369694 --- lld/COFF/Driver.cpp | 15 +++++++++++++++ lld/COFF/SymbolTable.cpp | 12 ++++++++++++ lld/COFF/SymbolTable.h | 1 + lld/COFF/Symbols.cpp | 9 +++++++++ lld/COFF/Symbols.h | 2 ++ lld/test/COFF/Inputs/libcall-archive.ll | 6 ++++++ lld/test/COFF/Inputs/libcall-archive.s | 2 ++ lld/test/COFF/libcall-archive.ll | 22 ++++++++++++++++++++++ 8 files changed, 69 insertions(+) create mode 100644 lld/test/COFF/Inputs/libcall-archive.ll create mode 100644 lld/test/COFF/Inputs/libcall-archive.s create mode 100644 lld/test/COFF/libcall-archive.ll diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index 32b09a736a40..5c5a89b21a7e 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/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 argsArr) { // Needed for LTO. InitializeAllTargetInfos(); @@ -1758,6 +1764,15 @@ void LinkerDriver::link(ArrayRef 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/lld/COFF/SymbolTable.cpp b/lld/COFF/SymbolTable.cpp index 13220ed49891..865791ca8e13 100644 --- a/lld/COFF/SymbolTable.cpp +++ b/lld/COFF/SymbolTable.cpp @@ -584,6 +584,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(sym)) { + MemoryBufferRef mb = l->getMemberBuffer(); + if (identify_magic(mb.getBuffer()) == llvm::file_magic::bitcode) + addUndefined(sym->getName()); + } +} + std::vector SymbolTable::getChunks() { std::vector res; for (ObjFile *file : ObjFile::instances) { diff --git a/lld/COFF/SymbolTable.h b/lld/COFF/SymbolTable.h index 68febc82235c..52eb8901e615 100644 --- a/lld/COFF/SymbolTable.h +++ b/lld/COFF/SymbolTable.h @@ -100,6 +100,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/lld/COFF/Symbols.cpp b/lld/COFF/Symbols.cpp index acb3b32203e5..1af11820a7e6 100644 --- a/lld/COFF/Symbols.cpp +++ b/lld/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/lld/COFF/Symbols.h b/lld/COFF/Symbols.h index 10d2b8149cd8..78c357aa2a58 100644 --- a/lld/COFF/Symbols.h +++ b/lld/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/lld/test/COFF/Inputs/libcall-archive.ll b/lld/test/COFF/Inputs/libcall-archive.ll new file mode 100644 index 000000000000..3f8a24df4c37 --- /dev/null +++ b/lld/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/lld/test/COFF/Inputs/libcall-archive.s b/lld/test/COFF/Inputs/libcall-archive.s new file mode 100644 index 000000000000..487cf2009f85 --- /dev/null +++ b/lld/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/lld/test/COFF/libcall-archive.ll b/lld/test/COFF/libcall-archive.ll new file mode 100644 index 000000000000..631503d0dd9a --- /dev/null +++ b/lld/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)