[clang] [llvm] [clang][PowerPC] Support the Swift calling convention on 32-bit PowerPC (PR #213447)
Alsey Coleman Miller via llvm-commits
llvm-commits at lists.llvm.org
Sat Aug 1 06:29:50 PDT 2026
https://github.com/colemancda created https://github.com/llvm/llvm-project/pull/213447
`PPC64TargetInfo` accepts `CC_Swift`, but `PPC32TargetInfo` overrides `checkCallingConvention` nowhere, so 32-bit targets inherit the base implementation that accepts only `CC_C`. Sema drops `swiftcall` with `-Wignored-attributes` and substitutes the default convention, and every `swift_context` parameter then fails:
```
error: 'swift_context' parameter can only be used with swiftcall or
swiftasynccall calling convention
```
This mirrors the 64-bit table for `PPC32TargetInfo`, registers a `SwiftABIInfo` in `PPC32TargetCodeGenInfo`, and lets `LowerCall_32SVR4` accept `CallingConv::Swift` rather than assert "Unknown calling convention!" on it.
The convention is lowered like the C convention, and `SwiftErrorInRegister` is false so the error is passed indirectly - no separate argument assignment is required.
`CC_SwiftAsync` stays refused, exactly as on PPC64.
Found while building the Swift standard library for 32-bit PowerPC with Buildroot.
>From bf8951892158757c8a4eb21364018062e487026c Mon Sep 17 00:00:00 2001
From: Alsey Coleman Miller <alseycmiller at gmail.com>
Date: Sat, 1 Aug 2026 09:28:25 -0400
Subject: [PATCH] [clang][PowerPC] Support the Swift calling convention on
32-bit PowerPC
PPC64TargetInfo accepts CC_Swift, but PPC32TargetInfo does not override
checkCallingConvention at all, so 32-bit targets inherit the base
implementation accepting only CC_C: swiftcall is dropped with a warning
and every swift_context parameter then fails to compile. Mirror the
64-bit table, register a SwiftABIInfo for CodeGen, and let
LowerCall_32SVR4 accept the convention instead of asserting on it.
CC_SwiftAsync stays refused, as on PPC64.
---
clang/lib/Basic/Targets/PPC.h | 12 +++++++++++
clang/lib/CodeGen/Targets/PPC.cpp | 5 ++++-
clang/test/Sema/ppc32-swiftcall.c | 18 ++++++++++++++++
llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 6 +++---
llvm/test/CodeGen/PowerPC/swiftcc.ll | 24 +++++++++++++++++++++
5 files changed, 61 insertions(+), 4 deletions(-)
create mode 100644 clang/test/Sema/ppc32-swiftcall.c
create mode 100644 llvm/test/CodeGen/PowerPC/swiftcc.ll
diff --git a/clang/lib/Basic/Targets/PPC.h b/clang/lib/Basic/Targets/PPC.h
index 22880e5a04a3f..e3d5a0fb99364 100644
--- a/clang/lib/Basic/Targets/PPC.h
+++ b/clang/lib/Basic/Targets/PPC.h
@@ -432,6 +432,18 @@ class LLVM_LIBRARY_VISIBILITY PPC32TargetInfo : public PPCTargetInfo {
return TargetInfo::PowerABIBuiltinVaList;
}
+ CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
+ switch (CC) {
+ case CC_C:
+ case CC_Swift:
+ return CCCR_OK;
+ case CC_SwiftAsync:
+ return CCCR_Error;
+ default:
+ return CCCR_Warning;
+ }
+ }
+
std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override {
return std::make_pair(32, 32);
}
diff --git a/clang/lib/CodeGen/Targets/PPC.cpp b/clang/lib/CodeGen/Targets/PPC.cpp
index 5109567212adb..785fdc4555470 100644
--- a/clang/lib/CodeGen/Targets/PPC.cpp
+++ b/clang/lib/CodeGen/Targets/PPC.cpp
@@ -388,7 +388,10 @@ class PPC32TargetCodeGenInfo : public TargetCodeGenInfo {
PPC32TargetCodeGenInfo(CodeGenTypes &CGT, bool SoftFloatABI,
bool RetSmallStructInRegABI)
: TargetCodeGenInfo(std::make_unique<PPC32_SVR4_ABIInfo>(
- CGT, SoftFloatABI, RetSmallStructInRegABI)) {}
+ CGT, SoftFloatABI, RetSmallStructInRegABI)) {
+ SwiftInfo =
+ std::make_unique<SwiftABIInfo>(CGT, /*SwiftErrorInRegister=*/false);
+ }
static bool isStructReturnInRegABI(const llvm::Triple &Triple,
const CodeGenOptions &Opts);
diff --git a/clang/test/Sema/ppc32-swiftcall.c b/clang/test/Sema/ppc32-swiftcall.c
new file mode 100644
index 0000000000000..76dcbcecd3721
--- /dev/null
+++ b/clang/test/Sema/ppc32-swiftcall.c
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -triple powerpc-unknown-linux-gnu -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple powerpcle-unknown-linux-gnu -fsyntax-only -verify %s
+
+// swiftcall is supported on 32-bit PowerPC, matching the 64-bit target;
+// swiftasynccall is not, for the same reason it is refused there.
+
+void __attribute__((swiftcall)) f(void *__attribute__((swift_context)) ctx) {}
+
+#if !__has_extension(swiftcc)
+#error swiftcc should be available on 32-bit PowerPC
+#endif
+
+#if __has_extension(swiftasynccc)
+#error swiftasynccc should not be available on 32-bit PowerPC
+#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/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index 1a80d0a05655a..2623f9600fb7c 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -5980,9 +5980,9 @@ SDValue PPCTargetLowering::LowerCall_32SVR4(
const bool IsVarArg = CFlags.IsVarArg;
const bool IsTailCall = CFlags.IsTailCall;
- assert((CallConv == CallingConv::C ||
- CallConv == CallingConv::Cold ||
- CallConv == CallingConv::Fast) && "Unknown calling convention!");
+ assert((CallConv == CallingConv::C || CallConv == CallingConv::Cold ||
+ CallConv == CallingConv::Fast || CallConv == CallingConv::Swift) &&
+ "Unknown calling convention!");
const Align PtrAlign(4);
diff --git a/llvm/test/CodeGen/PowerPC/swiftcc.ll b/llvm/test/CodeGen/PowerPC/swiftcc.ll
new file mode 100644
index 0000000000000..06e679861c176
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/swiftcc.ll
@@ -0,0 +1,24 @@
+; RUN: llc -mtriple=powerpc-unknown-linux-gnu -verify-machineinstrs < %s | FileCheck %s
+
+; swiftcc is lowered like the C convention on 32-bit PowerPC. Check that it
+; is accepted at all: LowerCall_32SVR4 used to assert on it.
+
+define swiftcc i32 @swiftcc_param(i32 %a, i32 %b) {
+; CHECK-LABEL: swiftcc_param:
+; CHECK: blr
+ %r = add i32 %a, %b
+ ret i32 %r
+}
+
+define swiftcc i32 @call_swiftcc(i32 %a, i32 %b) {
+; CHECK-LABEL: call_swiftcc:
+; CHECK: bl 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: blr
+ ret ptr %addr
+}
More information about the llvm-commits
mailing list