[lld] [lld][WebAssembly] Fix spurious signature mismatch under LTO (PR #136197)

Daniel Bertalan via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 18 01:48:01 PDT 2025


================
@@ -108,9 +108,10 @@ BitcodeCompiler::~BitcodeCompiler() = default;
 
 static void undefine(Symbol *s) {
   if (auto f = dyn_cast<DefinedFunction>(s))
+    // If the signature is null, there were no calls from non-bitcode objects.
     replaceSymbol<UndefinedFunction>(f, f->getName(), std::nullopt,
                                      std::nullopt, 0, f->getFile(),
-                                     f->signature);
+                                     f->signature, f->signature != nullptr);
----------------
BertalanD wrote:

I don't think that would fix the issue: `signatureMatches()` returns `true` when either function has a null signature.

In the test case, after LTO, the `() -> void` reference from `a.ll` is added first. The existing undefined symbol has a null signature, but this one doesn't, so we set `existingFunction->signature` to `() -> void`:

https://github.com/llvm/llvm-project/blob/1db03cab70fd29fe13cb60cc102285d0d0f33957/lld/wasm/SymbolTable.cpp#L657-L658

 As `isCalledDirectly` is set to true, we'll report the signature mismatch when we try to add the `() -> i32` definition from `b.ll`.

I suppose an alternative would be to only set `existingFunction->signature` if  the undefined symbol we replace it with is called directly, but that would mean we never set the signature if the function has no call sites, only its address is taken. That might cause problems later on.

https://github.com/llvm/llvm-project/pull/136197


More information about the llvm-commits mailing list