[lld] 22c4f95 - [lld][WebAssembly] Improve merging multiple occurrences of an undefined symbol (#178550)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Jan 29 09:27:27 PST 2026
Author: Sam Clegg
Date: 2026-01-29T09:27:22-08:00
New Revision: 22c4f9534a404680c798cbe22784fca6ebdd4dc4
URL: https://github.com/llvm/llvm-project/commit/22c4f9534a404680c798cbe22784fca6ebdd4dc4
DIFF: https://github.com/llvm/llvm-project/commit/22c4f9534a404680c798cbe22784fca6ebdd4dc4.diff
LOG: [lld][WebAssembly] Improve merging multiple occurrences of an undefined symbol (#178550)
This change renames `setImportAttributes` to `updateExistingUndefined`
which better defines what it does. We also now call this function for
all different symbol types.
In addition we preserve the `NO_STRIP` symbol attribute if any undefined
reference is tagged as such.
This is partial fix for #174676, although there seems to be anther crash
that occurs after this issue is fixed.
Added:
lld/test/wasm/merge-undefined-symbols.s
Modified:
lld/wasm/SymbolTable.cpp
Removed:
################################################################################
diff --git a/lld/test/wasm/merge-undefined-symbols.s b/lld/test/wasm/merge-undefined-symbols.s
new file mode 100644
index 0000000000000..62856d6ed86a7
--- /dev/null
+++ b/lld/test/wasm/merge-undefined-symbols.s
@@ -0,0 +1,41 @@
+# Verify that the `no_strip` attribute on undefined symbols is preserved
+# as long as one of the undefined references is `no_strip`.
+# The indirect function table is created by the linker in the case that
+# the __indirect_function_table symbol is live (i.e. marked as no_strip).
+# This test verifies that the undefined symbol is NO_STRIP, even if the first
+# undefined reference is not NO_STRIP.
+#
+# RUN: split-file %s %t
+# RUN: llvm-mc -mattr=+reference-types -filetype=obj -triple=wasm32-unknown-unknown -o %t/main.o %t/main.s
+# RUN: llvm-mc -mattr=+reference-types -filetype=obj -triple=wasm32-unknown-unknown -o %t/other.o %t/other.s
+#
+# RUN: wasm-ld %t/main.o %t/other.o -o %t.wasm
+# RUN: obj2yaml %t.wasm | FileCheck %s
+#
+# RUN: wasm-ld %t/other.o %t/main.o -o %t2.wasm
+# RUN: obj2yaml %t2.wasm | FileCheck %s
+
+#--- main.s
+.globl __indirect_function_table
+.tabletype __indirect_function_table, funcref
+.no_dead_strip __indirect_function_table
+
+.globl _start
+_start:
+ .functype _start () -> ()
+ end_function
+
+#--- other.s
+# This file contains a reference to __indirect_function_table that is not
+# marked as `.no_dead_strip`.
+.globl __indirect_function_table
+.tabletype __indirect_function_table, funcref
+
+# CHECK: - Type: TABLE
+# CHECK-NEXT: Tables:
+# CHECK-NEXT: - Index: 0
+# CHECK-NEXT: ElemType: FUNCREF
+# CHECK-NEXT: Limits:
+# CHECK-NEXT: Flags: [ HAS_MAX ]
+# CHECK-NEXT: Minimum: 0x1
+# CHECK-NEXT: Maximum: 0x1
diff --git a/lld/wasm/SymbolTable.cpp b/lld/wasm/SymbolTable.cpp
index 5c811e0ff42a7..33a68b5defd72 100644
--- a/lld/wasm/SymbolTable.cpp
+++ b/lld/wasm/SymbolTable.cpp
@@ -582,11 +582,10 @@ Symbol *SymbolTable::addDefinedTable(StringRef name, uint32_t flags,
// With LTO these attributes are not available when the bitcode is read and only
// become available when the LTO object is read. In this case we silently
// replace the empty attributes with the valid ones.
-template <typename T>
-static void setImportAttributes(T *existing,
- std::optional<StringRef> importName,
- std::optional<StringRef> importModule,
- uint32_t flags, InputFile *file) {
+static void
+updateExistingUndefined(Symbol *existing, uint32_t flags, InputFile *file,
+ std::optional<StringRef> importName = {},
+ std::optional<StringRef> importModule = {}) {
if (importName) {
if (!existing->importName)
existing->importName = importName;
@@ -612,6 +611,10 @@ static void setImportAttributes(T *existing,
if (existing->isWeak() && binding != WASM_SYMBOL_BINDING_WEAK) {
existing->flags = (existing->flags & ~WASM_SYMBOL_BINDING_MASK) | binding;
}
+
+ // Certain flags such as NO_STRIP should be maintianed if either old or
+ // new symbol is marked as such.
+ existing->flags |= flags & WASM_SYMBOL_NO_STRIP;
}
Symbol *SymbolTable::addUndefinedFunction(StringRef name,
@@ -675,12 +678,10 @@ Symbol *SymbolTable::addUndefinedFunction(StringRef name,
replaceSym();
}
if (existingUndefined) {
- setImportAttributes(existingUndefined, importName, importModule, flags,
- file);
+ updateExistingUndefined(existingUndefined, flags, file, importName,
+ importModule);
if (isCalledDirectly)
existingUndefined->isCalledDirectly = true;
- if (s->isWeak())
- s->flags = flags;
}
}
@@ -707,8 +708,8 @@ Symbol *SymbolTable::addUndefinedData(StringRef name, uint32_t flags,
lazy->extract();
} else if (s->isDefined()) {
checkDataType(s, file);
- } else if (s->isWeak()) {
- s->flags = flags;
+ } else {
+ updateExistingUndefined(s, flags, file);
}
return s;
}
@@ -734,8 +735,8 @@ Symbol *SymbolTable::addUndefinedGlobal(StringRef name,
lazy->extract();
else if (s->isDefined())
checkGlobalType(s, file, type);
- else if (s->isWeak())
- s->flags = flags;
+ else
+ updateExistingUndefined(s, flags, file);
return s;
}
@@ -760,8 +761,8 @@ Symbol *SymbolTable::addUndefinedTable(StringRef name,
lazy->extract();
else if (s->isDefined())
checkTableType(s, file, type);
- else if (s->isWeak())
- s->flags = flags;
+ else
+ updateExistingUndefined(s, flags, file);
return s;
}
@@ -786,12 +787,13 @@ Symbol *SymbolTable::addUndefinedTag(StringRef name,
lazy->extract();
else if (s->isDefined())
checkTagType(s, file, sig);
- else if (s->isWeak())
- s->flags = flags;
+ else
+ updateExistingUndefined(s, flags, file);
return s;
}
TableSymbol *SymbolTable::createUndefinedIndirectFunctionTable(StringRef name) {
+ LLVM_DEBUG(llvm::dbgs() << "createUndefinedIndirectFunctionTable\n");
WasmLimits limits{0, 0, 0, 0}; // Set by the writer.
WasmTableType *type = make<WasmTableType>();
type->ElemType = ValType::FUNCREF;
@@ -806,6 +808,7 @@ TableSymbol *SymbolTable::createUndefinedIndirectFunctionTable(StringRef name) {
}
TableSymbol *SymbolTable::createDefinedIndirectFunctionTable(StringRef name) {
+ LLVM_DEBUG(llvm::dbgs() << "createDefinedIndirectFunctionTable\n");
const uint32_t invalidIndex = -1;
WasmLimits limits{0, 0, 0, 0}; // Set by the writer.
WasmTableType type{ValType::FUNCREF, limits};
More information about the llvm-commits
mailing list