diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp --- a/lld/wasm/Driver.cpp +++ b/lld/wasm/Driver.cpp @@ -898,52 +898,61 @@ static void processStubLibraries() { log("-- processStubLibraries"); - 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 (!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); - 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); + bool depsAdded = false; + do { + depsAdded = false; + 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 (!sym || !sym->isUndefined()) { + if (sym && sym->traced) + message(toString(stub_file) + ": stub symbol not needed: " + name); else - LLVM_DEBUG(llvm::dbgs() - << "force export: " << toString(*needed) << "\n"); - needed->forceExport = true; - if (auto *lazy = dyn_cast(needed)) { - lazy->fetch(); - if (!config->whyExtract.empty()) - config->whyExtractRecords.emplace_back(stub_file->getName(), - sym->getFile(), *sym); + 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); + 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->fetch(); + if (!config->whyExtract.empty()) + config->whyExtractRecords.emplace_back(stub_file->getName(), + sym->getFile(), *sym); + } } } } } - } + } while (depsAdded); + log("-- done processStubLibraries"); }