diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -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)) @@ -3418,6 +3418,7 @@ CXCallingConv_PreserveMost = 14, CXCallingConv_PreserveAll = 15, CXCallingConv_AArch64VectorCall = 16, + CXCallingConv_SwiftAsync = 17, CXCallingConv_Invalid = 100, CXCallingConv_Unexposed = 200 diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -2459,6 +2459,11 @@ let Documentation = [SwiftCallDocs]; } +def SwiftAsyncCall : DeclOrTypeAttr { + let Spellings = [Clang<"swiftasynccall">]; + let Documentation = [SwiftAsyncCallDocs]; +} + def SwiftContext : ParameterABIAttr { let Spellings = [Clang<"swift_context">]; let Documentation = [SwiftContextDocs]; diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -4527,7 +4527,8 @@ 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. @@ -4540,14 +4541,39 @@ }]; } +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. }]; @@ -4592,7 +4618,8 @@ 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 diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3154,7 +3154,8 @@ 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< diff --git a/clang/include/clang/Basic/Features.def b/clang/include/clang/Basic/Features.def --- a/clang/include/clang/Basic/Features.def +++ b/clang/include/clang/Basic/Features.def @@ -93,6 +93,9 @@ FEATURE(thread_sanitizer, LangOpts.Sanitize.has(SanitizerKind::Thread)) FEATURE(dataflow_sanitizer, LangOpts.Sanitize.has(SanitizerKind::DataFlow)) FEATURE(scudo, LangOpts.Sanitize.hasOneOf(SanitizerKind::Scudo)) +FEATURE(swiftasynccc, + PP.getTargetInfo().checkCallingConvention(CC_SwiftAsync) == + clang::TargetInfo::CCCR_OK) // Objective-C features FEATURE(objc_arr, LangOpts.ObjCAutoRefCount) // FIXME: REMOVE? FEATURE(objc_arc, LangOpts.ObjCAutoRefCount) diff --git a/clang/include/clang/Basic/Specifiers.h b/clang/include/clang/Basic/Specifiers.h --- a/clang/include/clang/Basic/Specifiers.h +++ b/clang/include/clang/Basic/Specifiers.h @@ -266,6 +266,7 @@ 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)) @@ -284,6 +285,7 @@ case CC_SpirFunction: case CC_OpenCLKernel: case CC_Swift: + case CC_SwiftAsync: return false; default: return true; diff --git a/clang/include/clang/CodeGen/SwiftCallingConv.h b/clang/include/clang/CodeGen/SwiftCallingConv.h --- a/clang/include/clang/CodeGen/SwiftCallingConv.h +++ b/clang/include/clang/CodeGen/SwiftCallingConv.h @@ -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. // //===----------------------------------------------------------------------===// diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -671,6 +671,7 @@ return cast(MemExpr->getMemberDecl()); // FIXME: Will eventually need to cope with member pointers. + // NOTE: Update makeTailCallIfSwiftAsync on fixing this. return nullptr; } diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -3106,6 +3106,8 @@ return "ms_abi"; case CC_Swift: return "swiftcall"; + case CC_SwiftAsync: + return "swiftasynccall"; } llvm_unreachable("bad calling convention"); } diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -2728,6 +2728,8 @@ // ::= 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 @@ -2747,6 +2749,7 @@ 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; } diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -3142,6 +3142,7 @@ 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"; } @@ -3558,6 +3559,7 @@ case attr::ThisCall: case attr::RegCall: case attr::SwiftCall: + case attr::SwiftAsyncCall: case attr::VectorCall: case attr::AArch64VectorPcs: case attr::Pascal: diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -976,6 +976,9 @@ case CC_Swift: OS << " __attribute__((swiftcall))"; break; + case CC_SwiftAsync: + OS << "__attribute__((swiftasynccall))"; + break; case CC_PreserveMost: OS << " __attribute__((preserve_most))"; break; @@ -1706,6 +1709,7 @@ 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; diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp --- a/clang/lib/Basic/Targets/AArch64.cpp +++ b/clang/lib/Basic/Targets/AArch64.cpp @@ -576,6 +576,7 @@ switch (CC) { case CC_C: case CC_Swift: + case CC_SwiftAsync: case CC_PreserveMost: case CC_PreserveAll: case CC_OpenCLKernel: @@ -850,6 +851,7 @@ case CC_PreserveMost: case CC_PreserveAll: case CC_Swift: + case CC_SwiftAsync: case CC_Win64: return CCCR_OK; default: diff --git a/clang/lib/Basic/Targets/ARM.cpp b/clang/lib/Basic/Targets/ARM.cpp --- a/clang/lib/Basic/Targets/ARM.cpp +++ b/clang/lib/Basic/Targets/ARM.cpp @@ -1138,6 +1138,7 @@ case CC_AAPCS: case CC_AAPCS_VFP: case CC_Swift: + case CC_SwiftAsync: case CC_OpenCLKernel: return CCCR_OK; default: @@ -1217,6 +1218,7 @@ case CC_PreserveMost: case CC_PreserveAll: case CC_Swift: + case CC_SwiftAsync: return CCCR_OK; default: return CCCR_Warning; diff --git a/clang/lib/Basic/Targets/PPC.h b/clang/lib/Basic/Targets/PPC.h --- a/clang/lib/Basic/Targets/PPC.h +++ b/clang/lib/Basic/Targets/PPC.h @@ -454,6 +454,8 @@ switch (CC) { case CC_Swift: return CCCR_OK; + case CC_SwiftAsync: + return CCCR_Error; default: return CCCR_Warning; } diff --git a/clang/lib/Basic/Targets/SystemZ.h b/clang/lib/Basic/Targets/SystemZ.h --- a/clang/lib/Basic/Targets/SystemZ.h +++ b/clang/lib/Basic/Targets/SystemZ.h @@ -143,6 +143,8 @@ case CC_Swift: case CC_OpenCLKernel: return CCCR_OK; + case CC_SwiftAsync: + return CCCR_Error; default: return CCCR_Warning; } diff --git a/clang/lib/Basic/Targets/WebAssembly.h b/clang/lib/Basic/Targets/WebAssembly.h --- a/clang/lib/Basic/Targets/WebAssembly.h +++ b/clang/lib/Basic/Targets/WebAssembly.h @@ -129,6 +129,8 @@ case CC_C: case CC_Swift: return CCCR_OK; + case CC_SwiftAsync: + return CCCR_Error; default: return CCCR_Warning; } diff --git a/clang/lib/Basic/Targets/X86.h b/clang/lib/Basic/Targets/X86.h --- a/clang/lib/Basic/Targets/X86.h +++ b/clang/lib/Basic/Targets/X86.h @@ -357,6 +357,8 @@ case CC_IntelOclBicc: case CC_OpenCLKernel: return CCCR_OK; + case CC_SwiftAsync: + return CCCR_Error; default: return CCCR_Warning; } @@ -717,6 +719,7 @@ switch (CC) { case CC_C: case CC_Swift: + case CC_SwiftAsync: case CC_X86VectorCall: case CC_IntelOclBicc: case CC_Win64: @@ -798,6 +801,7 @@ case CC_PreserveAll: case CC_X86_64SysV: case CC_Swift: + case CC_SwiftAsync: case CC_X86RegCall: case CC_OpenCLKernel: return CCCR_OK; diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -66,6 +66,7 @@ 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; } } @@ -773,7 +774,7 @@ // 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); @@ -4029,11 +4030,11 @@ // later, so we can't check it directly. static bool hasInAllocaArgs(CodeGenModule &CGM, CallingConv ExplicitCC, ArrayRef 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; diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -1314,6 +1314,9 @@ return llvm::dwarf::DW_CC_LLVM_OpenCLKernel; case CC_Swift: return llvm::dwarf::DW_CC_LLVM_Swift; + case CC_SwiftAsync: + // [FIXME: swiftasynccc] Update to SwiftAsync once LLVM support lands. + return llvm::dwarf::DW_CC_LLVM_Swift; case CC_PreserveMost: return llvm::dwarf::DW_CC_LLVM_PreserveMost; case CC_PreserveAll: diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -1176,6 +1176,38 @@ }; } // namespace +/// If we have 'return f(...);', where both caller and callee are SwiftAsync, +/// codegen it as 'tail call ...; ret void;'. +static void makeTailCallIfSwiftAsync(const CallExpr *CE, CGBuilderTy &Builder, + const CGFunctionInfo *CurFnInfo) { + auto calleeQualType = CE->getCallee()->getType(); + const FunctionType *calleeType = nullptr; + if (calleeQualType->isFunctionPointerType() || + calleeQualType->isFunctionReferenceType() || + calleeQualType->isBlockPointerType() || + calleeQualType->isMemberFunctionPointerType()) { + calleeType = calleeQualType->getPointeeType()->castAs(); + } else if (auto *ty = dyn_cast(calleeQualType)) { + calleeType = ty; + } else if (auto CMCE = dyn_cast(CE)) { + if (auto methodDecl = CMCE->getMethodDecl()) { + // getMethodDecl() doesn't handle member pointers at the moment. + calleeType = methodDecl->getType()->castAs(); + } else { + return; + } + } else { + return; + } + if (calleeType->getCallConv() == CallingConv::CC_SwiftAsync && + (CurFnInfo->getASTCallingConvention() == CallingConv::CC_SwiftAsync)) { + auto CI = cast(&Builder.GetInsertBlock()->back()); + CI->setTailCallKind(llvm::CallInst::TCK_MustTail); + Builder.CreateRetVoid(); + Builder.ClearInsertionPoint(); + } +} + /// EmitReturnStmt - Note that due to GCC extensions, this can have an operand /// if the function returns void, or may be missing one if the function returns /// non-void. Fun stuff :). @@ -1234,8 +1266,11 @@ } else if (!ReturnValue.isValid() || (RV && RV->getType()->isVoidType())) { // Make sure not to return anything, but evaluate the expression // for side effects. - if (RV) + if (RV) { EmitAnyExpr(RV); + if (auto *CE = dyn_cast(RV)) + makeTailCallIfSwiftAsync(CE, Builder, CurFnInfo); + } } else if (!RV) { // Do nothing (return value is left uninitialized) } else if (FnRetTy->isReferenceType()) { diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -4561,6 +4561,9 @@ 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; @@ -4725,6 +4728,9 @@ case ParsedAttr::AT_SwiftCall: CC = CC_Swift; break; + case ParsedAttr::AT_SwiftAsyncCall: + CC = CC_SwiftAsync; + break; case ParsedAttr::AT_VectorCall: CC = CC_X86VectorCall; break; @@ -8101,6 +8107,7 @@ 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: diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -117,6 +117,7 @@ case ParsedAttr::AT_RegCall: \ case ParsedAttr::AT_Pascal: \ case ParsedAttr::AT_SwiftCall: \ + case ParsedAttr::AT_SwiftAsyncCall: \ case ParsedAttr::AT_VectorCall: \ case ParsedAttr::AT_AArch64VectorPcs: \ case ParsedAttr::AT_MSABI: \ @@ -2780,16 +2781,21 @@ llvm::function_ref getParamLoc) { assert(EPI.ExtParameterInfos && "shouldn't get here without param infos"); - bool hasCheckedSwiftCall = false; - auto checkForSwiftCC = [&](unsigned paramIndex) { - // Only do this once. - if (hasCheckedSwiftCall) return; - hasCheckedSwiftCall = true; - if (EPI.ExtInfo.getCC() == CC_Swift) return; + bool emittedError = false; + auto actualCC = EPI.ExtInfo.getCC(); + enum class RequiredCC { OnlySwift, SwiftOrSwiftAsync }; + auto checkCompatible = [&](unsigned paramIndex, RequiredCC required) { + bool isCompatible = + (required == RequiredCC::OnlySwift) + ? (actualCC == CC_Swift) + : (actualCC == CC_Swift || actualCC == CC_SwiftAsync); + if (isCompatible || emittedError) + return; S.Diag(getParamLoc(paramIndex), diag::err_swift_param_attr_not_swiftcall) - << getParameterABISpelling(EPI.ExtParameterInfos[paramIndex].getABI()); + << getParameterABISpelling(EPI.ExtParameterInfos[paramIndex].getABI()) + << (required == RequiredCC::OnlySwift); + emittedError = true; }; - for (size_t paramIndex = 0, numParams = paramTypes.size(); paramIndex != numParams; ++paramIndex) { switch (EPI.ExtParameterInfos[paramIndex].getABI()) { @@ -2800,7 +2806,7 @@ // swift_indirect_result parameters must be a prefix of the function // arguments. case ParameterABI::SwiftIndirectResult: - checkForSwiftCC(paramIndex); + checkCompatible(paramIndex, RequiredCC::SwiftOrSwiftAsync); if (paramIndex != 0 && EPI.ExtParameterInfos[paramIndex - 1].getABI() != ParameterABI::SwiftIndirectResult) { @@ -2810,16 +2816,16 @@ continue; case ParameterABI::SwiftContext: - checkForSwiftCC(paramIndex); + checkCompatible(paramIndex, RequiredCC::SwiftOrSwiftAsync); continue; + // SwiftAsyncContext is not limited to swiftasynccall functions. case ParameterABI::SwiftAsyncContext: - // FIXME: might want to require swiftasynccc when it exists continue; // swift_error parameters must be preceded by a swift_context parameter. case ParameterABI::SwiftErrorResult: - checkForSwiftCC(paramIndex); + checkCompatible(paramIndex, RequiredCC::OnlySwift); if (paramIndex == 0 || EPI.ExtParameterInfos[paramIndex - 1].getABI() != ParameterABI::SwiftContext) { @@ -7361,6 +7367,8 @@ return createSimpleAttr(Ctx, Attr); case ParsedAttr::AT_SwiftCall: return createSimpleAttr(Ctx, Attr); + case ParsedAttr::AT_SwiftAsyncCall: + return createSimpleAttr(Ctx, Attr); case ParsedAttr::AT_VectorCall: return createSimpleAttr(Ctx, Attr); case ParsedAttr::AT_AArch64VectorPcs: diff --git a/clang/test/CodeGen/64bit-swiftcall.c b/clang/test/CodeGen/64bit-swiftcall.c --- a/clang/test/CodeGen/64bit-swiftcall.c +++ b/clang/test/CodeGen/64bit-swiftcall.c @@ -6,9 +6,11 @@ // REQUIRES: aarch64-registered-target,x86-registered-target #define SWIFTCALL __attribute__((swiftcall)) +#define SWIFTASYNCCALL __attribute__((swiftasynccall)) #define OUT __attribute__((swift_indirect_result)) #define ERROR __attribute__((swift_error_result)) #define CONTEXT __attribute__((swift_context)) +#define ASYNC_CONTEXT __attribute__((swift_async_context)) // CHECK-DAG: %struct.atomic_padded = type { { %struct.packed, [7 x i8] } } // CHECK-DAG: %struct.packed = type <{ i64, i8 }> @@ -33,9 +35,15 @@ SWIFTCALL void context_1(CONTEXT void *self) {} // CHECK-LABEL: define {{.*}} void @context_1(i8* swiftself +SWIFTASYNCCALL void async_context_1(ASYNC_CONTEXT void *ctx) {} +// CHECK-LABEL: define {{.*}} void @async_context_1(i8* swiftasync + SWIFTCALL void context_2(void *arg0, CONTEXT void *self) {} // CHECK-LABEL: define {{.*}} void @context_2(i8*{{.*}}, i8* swiftself +SWIFTASYNCCALL void async_context_2(void *arg0, ASYNC_CONTEXT void *ctx) {} +// CHECK-LABEL: define {{.*}} void @async_context_2(i8*{{.*}}, i8* swiftasync + SWIFTCALL void context_error_1(CONTEXT int *self, ERROR float **error) {} // CHECK-LABEL: define {{.*}} void @context_error_1(i32* swiftself{{.*}}, float** swifterror %0) // CHECK: [[TEMP:%.*]] = alloca float*, align 8 diff --git a/clang/test/CodeGen/arm-swiftcall.c b/clang/test/CodeGen/arm-swiftcall.c --- a/clang/test/CodeGen/arm-swiftcall.c +++ b/clang/test/CodeGen/arm-swiftcall.c @@ -3,6 +3,7 @@ // RUN: %clang_cc1 -triple armv7k-apple-ios9 -emit-llvm -o - %s | FileCheck %s #define SWIFTCALL __attribute__((swiftcall)) +#define SWIFTASYNCCALL __attribute__((swiftasynccall)) #define OUT __attribute__((swift_indirect_result)) #define ERROR __attribute__((swift_error_result)) #define CONTEXT __attribute__((swift_context)) @@ -26,9 +27,15 @@ SWIFTCALL void context_1(CONTEXT void *self) {} // CHECK-LABEL: define{{.*}} void @context_1(i8* swiftself +SWIFTASYNCCALL void async_context_1(ASYNC_CONTEXT void *self) {} +// CHECK-LABEL: define{{.*}} void @async_context_1(i8* swiftasync + SWIFTCALL void context_2(void *arg0, CONTEXT void *self) {} // CHECK-LABEL: define{{.*}} void @context_2(i8*{{.*}}, i8* swiftself +SWIFTASYNCCALL void async_context_2(void *arg0, ASYNC_CONTEXT void *self) {} +// CHECK-LABEL: define{{.*}} void @async_context_2(i8*{{.*}}, i8* swiftasync + SWIFTCALL void context_error_1(CONTEXT int *self, ERROR float **error) {} // CHECK-LABEL: define{{.*}} void @context_error_1(i32* swiftself{{.*}}, float** swifterror %0) // CHECK: [[TEMP:%.*]] = alloca float*, align 4 @@ -54,9 +61,6 @@ SWIFTCALL void context_error_2(short s, CONTEXT int *self, ERROR float **error) {} // CHECK-LABEL: define{{.*}} void @context_error_2(i16{{.*}}, i32* swiftself{{.*}}, float** swifterror %0) -SWIFTCALL void async_context_1(ASYNC_CONTEXT void *self) {} -// CHECK-LABEL: define {{.*}} void @async_context_1(i8* swiftasync - /*****************************************************************************/ /********************************** LOWERING *********************************/ /*****************************************************************************/ diff --git a/clang/test/CodeGen/debug-info-cc.c b/clang/test/CodeGen/debug-info-cc.c --- a/clang/test/CodeGen/debug-info-cc.c +++ b/clang/test/CodeGen/debug-info-cc.c @@ -19,6 +19,7 @@ // 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)) // }; @@ -56,6 +57,13 @@ return a+b; } +// [FIXME: swiftasynccc] Update debuginfo tag to SwiftAsync once LLVM support lands. +// LINUX: !DISubprogram({{.*}}"add_swiftasynccall", {{.*}}type: ![[FTY:[0-9]+]] +// LINUX: ![[FTY]] = !DISubroutineType({{.*}}cc: DW_CC_LLVM_Swift, +__attribute__((swiftasynccall)) int add_swiftasynccall(int a, int b, int c) { + return a+b+c; +} + // LINUX: !DISubprogram({{.*}}"add_inteloclbicc", {{.*}}type: ![[FTY:[0-9]+]] // LINUX: ![[FTY]] = !DISubroutineType({{.*}}cc: DW_CC_LLVM_IntelOclBicc, __attribute__((intel_ocl_bicc)) int add_inteloclbicc(int a, int b) { diff --git a/clang/test/CodeGen/swift-async-call-conv.c b/clang/test/CodeGen/swift-async-call-conv.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/swift-async-call-conv.c @@ -0,0 +1,184 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -target-cpu core2 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple arm64-apple-ios9 -target-cpu cyclone -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple armv7-apple-darwin9 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple armv7s-apple-ios9 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple armv7k-apple-ios9 -emit-llvm -o - %s | FileCheck %s + +// RUN: %clang_cc1 -x c++ -triple x86_64-apple-darwin10 -target-cpu core2 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CPPONLY +// RUN: %clang_cc1 -x c++ -triple arm64-apple-ios9 -target-cpu cyclone -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CPPONLY +// RUN: %clang_cc1 -x c++ -triple armv7-apple-darwin9 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CPPONLY +// RUN: %clang_cc1 -x c++ -triple armv7s-apple-ios9 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CPPONLY +// RUN: %clang_cc1 -x c++ -triple armv7k-apple-ios9 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CPPONLY + +// Test tail call behavior when a swiftasynccall function is called +// from another swiftasynccall function. + +#define SWIFTCALL __attribute__((swiftcall)) +#define SWIFTASYNCCALL __attribute__((swiftasynccall)) +#define ASYNC_CONTEXT __attribute__((swift_async_context)) + +// CHECK-LABEL: swifttailcc void {{.*}}async_leaf1{{.*}}(i8* swiftasync +SWIFTASYNCCALL void async_leaf1(char * ASYNC_CONTEXT ctx) { + *ctx += 1; +} + +// CHECK-LABEL: swifttailcc void {{.*}}async_leaf2{{.*}}(i8* swiftasync +SWIFTASYNCCALL void async_leaf2(char * ASYNC_CONTEXT ctx) { + *ctx += 2; +} + +#if __cplusplus + #define MYBOOL bool +#else + #define MYBOOL _Bool +#endif + +// CHECK-LABEL: swifttailcc void {{.*}}async_branch{{.*}}i8* swiftasync +// CHECK: musttail call swifttailcc void @{{.*}}async_leaf1 +// CHECK-NEXT: ret void +// CHECK: musttail call swifttailcc void @{{.*}}async_leaf2 +// CHECK-NEXT: ret void +SWIFTASYNCCALL void async_branch(MYBOOL b, char * ASYNC_CONTEXT ctx) { + if (b) { + return async_leaf1(ctx); + } else { + return async_leaf2(ctx); + } +} + +// CHECK-LABEL: swifttailcc void {{.*}}async_not_all_tail +// CHECK-NOT: musttail call swifttailcc void @{{.*}}async_leaf1 +// CHECK: call swifttailcc void @{{.*}}async_leaf1 +// CHECK-NOT: ret void +// CHECK: musttail call swifttailcc void @{{.*}}async_leaf2 +// CHECK-NEXT: ret void +SWIFTASYNCCALL void async_not_all_tail(char * ASYNC_CONTEXT ctx) { + async_leaf1(ctx); + return async_leaf2(ctx); +} + +// CHECK-LABEL: swifttailcc void {{.*}}async_loop +// CHECK: musttail call swifttailcc void @{{.*}}async_leaf1 +// CHECK-NEXT: ret void +// CHECK: musttail call swifttailcc void @{{.*}}async_leaf2 +// CHECK-NEXT: ret void +// CHECK: musttail call swifttailcc void @{{.*}}async_loop +// CHECK-NEXT: ret void +SWIFTASYNCCALL void async_loop(unsigned u, char * ASYNC_CONTEXT ctx) { + if (u == 0) { + return async_leaf1(ctx); + } else if (u == 1) { + return async_leaf2(ctx); + } + return async_loop(u - 2, ctx); +} + +// Forward-declaration + mutual recursion is okay. + +SWIFTASYNCCALL void async_mutual_loop2(unsigned u, char * ASYNC_CONTEXT ctx); + +// CHECK-LABEL: swifttailcc void {{.*}}async_mutual_loop1 +// CHECK: musttail call swifttailcc void @{{.*}}async_leaf1 +// CHECK-NEXT: ret void +// CHECK: musttail call swifttailcc void @{{.*}}async_leaf2 +// CHECK-NEXT: ret void +// There is some bugginess around FileCheck's greediness/matching, +// so skipping the check for async_mutual_loop2 here. +SWIFTASYNCCALL void async_mutual_loop1(unsigned u, char * ASYNC_CONTEXT ctx) { + if (u == 0) { + return async_leaf1(ctx); + } else if (u == 1) { + return async_leaf2(ctx); + } + return async_mutual_loop2(u - 2, ctx); +} + +// CHECK-LABEL: swifttailcc void {{.*}}async_mutual_loop2 +// CHECK: musttail call swifttailcc void @{{.*}}async_leaf1 +// CHECK-NEXT: ret void +// CHECK: musttail call swifttailcc void @{{.*}}async_leaf2 +// CHECK-NEXT: ret void +// CHECK: musttail call swifttailcc void @{{.*}}async_mutual_loop1 +// CHECK-NEXT: ret void +SWIFTASYNCCALL void async_mutual_loop2(unsigned u, char * ASYNC_CONTEXT ctx) { + if (u == 0) { + return async_leaf1(ctx); + } else if (u == 1) { + return async_leaf2(ctx); + } + return async_mutual_loop1(u - 2, ctx); +} + +// When swiftasynccall functions are called by non-swiftasynccall functions, +// the call isn't marked as a tail call. + +// CHECK-LABEL: swiftcc i8 {{.*}}sync_calling_async +// CHECK-NOT: tail call +// CHECK: call swifttailcc void @{{.*}}async_branch +// CHECK-NOT: tail call +// CHECK: call swifttailcc void @{{.*}}async_loop +SWIFTCALL char sync_calling_async(MYBOOL b, unsigned u) { + char x = 'a'; + async_branch(b, &x); + async_loop(u, &x); + return x; +} + +// CHECK-LABEL: i8 {{.*}}c_calling_async +// CHECK-NOT: tail call +// CHECK: call swifttailcc void @{{.*}}async_branch +// CHECK-NOT: tail call +// CHECK: call swifttailcc void @{{.*}}async_loop +char c_calling_async(MYBOOL b, unsigned u) { + char x = 'a'; + async_branch(b, &x); + async_loop(u, &x); + return x; +} + +#if __cplusplus +struct S { + SWIFTASYNCCALL void (*fptr)(char * ASYNC_CONTEXT); + + SWIFTASYNCCALL void async_leaf_method(char * ASYNC_CONTEXT ctx) { + *ctx += 1; + } + SWIFTASYNCCALL void async_nonleaf_method1(char * ASYNC_CONTEXT ctx) { + return async_leaf_method(ctx); + } + SWIFTASYNCCALL void async_nonleaf_method2(char * ASYNC_CONTEXT ctx) { + return this->async_leaf_method(ctx); + } +}; + +SWIFTASYNCCALL void (S::*async_leaf_method_ptr)(char * ASYNC_CONTEXT) = &S::async_leaf_method; + +// CPPONLY-LABEL: swifttailcc void {{.*}}async_struct_field_and_methods +// CPPONLY: musttail call swifttailcc void %{{[0-9]+}} +// CPPONLY: musttail call swifttailcc void @{{.*}}async_nonleaf_method1 +// CPPONLY: musttail call swifttailcc void %{{[0-9]+}} +// CPPONLY: musttail call swifttailcc void @{{.*}}async_nonleaf_method2 +// CPPONLY-NOT: musttail call swifttailcc void @{{.*}}async_leaf_method +// ^ TODO: Member pointers should also work. +SWIFTASYNCCALL void async_struct_field_and_methods(int i, S &sref, S *sptr) { + char x = 'a'; + if (i == 0) { + return (*sref.fptr)(&x); + } else if (i == 1) { + return sref.async_nonleaf_method1(&x); + } else if (i == 2) { + return (*(sptr->fptr))(&x); + } else if (i == 3) { + return sptr->async_nonleaf_method2(&x); + } else if (i == 4) { + return (sref.*async_leaf_method_ptr)(&x); + } + return (sptr->*async_leaf_method_ptr)(&x); +} + +// CPPONLY-LABEL: define{{.*}} swifttailcc void @{{.*}}async_nonleaf_method1 +// CPPONLY: musttail call swifttailcc void @{{.*}}async_leaf_method + +// CPPONLY-LABEL: define{{.*}} swifttailcc void @{{.*}}async_nonleaf_method2 +// CPPONLY: musttail call swifttailcc void @{{.*}}async_leaf_method +#endif diff --git a/clang/test/CodeGen/swift-call-conv.c b/clang/test/CodeGen/swift-call-conv.c --- a/clang/test/CodeGen/swift-call-conv.c +++ b/clang/test/CodeGen/swift-call-conv.c @@ -1,5 +1,4 @@ // RUN: %clang_cc1 -triple aarch64-unknown-windows-msvc -emit-llvm %s -o - | FileCheck %s -// RUN: %clang_cc1 -triple thumbv7-unknown-windows-msvc -emit-llvm %s -o - | FileCheck %s // RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -emit-llvm %s -o - | FileCheck %s // REQUIRES: aarch64-registered-target,arm-registered-target,x86-registered-target @@ -7,3 +6,5 @@ void __attribute__((__swiftcall__)) f(void) {} // CHECK-LABEL: define dso_local swiftcc void @f() +void __attribute__((__swiftasynccall__)) f_async(void) {} +// CHECK-LABEL: define dso_local swifttailcc void @f_async() diff --git a/clang/test/Sema/attr-c2x.c b/clang/test/Sema/attr-c2x.c --- a/clang/test/Sema/attr-c2x.c +++ b/clang/test/Sema/attr-c2x.c @@ -16,6 +16,8 @@ void context_okay(void *context [[clang::swift_context]]) [[clang::swiftcall]]; void context_okay2(void *context [[clang::swift_context]], void *selfType, char **selfWitnessTable) [[clang::swiftcall]]; +void context_async_okay(void *context [[clang::swift_async_context]]) [[clang::swiftasynccall]]; +void context_async_okay2(void *context [[clang::swift_async_context]], void *selfType, char **selfWitnessTable) [[clang::swiftasynccall]]; [[clang::ownership_returns(foo)]] void *f1(void); [[clang::ownership_returns(foo)]] void *f2(); // expected-warning {{'ownership_returns' attribute only applies to non-K&R-style functions}} diff --git a/clang/test/Sema/attr-swiftcall.c b/clang/test/Sema/attr-swiftcall.c --- a/clang/test/Sema/attr-swiftcall.c +++ b/clang/test/Sema/attr-swiftcall.c @@ -2,22 +2,30 @@ // RUN: %clang_cc1 -triple x86_64-unknown-windows -fsyntax-only -verify %s #define SWIFTCALL __attribute__((swiftcall)) +#define SWIFTASYNCCALL __attribute__((swiftasynccall)) #define INDIRECT_RESULT __attribute__((swift_indirect_result)) #define ERROR_RESULT __attribute__((swift_error_result)) #define CONTEXT __attribute__((swift_context)) #define ASYNC_CONTEXT __attribute__((swift_async_context)) int notAFunction SWIFTCALL; // expected-warning {{'swiftcall' only applies to function types; type here is 'int'}} +int notAnAsyncFunction SWIFTASYNCCALL; // expected-warning {{'swiftasynccall' only applies to function types; type here is 'int'}} void variadic(int x, ...) SWIFTCALL; // expected-error {{variadic function cannot use swiftcall calling convention}} +void variadic_async(int x, ...) SWIFTASYNCCALL; // expected-error {{variadic function cannot use swiftasynccall calling convention}} void unprototyped() SWIFTCALL; // expected-error {{function with no prototype cannot use the swiftcall calling convention}} +void unprototyped_async() SWIFTASYNCCALL; // expected-error {{function with no prototype cannot use the swiftasynccall calling convention}} void multiple_ccs(int x) SWIFTCALL __attribute__((vectorcall)); // expected-error {{vectorcall and swiftcall attributes are not compatible}} +void multiple_ccs_async(int x) SWIFTASYNCCALL __attribute__((vectorcall)); // expected-error {{vectorcall and swiftasynccall attributes are not compatible}} void (*functionPointer)(void) SWIFTCALL; +void (*asyncFunctionPointer)(void) SWIFTASYNCCALL; -void indirect_result_nonswift(INDIRECT_RESULT void *out); // expected-error {{'swift_indirect_result' parameter can only be used with swiftcall calling convention}} +void indirect_result_nonswift(INDIRECT_RESULT void *out); // expected-error {{'swift_indirect_result' parameter can only be used with swiftcall or swiftasynccall calling convention}} void indirect_result_bad_position(int first, INDIRECT_RESULT void *out) SWIFTCALL; // expected-error {{'swift_indirect_result' parameters must be first parameters of function}} void indirect_result_bad_type(INDIRECT_RESULT int out) SWIFTCALL; // expected-error {{'swift_indirect_result' parameter must have pointer type; type here is 'int'}} void indirect_result_single(INDIRECT_RESULT void *out) SWIFTCALL; void indirect_result_multiple(INDIRECT_RESULT void *out1, INDIRECT_RESULT void *out2) SWIFTCALL; +void indirect_result_single_async(INDIRECT_RESULT void *out) SWIFTASYNCCALL; +void indirect_result_multiple_async(INDIRECT_RESULT void *out1, INDIRECT_RESULT void *out2) SWIFTASYNCCALL; void error_result_nonswift(ERROR_RESULT void **error); // expected-error {{'swift_error_result' parameter can only be used with swiftcall calling convention}} expected-error{{'swift_error_result' parameter must follow 'swift_context' parameter}} void error_result_bad_position2(int first, ERROR_RESULT void **error) SWIFTCALL; // expected-error {{'swift_error_result' parameter must follow 'swift_context' parameter}} @@ -26,10 +34,12 @@ void error_result_okay(int a, int b, CONTEXT void *context, ERROR_RESULT void **error) SWIFTCALL; void error_result_okay2(CONTEXT void *context, ERROR_RESULT void **error, void *selfType, char **selfWitnessTable) SWIFTCALL; -void context_nonswift(CONTEXT void *context); // expected-error {{'swift_context' parameter can only be used with swiftcall calling convention}} +void context_nonswift(CONTEXT void *context); // expected-error {{'swift_context' parameter can only be used with swiftcall or swiftasynccall calling convention}} void context_bad_type(CONTEXT int context) SWIFTCALL; // expected-error {{'swift_context' parameter must have pointer type; type here is 'int'}} void context_okay(CONTEXT void *context) SWIFTCALL; void context_okay2(CONTEXT void *context, void *selfType, char **selfWitnessTable) SWIFTCALL; +void context_okay_async(CONTEXT void *context) SWIFTASYNCCALL; +void context_okay2_async(CONTEXT void *context, void *selfType, char **selfWitnessTable) SWIFTASYNCCALL; void async_context_okay_for_now(ASYNC_CONTEXT void *context); void async_context_bad_type(ASYNC_CONTEXT int context) SWIFTCALL; // expected-error {{'swift_async_context' parameter must have pointer type; type here is 'int'}} diff --git a/clang/test/Sema/no_callconv.cpp b/clang/test/Sema/no_callconv.cpp --- a/clang/test/Sema/no_callconv.cpp +++ b/clang/test/Sema/no_callconv.cpp @@ -11,6 +11,7 @@ void __attribute__((ms_abi)) funcH() {} // expected-error {{'ms_abi' calling convention is not supported for this target}} void __attribute__((intel_ocl_bicc)) funcJ() {} // expected-error {{'intel_ocl_bicc' calling convention is not supported for this target}} void __attribute__((swiftcall)) funcK() {} // expected-error {{'swiftcall' calling convention is not supported for this target}} +void __attribute__((swiftasynccall)) funcKK() {} // expected-error {{'swiftasynccall' calling convention is not supported for this target}} void __attribute__((pascal)) funcG() {} // expected-error {{'pascal' calling convention is not supported for this target}} void __attribute__((preserve_most)) funcL() {} // expected-error {{'preserve_most' calling convention is not supported for this target}} void __attribute__((preserve_all)) funcM() {} // expected-error {{'preserve_all' calling convention is not supported for this target}} @@ -26,6 +27,7 @@ void __attribute__((ms_abi)) funcH() {} void __attribute__((intel_ocl_bicc)) funcJ() {} void __attribute__((swiftcall)) funcK() {} +void __attribute__((swiftasynccall)) funcKK() {} void __attribute__((preserve_most)) funcL() {} void __attribute__((preserve_all)) funcM() {} diff --git a/clang/test/SemaCXX/attr-swiftcall.cpp b/clang/test/SemaCXX/attr-swiftcall.cpp --- a/clang/test/SemaCXX/attr-swiftcall.cpp +++ b/clang/test/SemaCXX/attr-swiftcall.cpp @@ -1,20 +1,28 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify %s #define SWIFTCALL __attribute__((swiftcall)) +#define SWIFTASYNCCALL __attribute__((swiftasynccall)) #define INDIRECT_RESULT __attribute__((swift_indirect_result)) #define ERROR_RESULT __attribute__((swift_error_result)) #define CONTEXT __attribute__((swift_context)) +#define ASYNC_CONTEXT __attribute__((swift_async_context)) int notAFunction SWIFTCALL; // expected-warning {{'swiftcall' only applies to function types; type here is 'int'}} +int notAnAsyncFunction SWIFTASYNCCALL; // expected-warning {{'swiftasynccall' only applies to function types; type here is 'int'}} void variadic(int x, ...) SWIFTCALL; // expected-error {{variadic function cannot use swiftcall calling convention}} +void variadic_async(int x, ...) SWIFTASYNCCALL; // expected-error {{variadic function cannot use swiftasynccall calling convention}} void multiple_ccs(int x) SWIFTCALL __attribute__((vectorcall)); // expected-error {{vectorcall and swiftcall attributes are not compatible}} +void multiple_ccs_async(int x) SWIFTASYNCCALL __attribute__((vectorcall)); // expected-error {{vectorcall and swiftasynccall attributes are not compatible}} void (*functionPointer)(void) SWIFTCALL; +void (*asyncFunctionPointer)(void) SWIFTASYNCCALL; -void indirect_result_nonswift(INDIRECT_RESULT void *out); // expected-error {{'swift_indirect_result' parameter can only be used with swiftcall calling convention}} +void indirect_result_nonswift(INDIRECT_RESULT void *out); // expected-error {{'swift_indirect_result' parameter can only be used with swiftcall or swiftasynccall calling convention}} void indirect_result_bad_position(int first, INDIRECT_RESULT void *out) SWIFTCALL; // expected-error {{'swift_indirect_result' parameters must be first parameters of function}} void indirect_result_bad_type(INDIRECT_RESULT int out) SWIFTCALL; // expected-error {{'swift_indirect_result' parameter must have pointer type; type here is 'int'}} void indirect_result_single(INDIRECT_RESULT void *out) SWIFTCALL; void indirect_result_multiple(INDIRECT_RESULT void *out1, INDIRECT_RESULT void *out2) SWIFTCALL; +void indirect_result_single_async(INDIRECT_RESULT void *out) SWIFTASYNCCALL; +void indirect_result_multiple_async(INDIRECT_RESULT void *out1, INDIRECT_RESULT void *out2) SWIFTASYNCCALL; void error_result_nonswift(ERROR_RESULT void **error); // expected-error {{'swift_error_result' parameter can only be used with swiftcall calling convention}} expected-error{{'swift_error_result' parameter must follow 'swift_context' parameter}} void error_result_bad_position2(int first, ERROR_RESULT void **error) SWIFTCALL; // expected-error {{'swift_error_result' parameter must follow 'swift_context' parameter}} @@ -23,10 +31,17 @@ void error_result_okay(int a, int b, CONTEXT void *context, ERROR_RESULT void **error) SWIFTCALL; void error_result_okay(CONTEXT void *context, ERROR_RESULT void **error, void *selfType, char **selfWitnessTable) SWIFTCALL; -void context_nonswift(CONTEXT void *context); // expected-error {{'swift_context' parameter can only be used with swiftcall calling convention}} +void context_nonswift(CONTEXT void *context); // expected-error {{'swift_context' parameter can only be used with swiftcall or swiftasynccall calling convention}} void context_bad_type(CONTEXT int context) SWIFTCALL; // expected-error {{'swift_context' parameter must have pointer type; type here is 'int'}} void context_okay(CONTEXT void *context) SWIFTCALL; void context_okay(CONTEXT void *context, void *selfType, char **selfWitnessTable) SWIFTCALL; +void context_okay_async(CONTEXT void *context) SWIFTASYNCCALL; +void context_okay2_async(CONTEXT void *context, void *selfType, char **selfWitnessTable) SWIFTASYNCCALL; + +void async_context_nonswift(ASYNC_CONTEXT void *context); // OK +void async_context_bad_type(ASYNC_CONTEXT int context) SWIFTASYNCCALL; // expected-error {{'swift_async_context' parameter must have pointer type; type here is 'int'}} +void async_context_okay(ASYNC_CONTEXT void *context) SWIFTASYNCCALL; +void async_context_okay(void *someArg, ASYNC_CONTEXT void *context, void *otherArg) SWIFTASYNCCALL; template void indirect_result_temp_okay1(INDIRECT_RESULT T *out) SWIFTCALL; template void indirect_result_temp_okay2(INDIRECT_RESULT T out) SWIFTCALL; // expected-note {{candidate template ignored: substitution failure [with T = int]: 'swift_indirect_result' parameter must have pointer type; type here is 'int'}} diff --git a/clang/tools/libclang/CXType.cpp b/clang/tools/libclang/CXType.cpp --- a/clang/tools/libclang/CXType.cpp +++ b/clang/tools/libclang/CXType.cpp @@ -664,6 +664,7 @@ TCALLINGCONV(AAPCS_VFP); TCALLINGCONV(IntelOclBicc); TCALLINGCONV(Swift); + TCALLINGCONV(SwiftAsync); TCALLINGCONV(PreserveMost); TCALLINGCONV(PreserveAll); case CC_SpirFunction: return CXCallingConv_Unexposed; diff --git a/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h b/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h --- a/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h +++ b/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h @@ -67,7 +67,8 @@ Eabi, Vectorcall, Regcall, - Swift, // Clang-only + Swift, // Clang-only + SwiftAsync, // Clang-only }; enum class ReferenceKind : uint8_t { None, LValueRef, RValueRef }; diff --git a/llvm/lib/Demangle/MicrosoftDemangle.cpp b/llvm/lib/Demangle/MicrosoftDemangle.cpp --- a/llvm/lib/Demangle/MicrosoftDemangle.cpp +++ b/llvm/lib/Demangle/MicrosoftDemangle.cpp @@ -1713,6 +1713,8 @@ return CallingConv::Vectorcall; case 'S': return CallingConv::Swift; + case 'T': + return CallingConv::SwiftAsync; } return CallingConv::None; diff --git a/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp b/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp --- a/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp +++ b/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp @@ -110,6 +110,9 @@ case CallingConv::Swift: OS << "__attribute__((__swiftcall__)) "; break; + case CallingConv::SwiftAsync: + OS << "__attribute__((__swiftasynccall__)) "; + break; default: break; } diff --git a/llvm/lib/Transforms/IPO/MergeFunctions.cpp b/llvm/lib/Transforms/IPO/MergeFunctions.cpp --- a/llvm/lib/Transforms/IPO/MergeFunctions.cpp +++ b/llvm/lib/Transforms/IPO/MergeFunctions.cpp @@ -709,7 +709,10 @@ CallInst *CI = Builder.CreateCall(F, Args); ReturnInst *RI = nullptr; - CI->setTailCall(); + bool isSwiftTailCall = F->getCallingConv() == CallingConv::SwiftTail && + G->getCallingConv() == CallingConv::SwiftTail; + CI->setTailCallKind(isSwiftTailCall ? llvm::CallInst::TCK_MustTail + : llvm::CallInst::TCK_Tail); CI->setCallingConv(F->getCallingConv()); CI->setAttributes(F->getAttributes()); if (H->getReturnType()->isVoidTy()) { diff --git a/llvm/test/Demangle/ms-mangle.test b/llvm/test/Demangle/ms-mangle.test --- a/llvm/test/Demangle/ms-mangle.test +++ b/llvm/test/Demangle/ms-mangle.test @@ -341,6 +341,9 @@ ?swift_func@@YSXXZ ; CHECK: void __attribute__((__swiftcall__)) swift_func(void) +?swift_async_func@@YTXXZ +; CHECK: void __attribute__((__swiftasynccall__)) swift_async_func(void) + ??$fn_tmpl@$1?extern_c_func@@YAXXZ@@YAXXZ ; CHECK: void __cdecl fn_tmpl<&void __cdecl extern_c_func(void)>(void)