[llvm] [WebAssembly] Fix crash when storing externref to globals (PR #178474)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Jan 28 09:54:43 PST 2026
https://github.com/ParkHanbum created https://github.com/llvm/llvm-project/pull/178474
Storing `externref` values to global variables previously caused a selection error because the backend attempted a linear memory store.
This patch implements custom lowering for `ISD::STORE` to convert stores of `externref` values into `WebAssemblyISD::GLOBAL_SET`, ensuring they are correctly updated in the Wasm global space.
Fixes: #141011
>From 51603e5282d892bf8fdff3dd4316709073bffb86 Mon Sep 17 00:00:00 2001
From: Hanbum Park <kese111 at gmail.com>
Date: Thu, 29 Jan 2026 02:51:58 +0900
Subject: [PATCH] [WebAssembly] Fix crash when storing externref to globals
Storing `externref` values to global variables previously caused
a selection error because the backend attempted a linear memory store.
This patch implements custom lowering for `ISD::STORE` to convert
stores of `externref` values into `WebAssemblyISD::GLOBAL_SET`,
ensuring they are correctly updated in the Wasm global space.
Fixes: #141011
---
.../WebAssembly/WebAssemblyISelLowering.cpp | 17 +++++++++++++++++
.../Target/WebAssembly/WebAssemblyInstrInfo.td | 5 +++++
llvm/test/CodeGen/WebAssembly/global-set.ll | 13 +++++++++++++
3 files changed, 35 insertions(+)
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
index 5abf0e8f59d2a..69357c908397b 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
@@ -1824,6 +1824,23 @@ SDValue WebAssemblyTargetLowering::LowerStore(SDValue Op,
"Encountered an unlowerable store to the wasm_var address space",
false);
+ if (Value.getValueType() == MVT::externref) {
+ SDValue Ptr =
+ Base.getOpcode() != WebAssemblyISD::Wrapper ? Base : Base.getOperand(0);
+ auto *GNode = dyn_cast<GlobalAddressSDNode>(Ptr);
+ if (!GNode)
+ report_fatal_error("Cannot store externref to non-global address");
+
+ const GlobalValue *GV = GNode->getGlobal();
+ SDValue TargetGlobal =
+ DAG.getTargetGlobalAddress(GV, DL, Ptr.getValueType());
+ SDValue WrappedPtr =
+ DAG.getNode(WebAssemblyISD::Wrapper, DL, MVT::i32, TargetGlobal);
+
+ return DAG.getNode(WebAssemblyISD::GLOBAL_SET, DL, MVT::Other,
+ SN->getChain(), Value, WrappedPtr);
+ }
+
return Op;
}
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
index 76e94c2ec3d61..839f5e11fe6d2 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
@@ -458,6 +458,11 @@ def : Pat<(i32 (WebAssemblyWrapperREL texternalsym:$addr)),
def : Pat<(i64 (WebAssemblyWrapperREL texternalsym:$addr)),
(CONST_I64 texternalsym:$addr)>, Requires<[IsPIC, HasAddr64]>;
+// Manually define the pattern because 'externref' is not included in the
+// standard RegTypes iteration of the generic loop above.
+def : Pat<(WebAssemblyglobal_set externref:$src, (WebAssemblyWrapper tglobaladdr:$addr)),
+ (GLOBAL_SET_EXTERNREF tglobaladdr:$addr, externref:$src)>,
+ Requires<[HasReferenceTypes]>;
//===----------------------------------------------------------------------===//
// Additional sets of instructions.
//===----------------------------------------------------------------------===//
diff --git a/llvm/test/CodeGen/WebAssembly/global-set.ll b/llvm/test/CodeGen/WebAssembly/global-set.ll
index 4553957ae7588..6c37ba8e7ac1c 100644
--- a/llvm/test/CodeGen/WebAssembly/global-set.ll
+++ b/llvm/test/CodeGen/WebAssembly/global-set.ll
@@ -4,6 +4,19 @@
@i64_global = local_unnamed_addr addrspace(1) global i64 undef
@f32_global = local_unnamed_addr addrspace(1) global float undef
@f64_global = local_unnamed_addr addrspace(1) global double undef
+ at a = global ptr addrspace(10) null
+
+declare ptr addrspace(10) @function_that_gives_me_a_js_object()
+define void @object_store_to_global_ptr() {
+; CHECK-LABEL: object_store_to_global_ptr:
+; CHECK: .functype object_store_to_global_ptr () -> ()
+; CHECK-NEXT: call function_that_gives_me_a_js_object
+; CHECK-NEXT: global.set a
+; CHECK-NEXT: end_function
+ %object = call ptr addrspace(10) @function_that_gives_me_a_js_object()
+ store ptr addrspace(10) %object, ptr @a
+ ret void
+}
define void @set_i32_global(i32 %v) {
; CHECK-LABEL: set_i32_global:
More information about the llvm-commits
mailing list