Skip to content

Swift-next Cherry-pick: Swift async calling conventions #3060

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion clang/include/clang-c/Index.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
* compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable.
*/
#define CINDEX_VERSION_MAJOR 0
#define CINDEX_VERSION_MINOR 61
#define CINDEX_VERSION_MINOR 62

#define CINDEX_VERSION_ENCODE(major, minor) (((major)*10000) + ((minor)*1))

Expand Down Expand Up @@ -3418,6 +3418,7 @@ enum CXCallingConv {
CXCallingConv_PreserveMost = 14,
CXCallingConv_PreserveAll = 15,
CXCallingConv_AArch64VectorCall = 16,
CXCallingConv_SwiftAsync = 17,

CXCallingConv_Invalid = 100,
CXCallingConv_Unexposed = 200
Expand Down
5 changes: 5 additions & 0 deletions clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -2513,6 +2513,11 @@ def SwiftCall : DeclOrTypeAttr {
let Documentation = [SwiftCallDocs];
}

def SwiftAsyncCall : DeclOrTypeAttr {
let Spellings = [Clang<"swiftasynccall">];
let Documentation = [SwiftAsyncCallDocs];
}

def SwiftContext : ParameterABIAttr {
let Spellings = [Clang<"swift_context">];
let Documentation = [SwiftContextDocs];
Expand Down
39 changes: 33 additions & 6 deletions clang/include/clang/Basic/AttrDocs.td
Original file line number Diff line number Diff line change
Expand Up @@ -4686,7 +4686,8 @@ def SwiftContextDocs : Documentation {
let Category = DocCatVariable;
let Content = [{
The ``swift_context`` attribute marks a parameter of a ``swiftcall``
function as having the special context-parameter ABI treatment.
or ``swiftasynccall`` function as having the special context-parameter
ABI treatment.

This treatment generally passes the context value in a special register
which is normally callee-preserved.
Expand All @@ -4699,14 +4700,39 @@ A context parameter must have pointer or reference type.
}];
}

def SwiftAsyncCallDocs : Documentation {
let Category = DocCatVariable;
let Content = [{
The ``swiftasynccall`` attribute indicates that a function is
compatible with the low-level conventions of Swift async functions,
provided it declares the right formal arguments.

In most respects, this is similar to the ``swiftcall`` attribute, except for
the following:
- A parameter may be marked ``swift_async_context``, ``swift_context``
or ``swift_indirect_result`` (with the same restrictions on parameter
ordering as ``swiftcall``) but the parameter attribute
``swift_error_result`` is not permitted.
- A ``swiftasynccall`` function must have return type ``void``.
- Within a ``swiftasynccall`` function, a call to a ``swiftasynccall``
function that is the immediate operand of a ``return`` statement is
guaranteed to be performed as a tail call. This syntax is allowed even
in C as an extension (a call to a void-returning function cannot be a
return operand in standard C). If something in the calling function would
semantically be performed after a guaranteed tail call, such as the
non-trivial destruction of a local variable or temporary,
then the program is ill-formed.
}];
}

def SwiftAsyncContextDocs : Documentation {
let Category = DocCatVariable;
let Content = [{
The ``swift_async_context`` attribute marks a parameter as having the
special asynchronous context-parameter ABI treatment.
The ``swift_async_context`` attribute marks a parameter of a ``swiftasynccall``
function as having the special asynchronous context-parameter ABI treatment.

This treatment generally passes the context value in a special register
which is normally callee-preserved.
If the function is not ``swiftasynccall``, this attribute only generates
extended frame information.

A context parameter must have pointer or reference type.
}];
Expand Down Expand Up @@ -4751,7 +4777,8 @@ def SwiftIndirectResultDocs : Documentation {
let Category = DocCatVariable;
let Content = [{
The ``swift_indirect_result`` attribute marks a parameter of a ``swiftcall``
function as having the special indirect-result ABI treatment.
or ``swiftasynccall`` function as having the special indirect-result ABI
treatment.

This treatment gives the parameter the target's normal indirect-result
ABI treatment, which may involve passing it differently from an ordinary
Expand Down
3 changes: 2 additions & 1 deletion clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -3213,7 +3213,8 @@ def warn_nsdictionary_duplicate_key : Warning<
def note_nsdictionary_duplicate_key_here : Note<
"previous equal key is here">;
def err_swift_param_attr_not_swiftcall : Error<
"'%0' parameter can only be used with swiftcall calling convention">;
"'%0' parameter can only be used with swiftcall%select{ or swiftasynccall|}1 "
"calling convention%select{|s}1">;
def err_swift_indirect_result_not_first : Error<
"'swift_indirect_result' parameters must be first parameters of function">;
def err_swift_error_result_not_after_swift_context : Error<
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/Features.def
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ FEATURE(ptrauth_calls, LangOpts.PointerAuthCalls)
FEATURE(ptrauth_returns, LangOpts.PointerAuthReturns)
FEATURE(ptrauth_indirect_gotos, LangOpts.PointerAuthIndirectGotos)
FEATURE(scudo, LangOpts.Sanitize.hasOneOf(SanitizerKind::Scudo))
FEATURE(swiftasynccc, PP.getTargetInfo().isSwiftAsyncCCSupported())
// Objective-C features
FEATURE(objc_arr, LangOpts.ObjCAutoRefCount) // FIXME: REMOVE?
FEATURE(objc_arc, LangOpts.ObjCAutoRefCount)
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/Specifiers.h
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ namespace clang {
CC_SpirFunction, // default for OpenCL functions on SPIR target
CC_OpenCLKernel, // inferred for OpenCL kernels
CC_Swift, // __attribute__((swiftcall))
CC_SwiftAsync, // __attribute__((swiftasynccall))
CC_PreserveMost, // __attribute__((preserve_most))
CC_PreserveAll, // __attribute__((preserve_all))
CC_AArch64VectorCall, // __attribute__((aarch64_vector_pcs))
Expand All @@ -284,6 +285,7 @@ namespace clang {
case CC_SpirFunction:
case CC_OpenCLKernel:
case CC_Swift:
case CC_SwiftAsync:
return false;
default:
return true;
Expand Down
12 changes: 12 additions & 0 deletions clang/include/clang/Basic/TargetInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -1476,6 +1476,18 @@ class TargetInfo : public virtual TransferrableTargetInfo,

virtual CallingConvKind getCallingConvKind(bool ClangABICompat4) const;

/// \brief Is the Swift async calling convention supported for this target.
bool isSwiftAsyncCCSupported() const {
auto &triple = getTriple();
return triple.getArch() == llvm::Triple::x86_64 ||
triple.isARM() ||
triple.isAArch64();
}

CallingConvCheckResult checkSwiftAsyncCCSupported() const {
return isSwiftAsyncCCSupported() ? CCCR_OK : CCCR_Error;
}

/// Controls if __builtin_longjmp / __builtin_setjmp can be lowered to
/// llvm.eh.sjlj.longjmp / llvm.eh.sjlj.setjmp.
virtual bool hasSjLjLowering() const {
Expand Down
3 changes: 2 additions & 1 deletion clang/include/clang/CodeGen/SwiftCallingConv.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
//
//===----------------------------------------------------------------------===//
//
// Defines constants and types related to Swift ABI lowering.
// Defines constants and types related to Swift ABI lowering. The same ABI
// lowering applies to both sync and async functions.
//
//===----------------------------------------------------------------------===//

Expand Down
2 changes: 2 additions & 0 deletions clang/lib/AST/ItaniumMangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3109,6 +3109,8 @@ StringRef CXXNameMangler::getCallingConvQualifierName(CallingConv CC) {
return "ms_abi";
case CC_Swift:
return "swiftcall";
case CC_SwiftAsync:
return "swiftasynccall";
}
llvm_unreachable("bad calling convention");
}
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/AST/MicrosoftMangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2728,6 +2728,8 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(CallingConv CC) {
// ::= J # __export __fastcall
// ::= Q # __vectorcall
// ::= S # __attribute__((__swiftcall__)) // Clang-only
// ::= T # __attribute__((__swiftasynccall__))
// // Clang-only
// ::= w # __regcall
// The 'export' calling conventions are from a bygone era
// (*cough*Win16*cough*) when functions were declared for export with
Expand All @@ -2747,6 +2749,7 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(CallingConv CC) {
case CC_X86FastCall: Out << 'I'; break;
case CC_X86VectorCall: Out << 'Q'; break;
case CC_Swift: Out << 'S'; break;
case CC_SwiftAsync: Out << 'T'; break;
case CC_PreserveMost: Out << 'U'; break;
case CC_X86RegCall: Out << 'w'; break;
}
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/AST/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3139,6 +3139,7 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) {
case CC_SpirFunction: return "spir_function";
case CC_OpenCLKernel: return "opencl_kernel";
case CC_Swift: return "swiftcall";
case CC_SwiftAsync: return "swiftasynccall";
case CC_PreserveMost: return "preserve_most";
case CC_PreserveAll: return "preserve_all";
}
Expand Down Expand Up @@ -3555,6 +3556,7 @@ bool AttributedType::isCallingConv() const {
case attr::ThisCall:
case attr::RegCall:
case attr::SwiftCall:
case attr::SwiftAsyncCall:
case attr::VectorCall:
case attr::AArch64VectorPcs:
case attr::Pascal:
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/AST/TypePrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -980,6 +980,9 @@ void TypePrinter::printFunctionAfter(const FunctionType::ExtInfo &Info,
case CC_Swift:
OS << " __attribute__((swiftcall))";
break;
case CC_SwiftAsync:
OS << "__attribute__((swiftasynccall))";
break;
case CC_PreserveMost:
OS << " __attribute__((preserve_most))";
break;
Expand Down Expand Up @@ -1719,6 +1722,7 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
case attr::StdCall: OS << "stdcall"; break;
case attr::ThisCall: OS << "thiscall"; break;
case attr::SwiftCall: OS << "swiftcall"; break;
case attr::SwiftAsyncCall: OS << "swiftasynccall"; break;
case attr::VectorCall: OS << "vectorcall"; break;
case attr::Pascal: OS << "pascal"; break;
case attr::MSABI: OS << "ms_abi"; break;
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Basic/Targets/AArch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,8 @@ AArch64TargetInfo::checkCallingConvention(CallingConv CC) const {
case CC_AArch64VectorCall:
case CC_Win64:
return CCCR_OK;
case CC_SwiftAsync:
return checkSwiftAsyncCCSupported();
default:
return CCCR_Warning;
}
Expand Down Expand Up @@ -861,6 +863,8 @@ WindowsARM64TargetInfo::checkCallingConvention(CallingConv CC) const {
case CC_Swift:
case CC_Win64:
return CCCR_OK;
case CC_SwiftAsync:
return checkSwiftAsyncCCSupported();
default:
return CCCR_Warning;
}
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Basic/Targets/ARM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1140,6 +1140,8 @@ ARMTargetInfo::checkCallingConvention(CallingConv CC) const {
case CC_Swift:
case CC_OpenCLKernel:
return CCCR_OK;
case CC_SwiftAsync:
return checkSwiftAsyncCCSupported();
default:
return CCCR_Warning;
}
Expand Down Expand Up @@ -1218,6 +1220,8 @@ WindowsARMTargetInfo::checkCallingConvention(CallingConv CC) const {
case CC_PreserveAll:
case CC_Swift:
return CCCR_OK;
case CC_SwiftAsync:
return checkSwiftAsyncCCSupported();
default:
return CCCR_Warning;
}
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Basic/Targets/PPC.h
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,8 @@ class LLVM_LIBRARY_VISIBILITY PPC64TargetInfo : public PPCTargetInfo {
switch (CC) {
case CC_Swift:
return CCCR_OK;
case CC_SwiftAsync:
return checkSwiftAsyncCCSupported();
default:
return CCCR_Warning;
}
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Basic/Targets/SystemZ.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ class LLVM_LIBRARY_VISIBILITY SystemZTargetInfo : public TargetInfo {
case CC_Swift:
case CC_OpenCLKernel:
return CCCR_OK;
case CC_SwiftAsync:
return checkSwiftAsyncCCSupported();
default:
return CCCR_Warning;
}
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Basic/Targets/WebAssembly.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@ class LLVM_LIBRARY_VISIBILITY WebAssemblyTargetInfo : public TargetInfo {
case CC_C:
case CC_Swift:
return CCCR_OK;
case CC_SwiftAsync:
return checkSwiftAsyncCCSupported();
default:
return CCCR_Warning;
}
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/Basic/Targets/X86.h
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,8 @@ class LLVM_LIBRARY_VISIBILITY X86TargetInfo : public TargetInfo {
case CC_IntelOclBicc:
case CC_OpenCLKernel:
return CCCR_OK;
case CC_SwiftAsync:
return checkSwiftAsyncCCSupported();
default:
return CCCR_Warning;
}
Expand Down Expand Up @@ -723,6 +725,8 @@ class LLVM_LIBRARY_VISIBILITY X86_64TargetInfo : public X86TargetInfo {
case CC_X86RegCall:
case CC_OpenCLKernel:
return CCCR_OK;
case CC_SwiftAsync:
return checkSwiftAsyncCCSupported();
default:
return CCCR_Warning;
}
Expand Down Expand Up @@ -799,6 +803,8 @@ class LLVM_LIBRARY_VISIBILITY WindowsX86_64TargetInfo
case CC_X86RegCall:
case CC_OpenCLKernel:
return CCCR_OK;
case CC_SwiftAsync:
return checkSwiftAsyncCCSupported();
default:
return CCCR_Warning;
}
Expand Down
14 changes: 9 additions & 5 deletions clang/lib/CodeGen/CGCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ unsigned CodeGenTypes::ClangCallConvToLLVMCallConv(CallingConv CC) {
case CC_PreserveMost: return llvm::CallingConv::PreserveMost;
case CC_PreserveAll: return llvm::CallingConv::PreserveAll;
case CC_Swift: return llvm::CallingConv::Swift;
case CC_SwiftAsync: return llvm::CallingConv::SwiftTail;
}
}

Expand Down Expand Up @@ -773,7 +774,7 @@ CodeGenTypes::arrangeLLVMFunctionInfo(CanQualType resultType,
// Force target independent argument handling for the host visible
// kernel functions.
computeSPIRKernelABIInfo(CGM, *FI);
} else if (info.getCC() == CC_Swift) {
} else if (info.getCC() == CC_Swift || info.getCC() == CC_SwiftAsync) {
swiftcall::computeABIInfo(CGM, *FI);
} else {
getABIInfo().computeInfo(*FI);
Expand Down Expand Up @@ -4035,11 +4036,11 @@ void CodeGenFunction::EmitNonNullArgCheck(RValue RV, QualType ArgType,
// later, so we can't check it directly.
static bool hasInAllocaArgs(CodeGenModule &CGM, CallingConv ExplicitCC,
ArrayRef<QualType> ArgTypes) {
// The Swift calling convention doesn't go through the target-specific
// argument classification, so it never uses inalloca.
// The Swift calling conventions don't go through the target-specific
// argument classification, they never use inalloca.
// TODO: Consider limiting inalloca use to only calling conventions supported
// by MSVC.
if (ExplicitCC == CC_Swift)
if (ExplicitCC == CC_Swift || ExplicitCC == CC_SwiftAsync)
return false;
if (!CGM.getTarget().getCXXABI().isMicrosoft())
return false;
Expand Down Expand Up @@ -5306,10 +5307,13 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
if (CGM.getLangOpts().ObjCAutoRefCount)
AddObjCARCExceptionMetadata(CI);

// Set tail call kind if necessary.
// Adjust tail call behavior based on TargetDecl's attributes and CallInfo.
if (llvm::CallInst *Call = dyn_cast<llvm::CallInst>(CI)) {
if (TargetDecl && TargetDecl->hasAttr<NotTailCalledAttr>())
Call->setTailCallKind(llvm::CallInst::TCK_NoTail);
else if (CallInfo.getASTCallingConvention() == CC_SwiftAsync &&
CurFnInfo->getASTCallingConvention() == CC_SwiftAsync)
Call->setTailCallKind(llvm::CallInst::TCK_Tail);
else if (IsMustTail)
Call->setTailCallKind(llvm::CallInst::TCK_MustTail);
}
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/CodeGen/CGDebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1319,6 +1319,8 @@ static unsigned getDwarfCC(CallingConv CC) {
return llvm::dwarf::DW_CC_LLVM_OpenCLKernel;
case CC_Swift:
return llvm::dwarf::DW_CC_LLVM_Swift;
case CC_SwiftAsync:
return llvm::dwarf::DW_CC_LLVM_SwiftTail;
case CC_PreserveMost:
return llvm::dwarf::DW_CC_LLVM_PreserveMost;
case CC_PreserveAll:
Expand Down
7 changes: 7 additions & 0 deletions clang/lib/Sema/SemaDeclAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4570,6 +4570,9 @@ static void handleCallConvAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
case ParsedAttr::AT_SwiftCall:
D->addAttr(::new (S.Context) SwiftCallAttr(S.Context, AL));
return;
case ParsedAttr::AT_SwiftAsyncCall:
D->addAttr(::new (S.Context) SwiftAsyncCallAttr(S.Context, AL));
return;
case ParsedAttr::AT_VectorCall:
D->addAttr(::new (S.Context) VectorCallAttr(S.Context, AL));
return;
Expand Down Expand Up @@ -4734,6 +4737,9 @@ bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC,
case ParsedAttr::AT_SwiftCall:
CC = CC_Swift;
break;
case ParsedAttr::AT_SwiftAsyncCall:
CC = CC_SwiftAsync;
break;
case ParsedAttr::AT_VectorCall:
CC = CC_X86VectorCall;
break;
Expand Down Expand Up @@ -8110,6 +8116,7 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case ParsedAttr::AT_Pascal:
case ParsedAttr::AT_RegCall:
case ParsedAttr::AT_SwiftCall:
case ParsedAttr::AT_SwiftAsyncCall:
case ParsedAttr::AT_VectorCall:
case ParsedAttr::AT_MSABI:
case ParsedAttr::AT_SysVABI:
Expand Down
Loading