Index: test/wasm/weak-symbols.ll =================================================================== --- test/wasm/weak-symbols.ll +++ test/wasm/weak-symbols.ll @@ -24,7 +24,7 @@ ; CHECK-NEXT: ReturnType: I32 ; CHECK-NEXT: ParamTypes: ; CHECK-NEXT: - Type: FUNCTION -; CHECK-NEXT: FunctionTypes: [ 0, 0, 0, 0, 0 ] +; CHECK-NEXT: FunctionTypes: [ 0, 0, 0, 0 ] ; CHECK-NEXT: - Type: TABLE ; CHECK-NEXT: Tables: ; CHECK-NEXT: - ElemType: ANYFUNC @@ -59,7 +59,7 @@ ; CHECK-NEXT: Index: 2 ; CHECK-NEXT: - Name: exportWeak2 ; CHECK-NEXT: Kind: FUNCTION -; CHECK-NEXT: Index: 4 +; CHECK-NEXT: Index: 3 ; CHECK-NEXT: - Type: ELEM ; CHECK-NEXT: Segments: ; CHECK-NEXT: - Offset: @@ -79,9 +79,6 @@ ; CHECK-NEXT: Body: 4181808080000B ; CHECK-NEXT: - Index: 3 ; CHECK-NEXT: Locals: -; CHECK-NEXT: Body: 41020B -; CHECK-NEXT: - Index: 4 -; CHECK-NEXT: Locals: ; CHECK-NEXT: Body: 4181808080000B ; CHECK-NEXT: - Type: DATA ; CHECK-NEXT: Segments: @@ -101,6 +98,6 @@ ; CHECK-NEXT: Name: _start ; CHECK-NEXT: - Index: 2 ; CHECK-NEXT: Name: exportWeak1 -; CHECK-NEXT: - Index: 4 +; CHECK-NEXT: - Index: 3 ; CHECK-NEXT: Name: exportWeak2 ; CHECK-NEXT: ... Index: wasm/InputFiles.cpp =================================================================== --- wasm/InputFiles.cpp +++ wasm/InputFiles.cpp @@ -14,6 +14,7 @@ #include "SymbolTable.h" #include "lld/Common/ErrorHandler.h" #include "lld/Common/Memory.h" +#include "llvm/ADT/SmallBitVector.h" #include "llvm/Object/Binary.h" #include "llvm/Object/Wasm.h" #include "llvm/Support/raw_ostream.h" @@ -193,6 +194,7 @@ // Populate `FunctionSymbols` and `GlobalSymbols` based on the WasmSymbols // in the object + SmallBitVector ReachedFunctions(Funcs.size(), false); for (const SymbolRef &Sym : WasmObj->symbols()) { const WasmSymbol &WasmSym = WasmObj->getWasmSymbol(Sym.getRawDataRefImpl()); Symbol *S; @@ -202,6 +204,8 @@ if (!isExcludedByComdat(Function)) { S = createDefined(WasmSym, Symbol::Kind::DefinedFunctionKind, nullptr, Function); + if (S->getFile() == this) + ReachedFunctions[WasmSym.ElementIndex - NumFunctionImports] = true; break; } else { Function->Discarded = true; @@ -252,6 +256,16 @@ for (size_t I = 0; I < GlobalSymbols.size(); ++I) assert(GlobalSymbols[I] != nullptr);); + // This is a crude precursor to garbage collection, but it works really nicely + // for discarding multiple copies of weak symbols. If the function isn't + // reachable by any Symbol (because another file has defined the weak symbol), + // then it's discardable. We aren't considering here whether the Symbol is + // actually ever called. + for (uint32_t I = 0; I < Funcs.size(); ++I) { + if (!ReachedFunctions[I]) + Functions[I]->Discarded = true; + } + // Populate `TableSymbols` with all symbols that are called indirectly uint32_t SegmentCount = WasmObj->elements().size(); if (SegmentCount) {