diff --git a/lld/test/wasm/Inputs/strong-refs.s b/lld/test/wasm/Inputs/strong-refs.s new file mode 100644 --- /dev/null +++ b/lld/test/wasm/Inputs/strong-refs.s @@ -0,0 +1,5 @@ +.globl f2 +f2: + .functype f2 () -> (i32) + i32.const global_var + end_function diff --git a/lld/test/wasm/weak-undefined.s b/lld/test/wasm/weak-undefined.s --- a/lld/test/wasm/weak-undefined.s +++ b/lld/test/wasm/weak-undefined.s @@ -1,9 +1,18 @@ +# Test that undefined weak externals (global_var) and (foo) don't cause +# link failures and resolve to zero. + # RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown -o %t.o %s # RUN: wasm-ld -strip-all %t.o -o %t.wasm # RUN: obj2yaml %t.wasm | FileCheck %s -# Test that undefined weak externals (global_var) and (foo) don't cause -# link failures and resolve to zero. +# Also verify test that strong references in another file do cause link +# failure (See https://github.com/llvm/llvm-project/issues/60806) + +# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %p/Inputs/strong-refs.s -o %t-strong.o +# RUN: not wasm-ld -strip-all %t.o %t-strong.o -o %t.wasm 2>&1 | FileCheck --check-prefix=ERROR %s +# RUN: not wasm-ld -strip-all %t-strong.o %t.o -o %t.wasm 2>&1 | FileCheck --check-prefix=ERROR %s + +# ERROR: undefined symbol: global_var .functype foo () -> (i32) @@ -33,7 +42,6 @@ .weak foo .weak global_var - # CHECK: --- !WASM # CHECK-NEXT: FileHeader: # CHECK-NEXT: Version: 0x1 diff --git a/lld/wasm/SymbolTable.cpp b/lld/wasm/SymbolTable.cpp --- a/lld/wasm/SymbolTable.cpp +++ b/lld/wasm/SymbolTable.cpp @@ -548,6 +548,8 @@ file); if (isCalledDirectly) existingUndefined->isCalledDirectly = true; + if (s->isWeak()) + s->flags = flags; } } @@ -574,6 +576,8 @@ lazy->fetch(); } else if (s->isDefined()) { checkDataType(s, file); + } else if (s->isWeak()) { + s->flags = flags; } return s; } @@ -599,6 +603,8 @@ lazy->fetch(); else if (s->isDefined()) checkGlobalType(s, file, type); + else if (s->isWeak()) + s->flags = flags; return s; } @@ -623,6 +629,8 @@ lazy->fetch(); else if (s->isDefined()) checkTableType(s, file, type); + else if (s->isWeak()) + s->flags = flags; return s; } @@ -647,6 +655,8 @@ lazy->fetch(); else if (s->isDefined()) checkTagType(s, file, sig); + else if (s->isWeak()) + s->flags = flags; return s; } diff --git a/llvm/lib/Object/WasmObjectFile.cpp b/llvm/lib/Object/WasmObjectFile.cpp --- a/llvm/lib/Object/WasmObjectFile.cpp +++ b/llvm/lib/Object/WasmObjectFile.cpp @@ -38,7 +38,18 @@ void WasmSymbol::print(raw_ostream &Out) const { Out << "Name=" << Info.Name << ", Kind=" << toString(wasm::WasmSymbolType(Info.Kind)) << ", Flags=0x" - << Twine::utohexstr(Info.Flags); + << Twine::utohexstr(Info.Flags) << " ["; + switch (getBinding()) { + case wasm::WASM_SYMBOL_BINDING_GLOBAL: Out << "global"; break; + case wasm::WASM_SYMBOL_BINDING_LOCAL: Out << "local"; break; + case wasm::WASM_SYMBOL_BINDING_WEAK: Out << "weak"; break; + } + if (isHidden()) { + Out << ", hidden"; + } else { + Out << ", default"; + } + Out << "]"; if (!isTypeData()) { Out << ", ElemIndex=" << Info.ElementIndex; } else if (isDefined()) {