[llvm] [WebAssembly] Define `__funcref_call_table` in generated asm and objects (PR #180900)
Demetrius Kanios via llvm-commits
llvm-commits at lists.llvm.org
Wed Feb 11 00:37:14 PST 2026
https://github.com/QuantumSegfault created https://github.com/llvm/llvm-project/pull/180900
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).
>From 80479a78a5128012ec0b09f780bea1d8710337f4 Mon Sep 17 00:00:00 2001
From: Demetrius Kanios <demetrius at kanios.net>
Date: Wed, 11 Feb 2026 00:26:33 -0800
Subject: [PATCH] Define `__funcref_call_table` in generated asm and objects
---
.../Target/WebAssembly/WebAssemblyAsmPrinter.cpp | 16 ++++++++++++++++
llvm/test/CodeGen/WebAssembly/funcref-call.ll | 1 +
2 files changed, 17 insertions(+)
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
More information about the llvm-commits
mailing list