[lld][WebAssembly] Fix spurious signature mismatch warnings
authorSam Clegg <sbc@chromium.org>
Fri, 30 Aug 2019 19:50:59 +0000 (19:50 +0000)
committerSam Clegg <sbc@chromium.org>
Fri, 30 Aug 2019 19:50:59 +0000 (19:50 +0000)
Summary:
This a follow up on: https://reviews.llvm.org/D62153

Handle the case where there are multiple object files that contain
undefined references to the same function.  We only generate a function
variant if the existing symbol is directly called.

See: https://github.com/emscripten-core/emscripten/issues/8995

Subscribers: dschuff, jgravelle-google, aheejin, sunfish, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D67015

llvm-svn: 370509

lld/test/wasm/signature-mismatch-unknown.ll
lld/wasm/SymbolTable.cpp

index 65bb31511d1cfb614c8690e391d48f47f9056d55..9bd97db50f1f96cb1f2e39e84c66f55f3cfdf604 100644 (file)
@@ -3,6 +3,14 @@
 ; RUN: wasm-ld --fatal-warnings -o %t.wasm %t.ret32.o %t.main.o
 ; RUN: wasm-ld --fatal-warnings -o %t.wasm %t.main.o %t.ret32.o
 
+; Also test the case where there are two different object files that contains
+; referneces ret32:
+; %t.main.o: Does not call ret32 directly; used the wrong signature.
+; %t.call-ret32.o: Calls ret32 directly; uses the correct signature.
+; RUN: llc -filetype=obj %p/Inputs/call-ret32.ll -o %t.call-ret32.o
+; RUN: wasm-ld --export=call_ret32 --fatal-warnings -o %t.wasm %t.main.o %t.call-ret32.o %t.ret32.o
+; RUN: wasm-ld --export=call_ret32 --fatal-warnings -o %t.wasm %t.call-ret32.o %t.main.o %t.ret32.o
+
 target triple = "wasm32-unknown-unknown"
 
 ; Function declartion with incorrect signature.
index c46eec411468d30c3c60baf6f1685f60f0499a62..44417b076c7fc5842edfaeea1fc9dad47f59b048 100644 (file)
@@ -425,9 +425,16 @@ Symbol *SymbolTable::addUndefinedFunction(StringRef name, StringRef importName,
     }
     if (!existingFunction->signature && sig)
       existingFunction->signature = sig;
-    if (isCalledDirectly && !signatureMatches(existingFunction, sig))
-      if (getFunctionVariant(s, sig, file, &s))
+    if (isCalledDirectly && !signatureMatches(existingFunction, sig)) {
+      auto* existingUndefined = dyn_cast<UndefinedFunction>(existingFunction);
+      // If the existing undefined functions is not called direcltly then let
+      // this one take precedence.  Otherwise the existing function is either
+      // direclty called or defined, in which case we need a function variant.
+      if (existingUndefined && !existingUndefined->isCalledDirectly)
         replaceSym();
+      else if (getFunctionVariant(s, sig, file, &s))
+        replaceSym();
+    }
   }
 
   return s;