forked from OSchip/llvm-project
[lld][WebAssembly] Add libcall symbols to the link when LTO is being used.
This code is copied almost verbatim from the equivalent change to the ELF linker: - https://reviews.llvm.org/D50017 - https://reviews.llvm.org/D50475 The upshot is that libraries containing libcall (such as compiler-rt and libc) can be compiled with LTO. Fixes PR41384 Differential Revision: https://reviews.llvm.org/D71738
This commit is contained in:
parent
b590e0fd81
commit
9cd985815a
|
@ -0,0 +1,6 @@
|
||||||
|
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
|
||||||
|
target triple = "wasm32-unknown-unknown"
|
||||||
|
|
||||||
|
define void @memcpy() {
|
||||||
|
ret void
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
; 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: wasm-ld -o %t %t.o %t.a
|
||||||
|
; RUN: obj2yaml %t | FileCheck %s
|
||||||
|
|
||||||
|
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
|
||||||
|
target triple = "wasm32-unknown-unknown"
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
; CHECK: - Type: CUSTOM
|
||||||
|
; CHECK-NEXT: Name: name
|
||||||
|
; CHECK-NEXT: FunctionNames:
|
||||||
|
; CHECK-NEXT: - Index: 0
|
||||||
|
; CHECK-NEXT: Name: _start
|
||||||
|
; CHECK-NEXT: - Index: 1
|
||||||
|
; CHECK-NEXT: Name: memcpy
|
|
@ -437,6 +437,18 @@ static Symbol *handleUndefined(StringRef name) {
|
||||||
return sym;
|
return sym;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void handleLibcall(StringRef name) {
|
||||||
|
Symbol *sym = symtab->find(name);
|
||||||
|
if (!sym)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (auto *lazySym = dyn_cast<LazySymbol>(sym)) {
|
||||||
|
MemoryBufferRef mb = lazySym->getMemberBuffer();
|
||||||
|
if (isBitcode(mb))
|
||||||
|
lazySym->fetch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static UndefinedGlobal *
|
static UndefinedGlobal *
|
||||||
createUndefinedGlobal(StringRef name, llvm::wasm::WasmGlobalType *type) {
|
createUndefinedGlobal(StringRef name, llvm::wasm::WasmGlobalType *type) {
|
||||||
auto *sym = cast<UndefinedGlobal>(symtab->addUndefinedGlobal(
|
auto *sym = cast<UndefinedGlobal>(symtab->addUndefinedGlobal(
|
||||||
|
@ -742,6 +754,21 @@ void LinkerDriver::link(ArrayRef<const char *> argsArr) {
|
||||||
// Create wrapped symbols for -wrap option.
|
// Create wrapped symbols for -wrap option.
|
||||||
std::vector<WrappedSymbol> wrapped = addWrappedSymbols(args);
|
std::vector<WrappedSymbol> wrapped = addWrappedSymbols(args);
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// We only need to add libcall symbols to the link before LTO if the symbol's
|
||||||
|
// definition is in bitcode. Any other required libcall symbols will be added
|
||||||
|
// to the link after LTO when we add the LTO object file to the link.
|
||||||
|
if (!symtab->bitcodeFiles.empty())
|
||||||
|
for (auto *s : lto::LTO::getRuntimeLibcallSymbols())
|
||||||
|
handleLibcall(s);
|
||||||
|
if (errorCount())
|
||||||
|
return;
|
||||||
|
|
||||||
// Do link-time optimization if given files are LLVM bitcode files.
|
// Do link-time optimization if given files are LLVM bitcode files.
|
||||||
// This compiles bitcode files into real object files.
|
// This compiles bitcode files into real object files.
|
||||||
symtab->addCombinedLTOObject();
|
symtab->addCombinedLTOObject();
|
||||||
|
|
|
@ -162,6 +162,10 @@ public:
|
||||||
std::unique_ptr<llvm::lto::InputFile> obj;
|
std::unique_ptr<llvm::lto::InputFile> obj;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline bool isBitcode(MemoryBufferRef mb) {
|
||||||
|
return identify_magic(mb.getBuffer()) == llvm::file_magic::bitcode;
|
||||||
|
}
|
||||||
|
|
||||||
// Will report a fatal() error if the input buffer is not a valid bitcode
|
// Will report a fatal() error if the input buffer is not a valid bitcode
|
||||||
// or wasm object file.
|
// or wasm object file.
|
||||||
InputFile *createObjectFile(MemoryBufferRef mb, StringRef archiveName = "");
|
InputFile *createObjectFile(MemoryBufferRef mb, StringRef archiveName = "");
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#define DEBUG_TYPE "lld"
|
#define DEBUG_TYPE "lld"
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
using namespace llvm::object;
|
||||||
using namespace llvm::wasm;
|
using namespace llvm::wasm;
|
||||||
|
|
||||||
namespace lld {
|
namespace lld {
|
||||||
|
@ -334,6 +335,16 @@ const OutputSectionSymbol *SectionSymbol::getOutputSectionSymbol() const {
|
||||||
|
|
||||||
void LazySymbol::fetch() { cast<ArchiveFile>(file)->addMember(&archiveSymbol); }
|
void LazySymbol::fetch() { cast<ArchiveFile>(file)->addMember(&archiveSymbol); }
|
||||||
|
|
||||||
|
MemoryBufferRef LazySymbol::getMemberBuffer() {
|
||||||
|
Archive::Child c =
|
||||||
|
CHECK(archiveSymbol.getMember(),
|
||||||
|
"could not get the member for symbol " + toString(*this));
|
||||||
|
|
||||||
|
return CHECK(c.getMemoryBufferRef(),
|
||||||
|
"could not get the buffer for the member defining symbol " +
|
||||||
|
toString(*this));
|
||||||
|
}
|
||||||
|
|
||||||
void printTraceSymbolUndefined(StringRef name, const InputFile* file) {
|
void printTraceSymbolUndefined(StringRef name, const InputFile* file) {
|
||||||
message(toString(file) + ": reference to " + name);
|
message(toString(file) + ": reference to " + name);
|
||||||
}
|
}
|
||||||
|
|
|
@ -410,6 +410,7 @@ public:
|
||||||
|
|
||||||
static bool classof(const Symbol *s) { return s->kind() == LazyKind; }
|
static bool classof(const Symbol *s) { return s->kind() == LazyKind; }
|
||||||
void fetch();
|
void fetch();
|
||||||
|
MemoryBufferRef getMemberBuffer();
|
||||||
|
|
||||||
// Lazy symbols can have a signature because they can replace an
|
// Lazy symbols can have a signature because they can replace an
|
||||||
// UndefinedFunction which which case we need to be able to preserve the
|
// UndefinedFunction which which case we need to be able to preserve the
|
||||||
|
|
Loading…
Reference in New Issue