[clang] [llvm] [clang][RISCV] Support the Swift calling convention (PR #213448)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Aug 1 06:59:50 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-risc-v
Author: Alsey Coleman Miller (colemancda)
<details>
<summary>Changes</summary>
`RISCVTargetCodeGenInfo` already registers a `SwiftABIInfo`, so RISC-V looks like it supports the Swift calling convention, but nothing ever reaches CodeGen: `RISCVTargetInfo::checkCallingConvention` does not accept `CC_Swift`, so sema drops the attribute and substitutes the default convention. Every `swift_context` parameter then fails:
```
error: 'swift_context' parameter can only be used with swiftcall or
swiftasynccall calling convention
```
Reproducer:
```
echo '__attribute__((swiftcall)) void f(__attribute__((swift_context)) void *c);' > sc.c
clang -target riscv64-unknown-linux-gnu -fsyntax-only sc.c
```
Past sema, `RISCVTargetLowering::LowerFormalArguments` has no case for `CallingConv::Swift` and reports "Unsupported calling convention".
This accepts `CC_Swift` and lowers it. It needs no separate argument assignment: `CC_RISCV` is what the C convention already uses, and `SwiftErrorInRegister` is false, so the error is passed indirectly rather than pinned to a register.
`CC_SwiftAsync` is refused, as `SystemZTargetInfo` and `PPC64TargetInfo` refuse it - lowering it needs guaranteed tail calls the backend does not provide. Since `__has_extension(swiftasynccc)` is derived from this check, callers fall back to `swiftcall` rather than emitting a convention with no lowering.
`clang/test/Sema/swift-call-conv.c` asserted that RISC-V supports neither convention; that line is replaced by a dedicated test covering both.
Found while building the Swift standard library for riscv64 with Buildroot. Supersedes the RISC-V half of https://github.com/swiftlang/llvm-project/pull/5551, which was filed against the Swift fork.
---
Full diff: https://github.com/llvm/llvm-project/pull/213448.diff
5 Files Affected:
- (modified) clang/lib/Basic/Targets/RISCV.cpp (+3)
- (added) clang/test/Sema/riscv-swiftcall.c (+18)
- (modified) clang/test/Sema/swift-call-conv.c (-2)
- (modified) llvm/lib/Target/RISCV/RISCVISelLowering.cpp (+1)
- (added) llvm/test/CodeGen/RISCV/swiftcc.ll (+26)
``````````diff
diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp
index 6afef3e2c7c48..801cfe9e60cd1 100644
--- a/clang/lib/Basic/Targets/RISCV.cpp
+++ b/clang/lib/Basic/Targets/RISCV.cpp
@@ -612,7 +612,10 @@ RISCVTargetInfo::checkCallingConvention(CallingConv CC) const {
case CC_RISCVVLSCall_16384:
case CC_RISCVVLSCall_32768:
case CC_RISCVVLSCall_65536:
+ case CC_Swift:
return CCCR_OK;
+ case CC_SwiftAsync:
+ return CCCR_Error;
}
}
diff --git a/clang/test/Sema/riscv-swiftcall.c b/clang/test/Sema/riscv-swiftcall.c
new file mode 100644
index 0000000000000..e9ebbbef91745
--- /dev/null
+++ b/clang/test/Sema/riscv-swiftcall.c
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -triple riscv32-unknown-elf -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple riscv64-unknown-linux-gnu -fsyntax-only -verify %s
+
+// swiftcall is supported on RISC-V; swiftasynccall is not, because lowering
+// it needs guaranteed tail calls the backend does not provide.
+
+void __attribute__((swiftcall)) f(void *__attribute__((swift_context)) ctx) {}
+
+#if !__has_extension(swiftcc)
+#error swiftcc should be available on RISC-V
+#endif
+
+#if __has_extension(swiftasynccc)
+#error swiftasynccc should not be available on RISC-V
+#endif
+
+// expected-error at +1 {{'swiftasynccall' calling convention is not supported for this target}}
+void __attribute__((swiftasynccall)) g(void *__attribute__((swift_async_context)) ctx) {}
diff --git a/clang/test/Sema/swift-call-conv.c b/clang/test/Sema/swift-call-conv.c
index 2c9be84055848..42351f7e85d61 100644
--- a/clang/test/Sema/swift-call-conv.c
+++ b/clang/test/Sema/swift-call-conv.c
@@ -1,8 +1,6 @@
// RUN: %clang_cc1 -triple aarch64-unknown-windows-msvc -fsyntax-only %s -verify
// RUN: %clang_cc1 -triple thumbv7-unknown-windows-msvc -fsyntax-only %s -verify
// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -fsyntax-only %s -verify
-// RISC-V does not support swiftcall
-// RUN: %clang_cc1 -triple riscv32-unknown-elf -fsyntax-only %s -verify
#if __has_extension(swiftcc)
// expected-no-diagnostics
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index aad62e7d40c54..99b908f2ea6b9 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -25738,6 +25738,7 @@ SDValue RISCVTargetLowering::LowerFormalArguments(
case CallingConv::PreserveMost:
case CallingConv::GRAAL:
case CallingConv::RISCV_VectorCall:
+ case CallingConv::Swift:
#define CC_VLS_CASE(ABI_VLEN) case CallingConv::RISCV_VLSCall_##ABI_VLEN:
CC_VLS_CASE(32)
CC_VLS_CASE(64)
diff --git a/llvm/test/CodeGen/RISCV/swiftcc.ll b/llvm/test/CodeGen/RISCV/swiftcc.ll
new file mode 100644
index 0000000000000..0d505fd4d5862
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/swiftcc.ll
@@ -0,0 +1,26 @@
+; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s | FileCheck %s
+; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s | FileCheck %s
+
+; swiftcc is lowered like the C convention on RISC-V. Check that it is
+; accepted at all: LowerFormalArguments used to reject it with
+; "Unsupported calling convention".
+
+define swiftcc i32 @swiftcc_param(i32 %a, i32 %b) {
+; CHECK-LABEL: swiftcc_param:
+; CHECK: ret
+ %r = add i32 %a, %b
+ ret i32 %r
+}
+
+define swiftcc i32 @call_swiftcc(i32 %a, i32 %b) {
+; CHECK-LABEL: call_swiftcc:
+; CHECK: call swiftcc_param
+ %r = call swiftcc i32 @swiftcc_param(i32 %a, i32 %b)
+ ret i32 %r
+}
+
+define swiftcc ptr @swiftself_param(ptr swiftself %addr) {
+; CHECK-LABEL: swiftself_param:
+; CHECK: ret
+ ret ptr %addr
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/213448
More information about the llvm-commits
mailing list