[lld] [lld][WebAssembly] Allow defining of arbitrary symbols types in LTO objects (PR #196552)

Sam Clegg via llvm-commits llvm-commits at lists.llvm.org
Fri May 8 08:40:56 PDT 2026


https://github.com/sbc100 updated https://github.com/llvm/llvm-project/pull/196552

>From 4b3c480f90945da042ae23a1bd67f565fe6ffb65 Mon Sep 17 00:00:00 2001
From: Sam Clegg <sbc at chromium.org>
Date: Thu, 7 May 2026 16:40:33 -0700
Subject: [PATCH] [lld][WebAssembly] Allow defining of arbitrary symbols types
 in LTO objects

Bitcode files don't contains precise symbol type information so we
always allow new defined symbols overwrite bitcode symbols rather than
reporting type mismatches.

Fixes: #195311
---
 lld/test/wasm/lto/inline-asm-symbols.ll | 24 ++++++++++++++++++++++++
 lld/test/wasm/lto/signature-mismatch.ll |  6 +++---
 lld/wasm/SymbolTable.cpp                | 20 ++++++++++++++++++--
 3 files changed, 45 insertions(+), 5 deletions(-)
 create mode 100644 lld/test/wasm/lto/inline-asm-symbols.ll

diff --git a/lld/test/wasm/lto/inline-asm-symbols.ll b/lld/test/wasm/lto/inline-asm-symbols.ll
new file mode 100644
index 0000000000000..8b2f6270d7e2b
--- /dev/null
+++ b/lld/test/wasm/lto/inline-asm-symbols.ll
@@ -0,0 +1,24 @@
+;; Test that a bitcode symbol defined in inline assembly (which wasm-ld
+;; initially guesses is a FUNCTION) can be replaced by the LTO-generated
+;; object symbol (which is correctly identified as a TAG) without error.
+
+; RUN: llvm-as %s -o %t.o
+; RUN: wasm-ld --export=foo %t.o -o %t.wasm
+; RUN: obj2yaml %t.wasm | FileCheck %s
+
+; CHECK:  - Type:            TAG
+; CHECK:    TagTypes:        [ 1 ]
+; CHECK:  - Name:            foo
+; CHECK:    Kind:            TAG
+; CHECK:    Index:           0
+
+target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
+target triple = "wasm32-unknown-unknown"
+
+module asm ".globl foo"
+module asm ".tagtype foo i32"
+module asm "foo:"
+
+define void @_start() {
+  ret void
+}
diff --git a/lld/test/wasm/lto/signature-mismatch.ll b/lld/test/wasm/lto/signature-mismatch.ll
index 6580c8cf71b33..58ec045a77981 100644
--- a/lld/test/wasm/lto/signature-mismatch.ll
+++ b/lld/test/wasm/lto/signature-mismatch.ll
@@ -1,6 +1,6 @@
 ; 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
+; RUN: llvm-as %S/Inputs/archive.ll -o %t.archive.o
+; RUN: not wasm-ld --fatal-warnings %t.o %t.archive.o -o %t.wasm 2>&1 | FileCheck %s
 
 ; Test that functions defined in bitcode correctly report signature
 ; mismatches with existing undefined sybmols in normal objects.
@@ -16,5 +16,5 @@ define void @_start() {
 }
 
 ; CHECK: error: function signature mismatch: f
-; CHECK: >>> defined as (i32) -> void in {{.*}}signature-mismatch.ll.tmp1.o
+; CHECK: >>> defined as (i32) -> void in {{.*}}signature-mismatch.ll.tmp.archive.o
 ; CHECK: >>> defined as () -> void in {{.*}}signature-mismatch.ll.tmp.wasm.lto.o
diff --git a/lld/wasm/SymbolTable.cpp b/lld/wasm/SymbolTable.cpp
index cda192323f067..88ac54302c286 100644
--- a/lld/wasm/SymbolTable.cpp
+++ b/lld/wasm/SymbolTable.cpp
@@ -165,6 +165,11 @@ std::pair<Symbol *, bool> SymbolTable::insert(StringRef name,
   return {s, wasInserted};
 }
 
+static bool isBitcodeSymbol(const Symbol *symbol) {
+  return symbol->getFile() &&
+         symbol->getFile()->kind() == InputFile::BitcodeKind;
+}
+
 static void reportTypeError(const Symbol *existing, const InputFile *file,
                             llvm::wasm::WasmSymbolType type) {
   error("symbol type mismatch: " + toString(*existing) + "\n>>> defined as " +
@@ -192,6 +197,8 @@ static bool signatureMatches(FunctionSymbol *existing,
 static void checkGlobalType(const Symbol *existing, const InputFile *file,
                             const WasmGlobalType *newType) {
   if (!isa<GlobalSymbol>(existing)) {
+    if (isBitcodeSymbol(existing))
+      return;
     reportTypeError(existing, file, WASM_SYMBOL_TYPE_GLOBAL);
     return;
   }
@@ -206,12 +213,15 @@ static void checkGlobalType(const Symbol *existing, const InputFile *file,
 
 static void checkTagType(const Symbol *existing, const InputFile *file,
                          const WasmSignature *newSig) {
-  const auto *existingTag = dyn_cast<TagSymbol>(existing);
   if (!isa<TagSymbol>(existing)) {
+    if (isBitcodeSymbol(existing))
+      return;
     reportTypeError(existing, file, WASM_SYMBOL_TYPE_TAG);
     return;
   }
 
+  const auto *existingTag = cast<TagSymbol>(existing);
+
   const WasmSignature *oldSig = existingTag->signature;
   if (*newSig != *oldSig)
     warn("Tag signature mismatch: " + existing->getName() +
@@ -223,6 +233,8 @@ static void checkTagType(const Symbol *existing, const InputFile *file,
 static void checkTableType(const Symbol *existing, const InputFile *file,
                            const WasmTableType *newType) {
   if (!isa<TableSymbol>(existing)) {
+    if (isBitcodeSymbol(existing))
+      return;
     reportTypeError(existing, file, WASM_SYMBOL_TYPE_TABLE);
     return;
   }
@@ -237,7 +249,7 @@ static void checkTableType(const Symbol *existing, const InputFile *file,
 }
 
 static void checkDataType(const Symbol *existing, const InputFile *file) {
-  if (!isa<DataSymbol>(existing))
+  if (!isa<DataSymbol>(existing) && !isBitcodeSymbol(existing))
     reportTypeError(existing, file, WASM_SYMBOL_TYPE_DATA);
 }
 
@@ -511,6 +523,10 @@ Symbol *SymbolTable::addDefinedFunction(StringRef name, uint32_t flags,
 
   auto existingFunction = dyn_cast<FunctionSymbol>(s);
   if (!existingFunction) {
+    if (isBitcodeSymbol(s)) {
+      replaceSym(s);
+      return s;
+    }
     reportTypeError(s, file, WASM_SYMBOL_TYPE_FUNCTION);
     return s;
   }



More information about the llvm-commits mailing list