3535#include " clang/CodeGen/ModuleBuilder.h"
3636#include " clang/Sema/Sema.h"
3737#include " llvm/Analysis/ValueTracking.h"
38+ #include " llvm/IR/CallingConv.h"
39+ #include " llvm/IR/Constant.h"
40+ #include " llvm/IR/Function.h"
3841#include " llvm/IR/GlobalPtrAuthInfo.h"
3942#include " llvm/IR/GlobalValue.h"
4043#include " llvm/Support/Compiler.h"
@@ -220,7 +223,11 @@ IRGenFunction::getDefaultCoroutineAllocatorKind() {
220223 if (isCoroutine ()) {
221224 return CoroAllocatorKind::Malloc;
222225 }
223- return CoroAllocatorKind::Sync;
226+ if (IGM.SwiftCoroCC != llvm::CallingConv::SwiftCoro) {
227+ // If the swiftcorocc isn't available, fall back to malloc.
228+ return CoroAllocatorKind::Malloc;
229+ }
230+ return CoroAllocatorKind::Stack;
224231}
225232
226233llvm::Value *IRGenFunction::getAsyncTask () {
@@ -360,9 +367,10 @@ static llvm::CallingConv::ID getFreestandingConvention(IRGenModule &IGM) {
360367
361368// / Expand the requirements of the given abstract calling convention
362369// / into a "physical" calling convention.
363- llvm::CallingConv::ID irgen::expandCallingConv (IRGenModule &IGM,
364- SILFunctionTypeRepresentation convention,
365- bool isAsync) {
370+ llvm::CallingConv::ID
371+ irgen::expandCallingConv (IRGenModule &IGM,
372+ SILFunctionTypeRepresentation convention, bool isAsync,
373+ bool isCalleeAllocatedCoro) {
366374 switch (convention) {
367375 case SILFunctionTypeRepresentation::CFunctionPointer:
368376 case SILFunctionTypeRepresentation::ObjCMethod:
@@ -379,6 +387,8 @@ llvm::CallingConv::ID irgen::expandCallingConv(IRGenModule &IGM,
379387 case SILFunctionTypeRepresentation::KeyPathAccessorSetter:
380388 case SILFunctionTypeRepresentation::KeyPathAccessorEquals:
381389 case SILFunctionTypeRepresentation::KeyPathAccessorHash:
390+ if (isCalleeAllocatedCoro && !IGM.getOptions ().EmitYieldOnce2AsYieldOnce )
391+ return IGM.SwiftCoroCC ;
382392 if (isAsync)
383393 return IGM.SwiftAsyncCC ;
384394 return getFreestandingConvention (IGM);
@@ -2391,7 +2401,8 @@ Signature SignatureExpansion::getSignature() {
23912401 " C function type without C function info" );
23922402
23932403 auto callingConv =
2394- expandCallingConv (IGM, FnType->getRepresentation (), FnType->isAsync ());
2404+ expandCallingConv (IGM, FnType->getRepresentation (), FnType->isAsync (),
2405+ FnType->isCalleeAllocatedCoroutine ());
23952406
23962407 Signature result;
23972408 result.Type = llvmType;
@@ -5118,6 +5129,40 @@ void irgen::emitYieldManyCoroutineEntry(
51185129 allocFn, deallocFn, {});
51195130}
51205131
5132+ static llvm::Constant *getCoroAllocWrapperFn (IRGenModule &IGM) {
5133+ return IGM.getOrCreateHelperFunction (
5134+ " __swift_coro_alloc_" , IGM.Int8PtrTy ,
5135+ {IGM.CoroAllocatorPtrTy , IGM.SizeTy },
5136+ [](IRGenFunction &IGF) {
5137+ auto parameters = IGF.collectParameters ();
5138+ auto *allocator = parameters.claimNext ();
5139+ auto *size = parameters.claimNext ();
5140+ auto *nullAllocator = IGF.Builder .CreateCmp (
5141+ llvm::CmpInst::Predicate::ICMP_EQ, allocator,
5142+ llvm::ConstantPointerNull::get (
5143+ cast<llvm::PointerType>(allocator->getType ())));
5144+ auto *poplessReturn = IGF.createBasicBlock (" coro.return.popless" );
5145+ auto *normalReturn = IGF.createBasicBlock (" coro.return.normal" );
5146+ IGF.Builder .CreateCondBr (nullAllocator, poplessReturn, normalReturn);
5147+ IGF.Builder .emitBlock (poplessReturn);
5148+ // Emit the dynamic alloca.
5149+ auto *alloca =
5150+ IGF.Builder .IRBuilderBase ::CreateAlloca (IGF.IGM .Int8Ty , size);
5151+ alloca->setAlignment (llvm::Align (MaximumAlignment));
5152+ auto *ret = IGF.Builder .CreateIntrinsic (
5153+ alloca->getType (), llvm::Intrinsic::coro_return, {alloca});
5154+ IGF.Builder .CreateRet (ret);
5155+ IGF.Builder .emitBlock (normalReturn);
5156+ auto *call = IGF.Builder .CreateCall (
5157+ IGF.IGM .getCoroAllocFunctionPointer (), {allocator, size});
5158+ IGF.Builder .CreateRet (call);
5159+ },
5160+ /* setIsNoInline=*/ false ,
5161+ /* forPrologue=*/ false ,
5162+ /* isPerformanceConstraint=*/ false ,
5163+ /* optionalLinkageOverride=*/ nullptr , llvm::CallingConv::SwiftCoro);
5164+ }
5165+
51215166void irgen::emitYieldOnce2CoroutineEntry (
51225167 IRGenFunction &IGF, LinkEntity coroFunction, CanSILFunctionType fnType,
51235168 NativeCCEntryPointArgumentEmission &emission) {
@@ -5126,7 +5171,11 @@ void irgen::emitYieldOnce2CoroutineEntry(
51265171 IGF.IGM .getAddrOfCoroFunctionPointer (coroFunction));
51275172 llvm::Value *allocator = emission.getCoroutineAllocator ();
51285173 IGF.setCoroutineAllocator (allocator);
5129- auto allocFn = IGF.IGM .getOpaquePtr (IGF.IGM .getCoroAllocFn ());
5174+ auto isSwiftCoroCCAvailable =
5175+ IGF.IGM .SwiftCoroCC == llvm::CallingConv::SwiftCoro;
5176+ auto allocFn = IGF.IGM .getOpaquePtr (isSwiftCoroCCAvailable
5177+ ? getCoroAllocWrapperFn (IGF.IGM )
5178+ : IGF.IGM .getCoroAllocFn ());
51305179 auto deallocFn = IGF.IGM .getOpaquePtr (IGF.IGM .getCoroDeallocFn ());
51315180 emitRetconCoroutineEntry (
51325181 IGF, fnType, buffer, llvm::Intrinsic::coro_id_retcon_once_dynamic,
0 commit comments