diff --git a/lld/test/wasm/Inputs/libstub.so b/lld/test/wasm/Inputs/libstub.so index f7e38b4272f24..70f6648c60eee 100644 --- a/lld/test/wasm/Inputs/libstub.so +++ b/lld/test/wasm/Inputs/libstub.so @@ -1,6 +1,6 @@ #STUB # This is a comment -foo: foodep1,foodep2 +foo_import: foodep1,foodep2 # This symbols as no dependencies bar baz: bazdep diff --git a/lld/test/wasm/stub-library-archive.s b/lld/test/wasm/stub-library-archive.s index 7aacf676b3436..76483d1463d64 100644 --- a/lld/test/wasm/stub-library-archive.s +++ b/lld/test/wasm/stub-library-archive.s @@ -14,6 +14,7 @@ # depeds on baz which is also defined in libstub.so. .functype foo () -> () +.import_name foo, foo_import .globl _start _start: diff --git a/lld/test/wasm/stub-library.s b/lld/test/wasm/stub-library.s index 9cbf2505ea9e7..b972003c5b05d 100644 --- a/lld/test/wasm/stub-library.s +++ b/lld/test/wasm/stub-library.s @@ -6,15 +6,12 @@ # RUN: not wasm-ld %t.o %p/Inputs/libstub-missing-dep.so -o %t.wasm 2>&1 | FileCheck --check-prefix=MISSING-DEP %s # When the dependencies are missing the link fails -# RUN: not wasm-ld %t.o %p/Inputs/libstub-missing-sym.so -o %t.wasm 2>&1 | FileCheck --check-prefix=MISSING-SYM %s - # MISSING-DEP: libstub-missing-dep.so: undefined symbol: missing_dep. Required by foo # MISSING-DEP: libstub-missing-dep.so: undefined symbol: missing_dep2. Required by foo -# MISSING-SYM: undefined symbol: foo - # The function foo is defined in libstub.so but depend on foodep1 and foodep2 .functype foo () -> () +.import_name foo, foo_import .globl foodep1 foodep1: diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp index b06c1e9b0be1b..d099689911fc6 100644 --- a/lld/wasm/Driver.cpp +++ b/lld/wasm/Driver.cpp @@ -955,6 +955,47 @@ static void processStubLibrariesPreLTO() { } } +static bool addStubSymbolDeps(const StubFile *stub_file, Symbol *sym, + ArrayRef deps) { + // The first stub library to define a given symbol sets this and + // definitions in later stub libraries are ignored. + if (sym->forceImport) + return false; // Already handled + sym->forceImport = true; + if (sym->traced) + message(toString(stub_file) + ": importing " + sym->getName()); + else + LLVM_DEBUG(llvm::dbgs() << toString(stub_file) << ": importing " + << sym->getName() << "\n"); + bool depsAdded = false; + for (const auto dep : deps) { + auto *needed = symtab->find(dep); + if (!needed) { + error(toString(stub_file) + ": undefined symbol: " + dep + + ". Required by " + toString(*sym)); + } else if (needed->isUndefined()) { + error(toString(stub_file) + ": undefined symbol: " + toString(*needed) + + ". Required by " + toString(*sym)); + } else { + if (needed->traced) + message(toString(stub_file) + ": exported " + toString(*needed) + + " due to import of " + sym->getName()); + else + LLVM_DEBUG(llvm::dbgs() + << "force export: " << toString(*needed) << "\n"); + needed->forceExport = true; + if (auto *lazy = dyn_cast(needed)) { + depsAdded = true; + lazy->extract(); + if (!config->whyExtract.empty()) + ctx.whyExtractRecords.emplace_back(toString(stub_file), + sym->getFile(), *sym); + } + } + } + return depsAdded; +} + static void processStubLibraries() { log("-- processStubLibraries"); bool depsAdded = false; @@ -963,49 +1004,28 @@ static void processStubLibraries() { for (auto &stub_file : ctx.stubFiles) { LLVM_DEBUG(llvm::dbgs() << "processing stub file: " << stub_file->getName() << "\n"); + + // First look for any imported symbols that directly match + // the names of the stub imports for (auto [name, deps]: stub_file->symbolDependencies) { auto* sym = symtab->find(name); - if (!sym || !sym->isUndefined()) { + if (sym && sym->isUndefined()) { + depsAdded |= addStubSymbolDeps(stub_file, sym, deps); + } else { if (sym && sym->traced) message(toString(stub_file) + ": stub symbol not needed: " + name); else - LLVM_DEBUG(llvm::dbgs() << "stub symbol not needed: `" << name << "`\n"); - continue; + LLVM_DEBUG(llvm::dbgs() + << "stub symbol not needed: `" << name << "`\n"); } - // 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); - else - LLVM_DEBUG(llvm::dbgs() - << toString(stub_file) << ": importing " << name << "\n"); - for (const auto dep : deps) { - auto* needed = symtab->find(dep); - if (!needed) { - error(toString(stub_file) + ": undefined symbol: " + dep + - ". Required by " + toString(*sym)); - } else if (needed->isUndefined()) { - error(toString(stub_file) + - ": undefined symbol: " + toString(*needed) + - ". Required by " + toString(*sym)); - } else { - if (needed->traced) - message(toString(stub_file) + ": exported " + toString(*needed) + - " due to import of " + name); - else - LLVM_DEBUG(llvm::dbgs() - << "force export: " << toString(*needed) << "\n"); - needed->forceExport = true; - if (auto *lazy = dyn_cast(needed)) { - depsAdded = true; - lazy->extract(); - if (!config->whyExtract.empty()) - ctx.whyExtractRecords.emplace_back(stub_file->getName(), - sym->getFile(), *sym); - } + } + + // Secondly looks for any symbols with an `importName` that matches + for (Symbol *sym : symtab->symbols()) { + if (sym->isUndefined() && sym->importName.has_value()) { + auto it = stub_file->symbolDependencies.find(sym->importName.value()); + if (it != stub_file->symbolDependencies.end()) { + depsAdded |= addStubSymbolDeps(stub_file, sym, it->second); } } }