[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