[lld] 7a8ee92 - [lld][WebAssembly] Process stub libraries in a loop

Sam Clegg via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 11 11:22:58 PDT 2023


Author: Sam Clegg
Date: 2023-08-11T11:07:40-07:00
New Revision: 7a8ee92fa83c13967e916868541518e7cebdead7

URL: https://github.com/llvm/llvm-project/commit/7a8ee92fa83c13967e916868541518e7cebdead7
DIFF: https://github.com/llvm/llvm-project/commit/7a8ee92fa83c13967e916868541518e7cebdead7.diff

LOG: [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

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

Modified: 
    lld/test/wasm/Inputs/libstub.so
    lld/wasm/Driver.cpp

Removed: 
    


################################################################################
diff  --git a/lld/test/wasm/Inputs/libstub.so b/lld/test/wasm/Inputs/libstub.so
index 57e61f632b1017..f7e38b4272f249 100644
--- a/lld/test/wasm/Inputs/libstub.so
+++ b/lld/test/wasm/Inputs/libstub.so
@@ -3,3 +3,4 @@
 foo: 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
new file mode 100644
index 00000000000000..7aacf676b34360
--- /dev/null
+++ b/lld/test/wasm/stub-library-archive.s
@@ -0,0 +1,60 @@
+# RUN: split-file %s %t
+# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown -o %t.o %t/main.s
+# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown -o %t/foodeps.o %t/foodeps.s
+# RUN: rm -f %t/libfoodeps.a
+# RUN: llvm-ar rcs %t/libfoodeps.a %t/foodeps.o
+# RUN: wasm-ld %t.o %p/Inputs/libstub.so %t/libfoodeps.a -o %t.wasm
+# RUN: obj2yaml %t.wasm | FileCheck %s
+
+#--- main.s
+
+# The function foo is defined in libstub.so but depends on foodep1 and foodep2
+
+# foodep1 and foodep2 a defined libfoodeps.a(foodeps.o) but this function
+# depeds on baz which is also defined in libstub.so.
+
+.functype foo () -> ()
+
+.globl _start
+_start:
+    .functype _start () -> ()
+    call foo
+    end_function
+
+.globl bazdep
+bazdep:
+    .functype bazdep () -> ()
+    end_function
+
+#--- foodeps.s
+
+.functype baz () -> ()
+
+.globl foodep1
+foodep1:
+  .functype foodep1 () -> ()
+  call baz
+  end_function
+
+.globl foodep2
+foodep2:
+  .functype foodep2 () -> ()
+  end_function
+
+# CHECK:       - Type:            EXPORT
+# CHECK-NEXT:    Exports:
+# CHECK-NEXT:      - Name:            memory
+# CHECK-NEXT:        Kind:            MEMORY
+# CHECK-NEXT:        Index:           0
+# CHECK-NEXT:      - Name:            _start
+# CHECK-NEXT:        Kind:            FUNCTION
+# CHECK-NEXT:        Index:           2
+# CHECK-NEXT:      - Name:            bazdep
+# CHECK-NEXT:        Kind:            FUNCTION
+# CHECK-NEXT:        Index:           3
+# CHECK-NEXT:      - Name:            foodep1
+# CHECK-NEXT:        Kind:            FUNCTION
+# CHECK-NEXT:        Index:           4
+# CHECK-NEXT:      - Name:            foodep2
+# CHECK-NEXT:        Kind:            FUNCTION
+# CHECK-NEXT:        Index:           5

diff  --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp
index b0d6d1147e6b0b..c98d3522a5a227 100644
--- a/lld/wasm/Driver.cpp
+++ b/lld/wasm/Driver.cpp
@@ -898,52 +898,61 @@ static void processStubLibrariesPreLTO() {
 
 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<LazySymbol>(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<LazySymbol>(needed)) {
+              depsAdded = true;
+              lazy->fetch();
+              if (!config->whyExtract.empty())
+                config->whyExtractRecords.emplace_back(stub_file->getName(),
+                                                       sym->getFile(), *sym);
+            }
           }
         }
       }
     }
-  }
+  } while (depsAdded);
+
   log("-- done processStubLibraries");
 }
 


        


More information about the llvm-commits mailing list