[lld] [lld][WebAssembly] Handle stub symbol dependencies when an explicit import name is used (PR #80169)

Sam Clegg via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 19 11:39:15 PDT 2024


https://github.com/sbc100 updated https://github.com/llvm/llvm-project/pull/80169

>From cd133776fe54be283f9936c46d210fbdf8761dc9 Mon Sep 17 00:00:00 2001
From: Sam Clegg <sbc at chromium.org>
Date: Sun, 28 Jan 2024 10:19:49 -0800
Subject: [PATCH] [lld][WebAssembly] Handle stub symbol dependencies when an
 exlicit import name is used

---
 lld/wasm/Driver.cpp      | 94 ++++++++++++++++++++++++----------------
 lld/wasm/SymbolTable.cpp | 33 +++++++++++---
 lld/wasm/SymbolTable.h   |  2 +
 3 files changed, 86 insertions(+), 43 deletions(-)

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<StringRef> 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<LazySymbol>(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<LazySymbol>(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);
           }
         }
       }
diff --git a/lld/wasm/SymbolTable.cpp b/lld/wasm/SymbolTable.cpp
index 00c347ea3ef24..8a1c0ab1d4f43 100644
--- a/lld/wasm/SymbolTable.cpp
+++ b/lld/wasm/SymbolTable.cpp
@@ -507,6 +507,15 @@ static void setImportAttributes(T *existing,
   }
 }
 
+static void traceImport(std::optional<StringRef> importName, InputFile *file) {
+  if (importName.has_value()) {
+    auto name = importName.value();
+    if (symtab->isTraced(name)) {
+      printTraceSymbolUndefined(name, file);
+    }
+  }
+}
+
 Symbol *SymbolTable::addUndefinedFunction(StringRef name,
                                           std::optional<StringRef> importName,
                                           std::optional<StringRef> importModule,
@@ -526,6 +535,7 @@ Symbol *SymbolTable::addUndefinedFunction(StringRef name,
     printTraceSymbolUndefined(name, file);
 
   auto replaceSym = [&]() {
+    traceImport(importName, file);
     replaceSymbol<UndefinedFunction>(s, name, importName, importModule, flags,
                                      file, sig, isCalledDirectly);
   };
@@ -560,6 +570,7 @@ Symbol *SymbolTable::addUndefinedFunction(StringRef name,
         replaceSym();
     }
     if (existingUndefined) {
+      traceImport(importName, file);
       setImportAttributes(existingUndefined, importName, importModule, flags,
                           file);
       if (isCalledDirectly)
@@ -612,10 +623,11 @@ Symbol *SymbolTable::addUndefinedGlobal(StringRef name,
   if (s->traced)
     printTraceSymbolUndefined(name, file);
 
-  if (wasInserted)
+  if (wasInserted) {
+    traceImport(importName, file);
     replaceSymbol<UndefinedGlobal>(s, name, importName, importModule, flags,
                                    file, type);
-  else if (auto *lazy = dyn_cast<LazySymbol>(s))
+  } else if (auto *lazy = dyn_cast<LazySymbol>(s))
     lazy->extract();
   else if (s->isDefined())
     checkGlobalType(s, file, type);
@@ -638,10 +650,11 @@ Symbol *SymbolTable::addUndefinedTable(StringRef name,
   if (s->traced)
     printTraceSymbolUndefined(name, file);
 
-  if (wasInserted)
+  if (wasInserted) {
+    traceImport(importName, file);
     replaceSymbol<UndefinedTable>(s, name, importName, importModule, flags,
                                   file, type);
-  else if (auto *lazy = dyn_cast<LazySymbol>(s))
+  } else if (auto *lazy = dyn_cast<LazySymbol>(s))
     lazy->extract();
   else if (s->isDefined())
     checkTableType(s, file, type);
@@ -664,10 +677,11 @@ Symbol *SymbolTable::addUndefinedTag(StringRef name,
   if (s->traced)
     printTraceSymbolUndefined(name, file);
 
-  if (wasInserted)
+  if (wasInserted) {
+    traceImport(importName, file);
     replaceSymbol<UndefinedTag>(s, name, importName, importModule, flags, file,
                                 sig);
-  else if (auto *lazy = dyn_cast<LazySymbol>(s))
+  } else if (auto *lazy = dyn_cast<LazySymbol>(s))
     lazy->extract();
   else if (s->isDefined())
     checkTagType(s, file, sig);
@@ -831,6 +845,13 @@ void SymbolTable::trace(StringRef name) {
   symMap.insert({CachedHashStringRef(name), -1});
 }
 
+bool SymbolTable::isTraced(StringRef name) {
+  auto it = symMap.find(CachedHashStringRef(name));
+  if (it == symMap.end())
+    return false;
+  return it->second == -1 || symVector[it->second]->traced;
+}
+
 void SymbolTable::wrap(Symbol *sym, Symbol *real, Symbol *wrap) {
   // Swap symbols as instructed by -wrap.
   int &origIdx = symMap[CachedHashStringRef(sym->getName())];
diff --git a/lld/wasm/SymbolTable.h b/lld/wasm/SymbolTable.h
index 42ebb8be8eb3f..cec30bea91ea0 100644
--- a/lld/wasm/SymbolTable.h
+++ b/lld/wasm/SymbolTable.h
@@ -50,6 +50,8 @@ class SymbolTable {
 
   void trace(StringRef name);
 
+  bool isTraced(StringRef name);
+
   Symbol *addDefinedFunction(StringRef name, uint32_t flags, InputFile *file,
                              InputFunction *function);
   Symbol *addDefinedData(StringRef name, uint32_t flags, InputFile *file,



More information about the llvm-commits mailing list