Skip to content

Commit 7a8ee92

Browse files
committed
[lld][WebAssembly] Process stub libraries in a loop
When stub libraries trigger the fetching of new object files we can potentially introduce new undefined symbols so process the stub in loop until no new objects are pulled in. Differential Revision: https://reviews.llvm.org/D153466
1 parent 06adac8 commit 7a8ee92

File tree

3 files changed

+111
-41
lines changed

3 files changed

+111
-41
lines changed

lld/test/wasm/Inputs/libstub.so

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
foo: foodep1,foodep2
44
# This symbols as no dependencies
55
bar
6+
baz: bazdep

lld/test/wasm/stub-library-archive.s

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# RUN: split-file %s %t
2+
# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown -o %t.o %t/main.s
3+
# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown -o %t/foodeps.o %t/foodeps.s
4+
# RUN: rm -f %t/libfoodeps.a
5+
# RUN: llvm-ar rcs %t/libfoodeps.a %t/foodeps.o
6+
# RUN: wasm-ld %t.o %p/Inputs/libstub.so %t/libfoodeps.a -o %t.wasm
7+
# RUN: obj2yaml %t.wasm | FileCheck %s
8+
9+
#--- main.s
10+
11+
# The function foo is defined in libstub.so but depends on foodep1 and foodep2
12+
13+
# foodep1 and foodep2 a defined libfoodeps.a(foodeps.o) but this function
14+
# depeds on baz which is also defined in libstub.so.
15+
16+
.functype foo () -> ()
17+
18+
.globl _start
19+
_start:
20+
.functype _start () -> ()
21+
call foo
22+
end_function
23+
24+
.globl bazdep
25+
bazdep:
26+
.functype bazdep () -> ()
27+
end_function
28+
29+
#--- foodeps.s
30+
31+
.functype baz () -> ()
32+
33+
.globl foodep1
34+
foodep1:
35+
.functype foodep1 () -> ()
36+
call baz
37+
end_function
38+
39+
.globl foodep2
40+
foodep2:
41+
.functype foodep2 () -> ()
42+
end_function
43+
44+
# CHECK: - Type: EXPORT
45+
# CHECK-NEXT: Exports:
46+
# CHECK-NEXT: - Name: memory
47+
# CHECK-NEXT: Kind: MEMORY
48+
# CHECK-NEXT: Index: 0
49+
# CHECK-NEXT: - Name: _start
50+
# CHECK-NEXT: Kind: FUNCTION
51+
# CHECK-NEXT: Index: 2
52+
# CHECK-NEXT: - Name: bazdep
53+
# CHECK-NEXT: Kind: FUNCTION
54+
# CHECK-NEXT: Index: 3
55+
# CHECK-NEXT: - Name: foodep1
56+
# CHECK-NEXT: Kind: FUNCTION
57+
# CHECK-NEXT: Index: 4
58+
# CHECK-NEXT: - Name: foodep2
59+
# CHECK-NEXT: Kind: FUNCTION
60+
# CHECK-NEXT: Index: 5

lld/wasm/Driver.cpp

Lines changed: 50 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -898,52 +898,61 @@ static void processStubLibrariesPreLTO() {
898898

899899
static void processStubLibraries() {
900900
log("-- processStubLibraries");
901-
for (auto &stub_file : symtab->stubFiles) {
902-
LLVM_DEBUG(llvm::dbgs()
903-
<< "processing stub file: " << stub_file->getName() << "\n");
904-
for (auto [name, deps]: stub_file->symbolDependencies) {
905-
auto* sym = symtab->find(name);
906-
if (!sym || !sym->isUndefined()) {
907-
LLVM_DEBUG(llvm::dbgs() << "stub symbol not needed: " << name << "\n");
908-
continue;
909-
}
910-
// The first stub library to define a given symbol sets this and
911-
// definitions in later stub libraries are ignored.
912-
if (sym->forceImport)
913-
continue; // Already handled
914-
sym->forceImport = true;
915-
if (sym->traced)
916-
message(toString(stub_file) + ": importing " + name);
917-
else
918-
LLVM_DEBUG(llvm::dbgs()
919-
<< toString(stub_file) << ": importing " << name << "\n");
920-
for (const auto dep : deps) {
921-
auto* needed = symtab->find(dep);
922-
if (!needed) {
923-
error(toString(stub_file) + ": undefined symbol: " + dep +
924-
". Required by " + toString(*sym));
925-
} else if (needed->isUndefined()) {
926-
error(toString(stub_file) +
927-
": undefined symbol: " + toString(*needed) +
928-
". Required by " + toString(*sym));
929-
} else {
930-
if (needed->traced)
931-
message(toString(stub_file) + ": exported " + toString(*needed) +
932-
" due to import of " + name);
901+
bool depsAdded = false;
902+
do {
903+
depsAdded = false;
904+
for (auto &stub_file : symtab->stubFiles) {
905+
LLVM_DEBUG(llvm::dbgs()
906+
<< "processing stub file: " << stub_file->getName() << "\n");
907+
for (auto [name, deps]: stub_file->symbolDependencies) {
908+
auto* sym = symtab->find(name);
909+
if (!sym || !sym->isUndefined()) {
910+
if (sym && sym->traced)
911+
message(toString(stub_file) + ": stub symbol not needed: " + name);
933912
else
934-
LLVM_DEBUG(llvm::dbgs()
935-
<< "force export: " << toString(*needed) << "\n");
936-
needed->forceExport = true;
937-
if (auto *lazy = dyn_cast<LazySymbol>(needed)) {
938-
lazy->fetch();
939-
if (!config->whyExtract.empty())
940-
config->whyExtractRecords.emplace_back(stub_file->getName(),
941-
sym->getFile(), *sym);
913+
LLVM_DEBUG(llvm::dbgs() << "stub symbol not needed: `" << name << "`\n");
914+
continue;
915+
}
916+
// The first stub library to define a given symbol sets this and
917+
// definitions in later stub libraries are ignored.
918+
if (sym->forceImport)
919+
continue; // Already handled
920+
sym->forceImport = true;
921+
if (sym->traced)
922+
message(toString(stub_file) + ": importing " + name);
923+
else
924+
LLVM_DEBUG(llvm::dbgs()
925+
<< toString(stub_file) << ": importing " << name << "\n");
926+
for (const auto dep : deps) {
927+
auto* needed = symtab->find(dep);
928+
if (!needed) {
929+
error(toString(stub_file) + ": undefined symbol: " + dep +
930+
". Required by " + toString(*sym));
931+
} else if (needed->isUndefined()) {
932+
error(toString(stub_file) +
933+
": undefined symbol: " + toString(*needed) +
934+
". Required by " + toString(*sym));
935+
} else {
936+
if (needed->traced)
937+
message(toString(stub_file) + ": exported " + toString(*needed) +
938+
" due to import of " + name);
939+
else
940+
LLVM_DEBUG(llvm::dbgs()
941+
<< "force export: " << toString(*needed) << "\n");
942+
needed->forceExport = true;
943+
if (auto *lazy = dyn_cast<LazySymbol>(needed)) {
944+
depsAdded = true;
945+
lazy->fetch();
946+
if (!config->whyExtract.empty())
947+
config->whyExtractRecords.emplace_back(stub_file->getName(),
948+
sym->getFile(), *sym);
949+
}
942950
}
943951
}
944952
}
945953
}
946-
}
954+
} while (depsAdded);
955+
947956
log("-- done processStubLibraries");
948957
}
949958

0 commit comments

Comments
 (0)