From: Sam Clegg Date: Fri, 28 Sep 2018 16:50:14 +0000 (+0000) Subject: [WebAssembly] Preserve function signatures during LTO X-Git-Tag: llvmorg-8.0.0-rc1~7656 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8b0b48f343cb0347e266f8b551425e5fa21ce948;p=platform%2Fupstream%2Fllvm.git [WebAssembly] Preserve function signatures during LTO With LTO when and undefined function (with a known signature) in replaced by a defined bitcode function we were loosing the signature information (since bitcode functions don't have signatures). With this change we preserve the original signature from the undefined function and verify that the post LTO compiled function has the correct signature. This change improves the error handling in the case where there is a signature mismatch with a function defined in a bitcode file. Differential Revision: https://reviews.llvm.org/D50721 llvm-svn: 343340 --- diff --git a/lld/test/wasm/lto/signature-mismatch.ll b/lld/test/wasm/lto/signature-mismatch.ll new file mode 100644 index 0000000..4b6b3b8 --- /dev/null +++ b/lld/test/wasm/lto/signature-mismatch.ll @@ -0,0 +1,19 @@ +; RUN: llc -filetype=obj -o %t.o %s +; RUN: llvm-as %S/Inputs/archive.ll -o %t1.o +; RUN: not wasm-ld --fatal-warnings %t.o %t1.o -o %t.wasm 2>&1 | FileCheck %s + +; Test that functions defined in bitcode correctly report signature +; mistmaches with existing undefined sybmols in normal objects. + +target triple = "wasm32-unknown-unknown" + +; f is defined to take no argument in archive.ll which is compiled to bitcode +declare void @f(i32); + +define void @_start() { + call void @f(i32 0) + ret void +} + +; CHECK: >>> defined as (I32) -> void in {{.*}}signature-mismatch.ll.tmp1.o +; CHECK: >>> defined as () -> void in lto.tmp diff --git a/lld/wasm/LTO.cpp b/lld/wasm/LTO.cpp index f15551d..933607a0 100644 --- a/lld/wasm/LTO.cpp +++ b/lld/wasm/LTO.cpp @@ -72,10 +72,11 @@ BitcodeCompiler::BitcodeCompiler() : LTOObj(createLTO()) {} BitcodeCompiler::~BitcodeCompiler() = default; static void undefine(Symbol *S) { - if (isa(S)) - replaceSymbol(S, S->getName(), 0); + if (auto F = dyn_cast(S)) + replaceSymbol(F, F->getName(), 0, F->getFile(), + F->FunctionType); else if (isa(S)) - replaceSymbol(S, S->getName(), 0); + replaceSymbol(S, S->getName(), 0, S->getFile()); else llvm_unreachable("unexpected symbol kind"); } diff --git a/lld/wasm/SymbolTable.cpp b/lld/wasm/SymbolTable.cpp index 2a4249e..d1e9c05 100644 --- a/lld/wasm/SymbolTable.cpp +++ b/lld/wasm/SymbolTable.cpp @@ -201,7 +201,9 @@ static bool shouldReplace(const Symbol *Existing, InputFile *NewFile, Symbol *SymbolTable::addDefinedFunction(StringRef Name, uint32_t Flags, InputFile *File, InputFunction *Function) { - LLVM_DEBUG(dbgs() << "addDefinedFunction: " << Name << "\n"); + LLVM_DEBUG(dbgs() << "addDefinedFunction: " << Name << " [" + << (Function ? toString(Function->Signature) : "none") + << "]\n"); Symbol *S; bool WasInserted; std::tie(S, WasInserted) = insert(Name, File); @@ -214,8 +216,16 @@ Symbol *SymbolTable::addDefinedFunction(StringRef Name, uint32_t Flags, if (Function) checkFunctionType(S, File, &Function->Signature); - if (shouldReplace(S, File, Flags)) - replaceSymbol(S, Name, Flags, File, Function); + if (shouldReplace(S, File, Flags)) { + // If the new defined function doesn't have signture (i.e. bitcode + // functions) but the old symbols does then preserve the old signature + const WasmSignature *OldSig = nullptr; + if (auto* F = dyn_cast(S)) + OldSig = F->FunctionType; + auto NewSym = replaceSymbol(S, Name, Flags, File, Function); + if (!NewSym->FunctionType) + NewSym->FunctionType = OldSig; + } return S; } @@ -263,7 +273,8 @@ Symbol *SymbolTable::addDefinedGlobal(StringRef Name, uint32_t Flags, Symbol *SymbolTable::addUndefinedFunction(StringRef Name, uint32_t Flags, InputFile *File, const WasmSignature *Sig) { - LLVM_DEBUG(dbgs() << "addUndefinedFunction: " << Name << "\n"); + LLVM_DEBUG(dbgs() << "addUndefinedFunction: " << Name << + " [" << (Sig ? toString(*Sig) : "none") << "]\n"); Symbol *S; bool WasInserted;