[clang] [llvm] [RISCV] Add support for Swift calling conventions and error handling (PR #205469)
Alsey Coleman Miller via cfe-commits
cfe-commits at lists.llvm.org
Tue Jun 23 19:22:16 PDT 2026
https://github.com/colemancda created https://github.com/llvm/llvm-project/pull/205469
Upstream version of https://github.com/swiftlang/llvm-project/pull/5551
>From 5ac4600bcfe16d63660ef1fd2236a55f56270218 Mon Sep 17 00:00:00 2001
From: Alsey Coleman Miller <alseycmiller at gmail.com>
Date: Tue, 23 Jun 2026 22:18:29 -0400
Subject: [PATCH] [RISCV] Add support for Swift calling conventions and error
handling
---
clang/lib/Basic/Targets/RISCV.cpp | 2 +
clang/lib/CodeGen/Targets/RISCV.cpp | 2 +-
llvm/lib/Target/RISCV/RISCVCallingConv.cpp | 41 ++++++++++++++++++---
llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 2 +
llvm/lib/Target/RISCV/RISCVISelLowering.h | 2 +
5 files changed, 43 insertions(+), 6 deletions(-)
diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp
index 6afef3e2c7c48..6d9a56754835f 100644
--- a/clang/lib/Basic/Targets/RISCV.cpp
+++ b/clang/lib/Basic/Targets/RISCV.cpp
@@ -598,6 +598,8 @@ RISCVTargetInfo::checkCallingConvention(CallingConv CC) const {
switch (CC) {
default:
return CCCR_Warning;
+ case CC_Swift:
+ case CC_SwiftAsync:
case CC_C:
case CC_RISCVVectorCall:
case CC_RISCVVLSCall_32:
diff --git a/clang/lib/CodeGen/Targets/RISCV.cpp b/clang/lib/CodeGen/Targets/RISCV.cpp
index bc3be06d176bc..608d980f5ecad 100644
--- a/clang/lib/CodeGen/Targets/RISCV.cpp
+++ b/clang/lib/CodeGen/Targets/RISCV.cpp
@@ -989,7 +989,7 @@ class RISCVTargetCodeGenInfo : public TargetCodeGenInfo {
: TargetCodeGenInfo(
std::make_unique<RISCVABIInfo>(CGT, XLen, FLen, EABI)) {
SwiftInfo =
- std::make_unique<SwiftABIInfo>(CGT, /*SwiftErrorInRegister=*/false);
+ std::make_unique<SwiftABIInfo>(CGT, /*SwiftErrorInRegister=*/true);
}
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
diff --git a/llvm/lib/Target/RISCV/RISCVCallingConv.cpp b/llvm/lib/Target/RISCV/RISCVCallingConv.cpp
index 9853644080161..d24d3bddf76b1 100644
--- a/llvm/lib/Target/RISCV/RISCVCallingConv.cpp
+++ b/llvm/lib/Target/RISCV/RISCVCallingConv.cpp
@@ -377,6 +377,9 @@ static bool CC_RISCV_Impl(unsigned ValNo, MVT ValVT, MVT LocVT,
unsigned XLen = Subtarget.getXLen();
MVT XLenVT = Subtarget.getXLenVT();
+ RISCVABI::ABI ABI = Subtarget.getTargetABI();
+ bool IsEABI = ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E;
+
if (ArgFlags.isNest()) {
// Static chain parameter must not be passed in normal argument registers,
// so we assign t2/t3 for it as done in GCC's
@@ -387,9 +390,7 @@ static bool CC_RISCV_Impl(unsigned ValNo, MVT ValVT, MVT LocVT,
// Normal: t2, Branch control flow protection: t3
const auto StaticChainReg = HasCFBranch ? RISCV::X28 : RISCV::X7;
- RISCVABI::ABI ABI = Subtarget.getTargetABI();
- if (HasCFBranch &&
- (ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E))
+ if (HasCFBranch && IsEABI)
reportFatalUsageError(
"Nested functions with control flow protection are not "
"usable with ILP32E or LP64E ABI.");
@@ -399,6 +400,38 @@ static bool CC_RISCV_Impl(unsigned ValNo, MVT ValVT, MVT LocVT,
}
}
+ // Swift calling convention special registers. Use callee-saved s-registers
+ // so they survive across call boundaries without extra save/restore overhead.
+ // X18(s2)=SwiftSelf, X19(s3)=SwiftError, X20(s4)=SwiftAsync, X21(s5)=SwiftCoro.
+ // X18-X21 exceed the 16-register limit of RVE; fall through to normal
+ // allocation on E-variant ABIs.
+ if (LocVT == XLenVT && !IsEABI) {
+ if (ArgFlags.isSwiftSelf()) {
+ if (MCRegister Reg = State.AllocateReg(RISCV::X18)) {
+ State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
+ return false;
+ }
+ }
+ if (ArgFlags.isSwiftError()) {
+ if (MCRegister Reg = State.AllocateReg(RISCV::X19)) {
+ State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
+ return false;
+ }
+ }
+ if (ArgFlags.isSwiftAsync()) {
+ if (MCRegister Reg = State.AllocateReg(RISCV::X20)) {
+ State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
+ return false;
+ }
+ }
+ if (ArgFlags.isSwiftCoro()) {
+ if (MCRegister Reg = State.AllocateReg(RISCV::X21)) {
+ State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
+ return false;
+ }
+ }
+ }
+
// Any return value split in to more than two values can't be returned
// directly. Vectors are returned via the available vector registers.
if ((!LocVT.isVector() || Subtarget.isPExtPackedType(LocVT)) && IsRet &&
@@ -414,8 +447,6 @@ static bool CC_RISCV_Impl(unsigned ValNo, MVT ValVT, MVT LocVT,
bool AllowFPRForF16_F32 = false;
// UseFPRForF64 if targeting an FLEN>=64 ABI and the argument isn't variadic.
bool AllowFPRForF64 = false;
-
- RISCVABI::ABI ABI = Subtarget.getTargetABI();
switch (ABI) {
default:
llvm_unreachable("Unexpected ABI");
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 7a2b9611683c6..4d1ca19ed91ef 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -24753,6 +24753,8 @@ SDValue RISCVTargetLowering::LowerFormalArguments(
default:
reportFatalUsageError("Unsupported calling convention");
case CallingConv::C:
+ case CallingConv::Swift:
+ case CallingConv::SwiftTail:
case CallingConv::Fast:
case CallingConv::PreserveMost:
case CallingConv::GRAAL:
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h
index 4e7912ed815dd..410acb9885c59 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.h
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h
@@ -453,6 +453,8 @@ class RISCVTargetLowering : public TargetLowering {
bool supportKCFIBundles() const override { return true; }
+ bool supportSwiftError() const override { return true; }
+
SDValue expandIndirectJTBranch(const SDLoc &dl, SDValue Value, SDValue Addr,
int JTI, SelectionDAG &DAG) const override;
More information about the cfe-commits
mailing list