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
}
; 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
// 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;
}
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;
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();