[llvm] [WebAssembly] Fix null Subtarget crash for addrspace(1) globals (PR #181536)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Feb 16 04:05:00 PST 2026
https://github.com/ParkHanbum updated https://github.com/llvm/llvm-project/pull/181536
>From 2f1555badaffb78e3d27f886eeaab3b63d2c3175 Mon Sep 17 00:00:00 2001
From: hanbeom <kese111 at gmail.com>
Date: Sun, 15 Feb 2026 17:12:50 +0900
Subject: [PATCH 1/3] [WebAssembly] Fix null Subtarget crash for addrspace(1)
globals
If Subtarget is null during global emission, it is now retrieved
from TargetMachine to prevent crashes caused by empty VTs in
wasmSymbolSetType.
Fixed: #181527
---
.../Target/WebAssembly/WebAssemblyAsmPrinter.cpp | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
index 1cacdb04fa74d..a088b67a5eedc 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
@@ -197,16 +197,22 @@ void WebAssemblyAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {
if (!Sym->getType()) {
SmallVector<MVT, 1> VTs;
Type *GlobalVT = GV->getValueType();
- if (Subtarget) {
+ if (!Subtarget) {
// Subtarget is only set when a function is defined, because
// each function can declare a different subtarget. For example,
// on ARM a compilation unit might have a function on ARM and
// another on Thumb. Therefore only if Subtarget is non-null we
- // can actually calculate the legal VTs.
- const WebAssemblyTargetLowering &TLI = *Subtarget->getTargetLowering();
- computeLegalValueVTs(TLI, GV->getParent()->getContext(),
- GV->getDataLayout(), GlobalVT, VTs);
+ // can actually calculate the legal VTs. Therefore, if Subtarget
+ // is null, we retrieve the default subtarget from TargetMachine
+ // to calculate the legal VTs.
+ auto &WasmTM = static_cast<const WebAssemblyTargetMachine &>(TM);
+ Subtarget = WasmTM.getSubtargetImpl();
}
+
+ const WebAssemblyTargetLowering &TLI = *Subtarget->getTargetLowering();
+ computeLegalValueVTs(TLI, GV->getParent()->getContext(),
+ GV->getDataLayout(), GlobalVT, VTs);
+
WebAssembly::wasmSymbolSetType(Sym, GlobalVT, VTs);
}
>From 75bda2ef40422224420e2647f15031a4bd52fa8e Mon Sep 17 00:00:00 2001
From: Hanbum Park <kese111 at gmail.com>
Date: Sun, 15 Feb 2026 21:19:03 +0900
Subject: [PATCH 2/3] add test
---
.../CodeGen/WebAssembly/global-addrspace.ll | 20 +++++++++++++++++++
1 file changed, 20 insertions(+)
create mode 100644 llvm/test/CodeGen/WebAssembly/global-addrspace.ll
diff --git a/llvm/test/CodeGen/WebAssembly/global-addrspace.ll b/llvm/test/CodeGen/WebAssembly/global-addrspace.ll
new file mode 100644
index 0000000000000..c0dd5ff56c8e7
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/global-addrspace.ll
@@ -0,0 +1,20 @@
+; RUN: llc < %s -mtriple=wasm32-unknown-unknown | FileCheck %s
+
+;; This test ensures that globals in addrspace(1) (Wasm-specific variables)
+;; do not cause a crash during emission when Subtarget is not set
+;; (e.g., in modules without functions) and correctly emit their initializers.
+
+; CHECK-LABEL: .globaltype wasm_var, i32
+; CHECK-NEXT: .globl wasm_var
+; CHECK-NEXT: wasm_var:
+ at wasm_var = addrspace(1) global i32 42
+
+; CHECK-LABEL: .globaltype wasm_var_float, f32
+; CHECK-NEXT: .globl wasm_var_float
+; CHECK-NEXT: wasm_var_float:
+ at wasm_var_float = addrspace(1) global float 0x40091EB860000000
+
+; CHECK-LABEL: .globaltype wasm_var_i64, i64
+; CHECK-NEXT: .globl wasm_var_i64
+; CHECK-NEXT: wasm_var_i64:
+ at wasm_var_i64 = addrspace(1) global i64 1234567890
>From 6c82979a54dba020e46173e8b9c2c7033203b637 Mon Sep 17 00:00:00 2001
From: hanbeom <kese111 at gmail.com>
Date: Mon, 16 Feb 2026 21:03:55 +0900
Subject: [PATCH 3/3] comment change
---
.../Target/WebAssembly/WebAssemblyAsmPrinter.cpp | 13 ++++++-------
1 file changed, 6 insertions(+), 7 deletions(-)
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
index a088b67a5eedc..4c978a326d674 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
@@ -198,13 +198,12 @@ void WebAssemblyAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {
SmallVector<MVT, 1> VTs;
Type *GlobalVT = GV->getValueType();
if (!Subtarget) {
- // Subtarget is only set when a function is defined, because
- // each function can declare a different subtarget. For example,
- // on ARM a compilation unit might have a function on ARM and
- // another on Thumb. Therefore only if Subtarget is non-null we
- // can actually calculate the legal VTs. Therefore, if Subtarget
- // is null, we retrieve the default subtarget from TargetMachine
- // to calculate the legal VTs.
+ // Subtarget is typically set when a function is processed. In modules
+ // with only global variables (no functions), Subtarget remains null.
+ // Unlike architectures that support per-function subtargets (e.g., ARM
+ // vs Thumb), WebAssembly features are coalesced module-wide before ISel.
+ // Therefore, if Subtarget is null, it is safe to retrieve the default
+ // Subtarget from TargetMachine to calculate legal VTs.
auto &WasmTM = static_cast<const WebAssemblyTargetMachine &>(TM);
Subtarget = WasmTM.getSubtargetImpl();
}
More information about the llvm-commits
mailing list