[WebAssembly] Fix signatures of undefined function in LTO object which are not called directly.

We recently added special handling for function that are not called
directly but failed to add testing for the LTO case.

See https://reviews.llvm.org/D62153

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

git-svn-id: https://llvm.org/svn/llvm-project/lld/trunk@361975 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/wasm/lto/undef.ll b/test/wasm/lto/undef.ll
index 729007b..65e8e46 100644
--- a/test/wasm/lto/undef.ll
+++ b/test/wasm/lto/undef.ll
@@ -5,10 +5,22 @@
 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 
-declare void @bar()
+declare i32 @bar()
+
+; Symbols such as foo which are only called indirectly are handled slightly
+; differently with resepect to signature checking.
+declare i32 @foo()
+
+@ptr = global i8* bitcast (i32 ()* @foo to i8*), align 8
+; Ensure access to ptr is not inlined below, even under LTO
+@llvm.used = appending global [1 x i8**] [i8** @ptr], section "llvm.metadata"
 
 define void @_start() {
-  call void @bar()
+  call i32 @bar()
+
+  %addr = load i32 ()*, i32 ()** bitcast (i8** @ptr to i32 ()**), align 8
+  call i32 %addr()
+
   ret void
 }
 
@@ -18,3 +30,7 @@
 ; CHECK-NEXT:        Field:           bar
 ; CHECK-NEXT:        Kind:            FUNCTION
 ; CHECK-NEXT:        SigIndex:        0
+; CHECK-NEXT:      - Module:          env
+; CHECK-NEXT:        Field:           foo
+; CHECK-NEXT:        Kind:            FUNCTION
+; CHECK-NEXT:        SigIndex:        0
diff --git a/wasm/SymbolTable.cpp b/wasm/SymbolTable.cpp
index ae42474..dec59cb 100644
--- a/wasm/SymbolTable.cpp
+++ b/wasm/SymbolTable.cpp
@@ -136,14 +136,13 @@
 // mismatch.
 static bool signatureMatches(FunctionSymbol *Existing,
                              const WasmSignature *NewSig) {
-  if (!NewSig)
-    return true;
-
   const WasmSignature *OldSig = Existing->Signature;
-  if (!OldSig) {
-    Existing->Signature = NewSig;
+
+  // If either function is missing a signature (this happend for bitcode
+  // symbols) then assume they match.  Any mismatch will be reported later
+  // when the LTO objects are added.
+  if (!NewSig || !OldSig)
     return true;
-  }
 
   return *NewSig == *OldSig;
 }
@@ -390,8 +389,9 @@
                                           uint32_t Flags, InputFile *File,
                                           const WasmSignature *Sig,
                                           bool IsCalledDirectly) {
-  LLVM_DEBUG(dbgs() << "addUndefinedFunction: " << Name <<
-             " [" << (Sig ? toString(*Sig) : "none") << "]\n");
+  LLVM_DEBUG(dbgs() << "addUndefinedFunction: " << Name << " ["
+                    << (Sig ? toString(*Sig) : "none")
+                    << "] IsCalledDirectly:" << IsCalledDirectly << "\n");
 
   Symbol *S;
   bool WasInserted;
@@ -414,6 +414,8 @@
       reportTypeError(S, File, WASM_SYMBOL_TYPE_FUNCTION);
       return S;
     }
+    if (!ExistingFunction->Signature && Sig)
+      ExistingFunction->Signature = Sig;
     if (IsCalledDirectly && !signatureMatches(ExistingFunction, Sig))
       if (getFunctionVariant(S, Sig, File, &S))
         Replace();