[llvm] [WebAssembly] Define `__funcref_call_table` in generated asm and objects (PR #180900)

via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 11 00:37:46 PST 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-webassembly

Author: Demetrius Kanios (QuantumSegfault)

<details>
<summary>Changes</summary>

Currently, calls into funcref (`call addrspace(20)`) are lowered into a store of the ref into a special single-element `__funcref_call_table`, a call_indirect into said table, then a store of null into it.

It functions just fine when `-filetype=asm` (default), but when emitting an object file directly from llc it fails with `LLVM ERROR: undefined table symbol cannot be weak`

This fixes said error by "defining" it during `WebAssemblyAsmPrinter`, and ensuring it is definitely emitted as weak (so duplicate tables in multiple objects are merged into a single one).

---
Full diff: https://github.com/llvm/llvm-project/pull/180900.diff


2 Files Affected:

- (modified) llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp (+16) 
- (modified) llvm/test/CodeGen/WebAssembly/funcref-call.ll (+1) 


``````````diff
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
index 1cacdb04fa74d..afe834b077909 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
@@ -392,6 +392,22 @@ void WebAssemblyAsmPrinter::emitEndOfAsmFile(Module &M) {
   // emitDecls() is not called until now.
   emitDecls(M);
 
+  {
+    StringRef Name = "__funcref_call_table";
+    auto *Sym = static_cast<MCSymbolWasm *>(OutContext.lookupSymbol(Name));
+    if (Sym) {
+      if (!Sym->isFunctionTable())
+        OutContext.reportError(SMLoc(), "symbol is not a wasm funcref table");
+
+      if (Sym->isWeak()) {
+        OutStreamer->emitSymbolAttribute(Sym, MCSA_Weak);
+      }
+      if (!Sym->isDefined()) {
+        OutStreamer->emitLabel(Sym);
+        OutStreamer->addBlankLine();
+      }
+    }
+  }
   // When a function's address is taken, a TABLE_INDEX relocation is emitted
   // against the function symbol at the use site.  However the relocation
   // doesn't explicitly refer to the table.  In the future we may want to
diff --git a/llvm/test/CodeGen/WebAssembly/funcref-call.ll b/llvm/test/CodeGen/WebAssembly/funcref-call.ll
index 9904df2280e81..4f6025de4759c 100644
--- a/llvm/test/CodeGen/WebAssembly/funcref-call.ll
+++ b/llvm/test/CodeGen/WebAssembly/funcref-call.ll
@@ -1,6 +1,7 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
 ; RUN: llc < %s --mtriple=wasm32-unknown-unknown -fast-isel=0 -mattr=+reference-types | FileCheck %s
 ; RUN: llc < %s --mtriple=wasm32-unknown-unknown -fast-isel=1 -mattr=+reference-types | FileCheck %s
+; RUN: llc < %s --mtriple=wasm32-unknown-unknown --filetype=obj
 
 %funcref = type ptr addrspace(20) ;; addrspace 20 is nonintegral
 

``````````

</details>


https://github.com/llvm/llvm-project/pull/180900


More information about the llvm-commits mailing list