[llvm-branch-commits] [clang] release/23.x: [WebAssembly] Add funclet bundle to thread local wrapper calls (#213826) (PR #218805)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Tue Aug 25 15:56:58 PDT 2026
https://github.com/llvmbot created https://github.com/llvm/llvm-project/pull/218805
Backport 73817e6a9279833e53fb9ccca3158ed987c4ad61
Requested by: @aheejin
>From fd25fa40a31cbb0758afbae26857d19ecf742076 Mon Sep 17 00:00:00 2001
From: Heejin Ahn <aheejin at gmail.com>
Date: Mon, 3 Aug 2026 22:19:32 -0700
Subject: [PATCH] [WebAssembly] Add funclet bundle to thread local wrapper
calls (#213826)
When accessing a thread local variable, Clang generates a thread local
wrapper function that checks if the variable has been initialized, and
if it isn't, initializes it. This is a function call, so if this is
within a funclet (i.e., within a `catchpad` or `cleanuppad`), it needs
the funclet bundle argument, which was missing before. If it lacks a
funclet argument, it will be considered invalid and removed in
WinEHPrepare.
Fixes https://github.com/emscripten-core/emscripten/issues/27448.
(cherry picked from commit 73817e6a9279833e53fb9ccca3158ed987c4ad61)
---
clang/lib/CodeGen/ItaniumCXXABI.cpp | 3 ++-
clang/test/CodeGenCXX/wasm-eh.cpp | 32 +++++++++++++++++++++++++++--
2 files changed, 32 insertions(+), 3 deletions(-)
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index b17478cb7ffde..2f43eb6e13185 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -3441,7 +3441,8 @@ LValue ItaniumCXXABI::EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF,
llvm::Value *Val = CGF.CGM.GetAddrOfGlobalVar(VD);
llvm::Function *Wrapper = getOrCreateThreadLocalWrapper(VD, Val);
- llvm::CallInst *CallVal = CGF.Builder.CreateCall(Wrapper);
+ llvm::CallInst *CallVal =
+ CGF.Builder.CreateCall(Wrapper, {}, CGF.getBundlesForFunclet(Wrapper));
CallVal->setCallingConv(Wrapper->getCallingConv());
LValue LV;
diff --git a/clang/test/CodeGenCXX/wasm-eh.cpp b/clang/test/CodeGenCXX/wasm-eh.cpp
index f243f37ecb435..0b87107e476c7 100644
--- a/clang/test/CodeGenCXX/wasm-eh.cpp
+++ b/clang/test/CodeGenCXX/wasm-eh.cpp
@@ -41,7 +41,7 @@ void multiple_catches_wo_catch_all() {
// CHECK-NEXT: %[[EXN:.*]] = call ptr @llvm.wasm.get.exception(token %[[CATCHPAD]])
// CHECK-NEXT: store ptr %[[EXN]], ptr %exn.slot
// CHECK-NEXT: %[[SELECTOR:.*]] = call i32 @llvm.wasm.get.ehselector(token %[[CATCHPAD]])
-// CHECK-NEXT: %[[TYPEID:.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIi) #7
+// CHECK-NEXT: %[[TYPEID:.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIi) {{.*}}
// CHECK-NEXT: %[[MATCHES:.*]] = icmp eq i32 %[[SELECTOR]], %[[TYPEID]]
// CHECK-NEXT: br i1 %[[MATCHES]], label %[[CATCH_INT_BB:.*]], label %[[CATCH_FALLTHROUGH_BB:.*]]
@@ -58,7 +58,7 @@ void multiple_catches_wo_catch_all() {
// CHECK-NEXT: br label %[[TRY_CONT_BB:.*]]
// CHECK: [[CATCH_FALLTHROUGH_BB]]
-// CHECK-NEXT: %[[TYPEID:.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTId) #7
+// CHECK-NEXT: %[[TYPEID:.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTId) {{.*}}
// CHECK-NEXT: %[[MATCHES:.*]] = icmp eq i32 %[[SELECTOR]], %[[TYPEID]]
// CHECK-NEXT: br i1 %[[MATCHES]], label %[[CATCH_FLOAT_BB:.*]], label %[[RETHROW_BB:.*]]
@@ -388,6 +388,34 @@ void noexcept_throw() noexcept {
throw 3;
}
+int get_val() { return 42; }
+thread_local int tls = get_val();
+
+// CHECK-LABEL: @_Z26tls_wrapper_within_funcletv()
+// CHECK: %[[CATCHSWITCH:.*]] = catchswitch within none [label %[[CATCHSTART_BB:.*]]] unwind to caller
+
+// CHECK: [[CATCHSTART_BB]]:
+// CHECK-NEXT: %[[CATCHPAD:.*]] = catchpad within %[[CATCHSWITCH]] [ptr null]
+// CHECK-NEXT: %[[EXN:.*]] = call ptr @llvm.wasm.get.exception(token %[[CATCHPAD]])
+// CHECK-NEXT: store ptr %[[EXN]], ptr %exn.slot
+// CHECK-NEXT: {{.*}} call i32 @llvm.wasm.get.ehselector(token %[[CATCHPAD]])
+// CHECK-NEXT: br label %[[CATCH_ALL_BB:.*]]
+
+// CHECK: [[CATCH_ALL_BB]]:
+// CHECK-NEXT: %[[EXN_LOAD:.*]] = load ptr, ptr %exn.slot
+// CHECK-NEXT: call ptr @__cxa_begin_catch(ptr %[[EXN_LOAD]]) {{.*}} [ "funclet"(token %[[CATCHPAD]]) ]
+// CHECK-NEXT: call {{.*}} @_ZTW3tls() [ "funclet"(token %[[CATCHPAD]]) ]
+
+// Thread-local wrapper calls within a funclet should have a catchpad/cleanuppad
+// funclet bundle argument.
+int tls_wrapper_within_funclet() {
+ try {
+ throw 1;
+ } catch (...) {
+ return tls;
+ }
+}
+
// CATCH-LABEL: define void @_Z14noexcept_throwv()
// CHECK: %{{.*}} = cleanuppad within none []
// CHECK-NEXT: call void @_ZSt9terminatev()
More information about the llvm-branch-commits
mailing list