[lld][WebAssembly] stub objects: Fix handling of LTO libcall dependencies

This actually simplifies the code by performs a pre-pass of the stub
objects prior to LTO.

This should be the final change needed before we can make the switch
on the emscripten side: https://github.com/emscripten-core/emscripten/pull/18905

Differential Revision: https://reviews.llvm.org/D148287
This commit is contained in:
Sam Clegg
2023-04-13 11:41:27 -07:00
parent fd5d0a88dd
commit d43f0889dd
2 changed files with 33 additions and 15 deletions

View File

@@ -1,6 +1,6 @@
# RUN: split-file %s %t
# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown -o %t_main.o %t/main.s
# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown -o %t_foo.o %t/foo.s
# RUN: llvm-as %S/Inputs/foo.ll -o %t_foo.o
# RUN: llvm-as %S/Inputs/libcall.ll -o %t_libcall.o
# RUN: wasm-ld %t_main.o %t_libcall.o %t_foo.o %p/Inputs/stub.so -o %t.wasm
# RUN: obj2yaml %t.wasm | FileCheck %s
@@ -25,12 +25,6 @@ _start:
call func_with_libcall
end_function
#--- foo.s
.globl foo
foo:
.functype foo () -> ()
end_function
# CHECK: Imports:
# CHECK-NEXT: - Module: env
# CHECK-NEXT: Field: memcpy
@@ -46,4 +40,4 @@ foo:
# CHECK-NEXT: Index: 1
# CHECK-NEXT: - Name: foo
# CHECK-NEXT: Kind: FUNCTION
# CHECK-NEXT: Index: 2
# CHECK-NEXT: Index: 3

View File

@@ -874,6 +874,28 @@ static void createOptionalSymbols() {
WasmSym::tlsBase = createOptionalGlobal("__tls_base", false);
}
static void processStubLibrariesPreLTO() {
log("-- processStubLibrariesPreLTO");
for (auto &stub_file : symtab->stubFiles) {
LLVM_DEBUG(llvm::dbgs()
<< "processing stub file: " << stub_file->getName() << "\n");
for (auto [name, deps]: stub_file->symbolDependencies) {
auto* sym = symtab->find(name);
// If the symbol is not present at all (yet), or if it is present but
// undefined, then mark the dependent symbols as used by a regular
// object so they will be preserved and exported by the LTO process.
if (!sym || sym->isUndefined()) {
for (const auto dep : deps) {
auto* needed = symtab->find(dep);
if (needed ) {
needed->isUsedInRegularObj = true;
}
}
}
}
}
}
static void processStubLibraries() {
log("-- processStubLibraries");
for (auto &stub_file : symtab->stubFiles) {
@@ -881,12 +903,14 @@ static void processStubLibraries() {
<< "processing stub file: " << stub_file->getName() << "\n");
for (auto [name, deps]: stub_file->symbolDependencies) {
auto* sym = symtab->find(name);
if (!sym || !sym->isUndefined() || sym->forceImport) {
LLVM_DEBUG(llvm::dbgs() << "stub not in needed: " << name << "\n");
if (!sym || !sym->isUndefined()) {
LLVM_DEBUG(llvm::dbgs() << "stub symbol not needed: " << name << "\n");
continue;
}
// The first stub library to define a given symbol sets this and
// definitions in later stub libraries are ignored.
if (sym->forceImport)
continue; // Already handled
sym->forceImport = true;
if (sym->traced)
message(toString(stub_file) + ": importing " + name);
@@ -1213,9 +1237,9 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
if (errorCount())
return;
// processStubLibraries must happen before LTO because it can trigger the
// export of arbirary symbols that might themselves be defined in LTO objects.
processStubLibraries();
// We process the stub libraries once beofore LTO to ensure that any possible
// required exports are preserved by the LTO process.
processStubLibrariesPreLTO();
// Do link-time optimization if given files are LLVM bitcode files.
// This compiles bitcode files into real object files.
@@ -1225,8 +1249,8 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
// The LTO process can generate new undefined symbols, specifically libcall
// functions. Because those symbols might be declared in a stub library we
// need the process the stub libraries once again after LTO to handle any
// newly undefined symbols.
// need the process the stub libraries once again after LTO to handle all
// undefined symbols, including ones that didn't exist prior to LTO.
processStubLibraries();
writeWhyExtract();