[clang] clang: enable `swiftasynccall` for Wasm (PR #203330)
Max Desiatov via cfe-commits
cfe-commits at lists.llvm.org
Thu Jun 18 06:33:21 PDT 2026
https://github.com/MaxDesiatov updated https://github.com/llvm/llvm-project/pull/203330
>From 91675e678f24501cbfc581f8c2db7bffe72ebd0e Mon Sep 17 00:00:00 2001
From: Max Desiatov <m_desiatov at apple.com>
Date: Thu, 11 Jun 2026 17:28:40 +0100
Subject: [PATCH 1/2] clang: enable `swiftasynccall` for Wasm
Follow-up to https://github.com/llvm/llvm-project/pull/188296, where in LLVM `swiftasynccall` is lowered to Wasm `return_call` and `return_call_indirect` instructions when tail calls are enabled. This still needed to be enabled at the Clang level in `checkCallingConvention` in `lib/Basic/Targets/WebAssembly.h`.
---
clang/lib/Basic/Targets/WebAssembly.h | 2 +-
clang/test/Sema/wasm-swiftasynccall.c | 11 +++++++++++
2 files changed, 12 insertions(+), 1 deletion(-)
create mode 100644 clang/test/Sema/wasm-swiftasynccall.c
diff --git a/clang/lib/Basic/Targets/WebAssembly.h b/clang/lib/Basic/Targets/WebAssembly.h
index 6085197498163..fa0a2b9b505e0 100644
--- a/clang/lib/Basic/Targets/WebAssembly.h
+++ b/clang/lib/Basic/Targets/WebAssembly.h
@@ -186,7 +186,7 @@ class LLVM_LIBRARY_VISIBILITY WebAssemblyTargetInfo : public TargetInfo {
case CC_Swift:
return CCCR_OK;
case CC_SwiftAsync:
- return CCCR_Error;
+ return HasTailCall ? CCCR_OK : CCCR_Error;
default:
return CCCR_Warning;
}
diff --git a/clang/test/Sema/wasm-swiftasynccall.c b/clang/test/Sema/wasm-swiftasynccall.c
new file mode 100644
index 0000000000000..37061b7cdcaab
--- /dev/null
+++ b/clang/test/Sema/wasm-swiftasynccall.c
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -triple wasm32-unknown-unknown -target-feature +tail-call -fsyntax-only -verify=tail %s
+// RUN: %clang_cc1 -triple wasm32-unknown-unknown -fsyntax-only -verify=notail %s
+
+// tail-no-diagnostics
+
+// With the tail-call feature, swiftasynccall should be accepted on
+// WebAssembly since the backend can lower musttail calls to return_call.
+// Without it, swiftasynccall should be rejected.
+
+// notail-error at +1 {{'swiftasynccall' calling convention is not supported for this target}}
+void __attribute__((swiftasynccall)) async_func(char *__attribute__((swift_async_context)) ctx) {}
>From 67791956da66586c6b3c460d35f150b7e444aecf Mon Sep 17 00:00:00 2001
From: Max Desiatov <m_desiatov at apple.com>
Date: Thu, 18 Jun 2026 14:28:56 +0100
Subject: [PATCH 2/2] clang/wasm-swiftasynccall: add IR and asm codegen tests
---
.../CodeGen/WebAssembly/wasm-swiftasynccall.c | 42 +++++++++++++++++++
clang/test/Sema/wasm-swiftasynccall.c | 5 +--
2 files changed, 44 insertions(+), 3 deletions(-)
create mode 100644 clang/test/CodeGen/WebAssembly/wasm-swiftasynccall.c
diff --git a/clang/test/CodeGen/WebAssembly/wasm-swiftasynccall.c b/clang/test/CodeGen/WebAssembly/wasm-swiftasynccall.c
new file mode 100644
index 0000000000000..991f187aaf5b5
--- /dev/null
+++ b/clang/test/CodeGen/WebAssembly/wasm-swiftasynccall.c
@@ -0,0 +1,42 @@
+// REQUIRES: webassembly-registered-target
+// RUN: %clang_cc1 -no-enable-noundef-analysis -triple wasm32-unknown-unknown \
+// RUN: -target-feature +tail-call -emit-llvm -o - %s | FileCheck %s --check-prefix=IR
+// RUN: %clang_cc1 -triple wasm32-unknown-unknown -target-feature +tail-call \
+// RUN: -S -o - %s | FileCheck %s --check-prefix=ASM
+
+// swiftasynccall uses the swifttailcc CC and musttail calls, which the
+// WebAssembly backend lowers to return_call / return_call_indirect with the
+// tail-call feature. Sema acceptance: Sema/wasm-swiftasynccall.c.
+
+#define SWIFTASYNCCALL __attribute__((swiftasynccall))
+#define ASYNC_CONTEXT __attribute__((swift_async_context))
+
+// Definition uses swifttailcc.
+// IR-LABEL: define {{.*}}swifttailcc void @async_leaf(ptr swiftasync
+SWIFTASYNCCALL void async_leaf(char *ASYNC_CONTEXT ctx) {
+ *ctx += 1;
+}
+
+// Direct tail call lowers to return_call.
+// IR-LABEL: define {{.*}}swifttailcc void @async_direct(ptr swiftasync
+// IR: musttail call swifttailcc void @async_leaf(ptr swiftasync
+// IR-NEXT: ret void
+//
+// ASM-LABEL: async_direct:
+// ASM: return_call async_leaf
+SWIFTASYNCCALL void async_direct(char *ASYNC_CONTEXT ctx) {
+ return async_leaf(ctx);
+}
+
+typedef SWIFTASYNCCALL void (*async_fn_t)(char *ASYNC_CONTEXT);
+
+// Indirect tail call lowers to return_call_indirect.
+// IR-LABEL: define {{.*}}swifttailcc void @async_indirect(ptr
+// IR: musttail call swifttailcc void %{{.*}}(ptr swiftasync
+// IR-NEXT: ret void
+//
+// ASM-LABEL: async_indirect:
+// ASM: return_call_indirect
+SWIFTASYNCCALL void async_indirect(async_fn_t fn, char *ASYNC_CONTEXT ctx) {
+ return fn(ctx);
+}
diff --git a/clang/test/Sema/wasm-swiftasynccall.c b/clang/test/Sema/wasm-swiftasynccall.c
index 37061b7cdcaab..838a9a2e00227 100644
--- a/clang/test/Sema/wasm-swiftasynccall.c
+++ b/clang/test/Sema/wasm-swiftasynccall.c
@@ -3,9 +3,8 @@
// tail-no-diagnostics
-// With the tail-call feature, swiftasynccall should be accepted on
-// WebAssembly since the backend can lower musttail calls to return_call.
-// Without it, swiftasynccall should be rejected.
+// swiftasynccall is accepted only with the tail-call feature, which lets the
+// backend lower its musttail calls to return_call.
// notail-error at +1 {{'swiftasynccall' calling convention is not supported for this target}}
void __attribute__((swiftasynccall)) async_func(char *__attribute__((swift_async_context)) ctx) {}
More information about the cfe-commits
mailing list