@@ -5118,39 +5118,59 @@ void irgen::emitYieldManyCoroutineEntry(
51185118 allocFn, deallocFn, {});
51195119}
51205120
5121- static llvm::Constant *getCoroAllocWrapperFn (IRGenModule &IGM) {
5121+ static llvm::Constant *getCoroAllocFn (IRGenModule &IGM) {
5122+ auto isSwiftCoroCCAvailable = IGM.SwiftCoroCC == llvm::CallingConv::SwiftCoro;
51225123 return IGM.getOrCreateHelperFunction (
5123- " __swift_coro_alloc_" , IGM.Int8PtrTy ,
5124- {IGM.CoroAllocatorPtrTy , IGM.SizeTy },
5125- [](IRGenFunction &IGF) {
5124+ " _swift_coro_alloc" , IGM.Int8PtrTy , {IGM.CoroAllocatorPtrTy , IGM.SizeTy },
5125+ [isSwiftCoroCCAvailable](IRGenFunction &IGF) {
51265126 auto parameters = IGF.collectParameters ();
51275127 auto *allocator = parameters.claimNext ();
51285128 auto *size = parameters.claimNext ();
5129- auto *nullAllocator = IGF.Builder .CreateCmp (
5130- llvm::CmpInst::Predicate::ICMP_EQ, allocator,
5131- llvm::ConstantPointerNull::get (
5132- cast<llvm::PointerType>(allocator->getType ())));
5133- auto *poplessReturn = IGF.createBasicBlock (" coro.return.popless" );
5134- auto *normalReturn = IGF.createBasicBlock (" coro.return.normal" );
5135- IGF.Builder .CreateCondBr (nullAllocator, poplessReturn, normalReturn);
5136- IGF.Builder .emitBlock (poplessReturn);
5137- // Emit the dynamic alloca.
5138- auto *alloca =
5139- IGF.Builder .IRBuilderBase ::CreateAlloca (IGF.IGM .Int8Ty , size);
5140- alloca->setAlignment (llvm::Align (MaximumAlignment));
5141- auto *retPopless = IGF.Builder .CreateIntrinsic (
5142- IGF.IGM .VoidTy , llvm::Intrinsic::ret_popless, {});
5143- retPopless->setTailCallKind (llvm::CallInst::TailCallKind::TCK_MustTail);
5144- IGF.Builder .CreateRet (alloca);
5145- IGF.Builder .emitBlock (normalReturn);
5146- auto *call = IGF.Builder .CreateCall (
5147- IGF.IGM .getCoroAllocFunctionPointer (), {allocator, size});
5129+ if (isSwiftCoroCCAvailable) {
5130+ // swiftcorocc is available, so if there's no allocator pointer,
5131+ // allocate storage on the stack and return a pointer to it without
5132+ // popping the stack.
5133+ auto *nullAllocator = IGF.Builder .CreateCmp (
5134+ llvm::CmpInst::Predicate::ICMP_EQ, allocator,
5135+ llvm::ConstantPointerNull::get (
5136+ cast<llvm::PointerType>(allocator->getType ())));
5137+ auto *poplessReturn = IGF.createBasicBlock (" popless" );
5138+ auto *normalReturn = IGF.createBasicBlock (" normal" );
5139+ IGF.Builder .CreateCondBr (nullAllocator, poplessReturn, normalReturn);
5140+ IGF.Builder .emitBlock (poplessReturn);
5141+ // Emit the dynamic alloca.
5142+ auto *alloca =
5143+ IGF.Builder .IRBuilderBase ::CreateAlloca (IGF.IGM .Int8Ty , size);
5144+ alloca->setAlignment (llvm::Align (MaximumAlignment));
5145+ auto *retPopless = IGF.Builder .CreateIntrinsic (
5146+ IGF.IGM .VoidTy , llvm::Intrinsic::ret_popless, {});
5147+ retPopless->setTailCallKind (
5148+ llvm::CallInst::TailCallKind::TCK_MustTail);
5149+ IGF.Builder .CreateRet (alloca);
5150+ // Start emitting the "normal" block.
5151+ IGF.Builder .emitBlock (normalReturn);
5152+ }
5153+ auto *calleePtr = IGF.Builder .CreateInBoundsGEP (
5154+ IGF.IGM .CoroAllocatorTy , allocator,
5155+ {llvm::ConstantInt::get (IGF.IGM .Int32Ty , 0 ),
5156+ llvm::ConstantInt::get (IGF.IGM .Int32Ty , 1 )});
5157+ auto *callee = IGF.Builder .CreateLoad (
5158+ Address (calleePtr, IGF.IGM .CoroAllocateFnTy ->getPointerTo (),
5159+ IGF.IGM .getPointerAlignment ()),
5160+ " allocate_fn" );
5161+ auto fnPtr = FunctionPointer::createUnsigned (
5162+ FunctionPointer::Kind::Function, callee,
5163+ Signature (cast<llvm::FunctionType>(IGF.IGM .CoroAllocateFnTy ), {},
5164+ IGF.IGM .SwiftCC ));
5165+ auto *call = IGF.Builder .CreateCall (fnPtr, {size});
5166+ call->setDoesNotThrow ();
5167+ call->setCallingConv (IGF.IGM .SwiftCC );
51485168 IGF.Builder .CreateRet (call);
51495169 },
5150- /* setIsNoInline=*/ false ,
5170+ /* setIsNoInline=*/ true ,
51515171 /* forPrologue=*/ false ,
51525172 /* isPerformanceConstraint=*/ false ,
5153- /* optionalLinkageOverride=*/ nullptr , llvm::CallingConv::SwiftCoro );
5173+ /* optionalLinkageOverride=*/ nullptr , IGM. SwiftCoroCC );
51545174}
51555175
51565176static llvm::Constant *getCoroDeallocWrapperFn (IRGenModule &IGM) {
@@ -5190,9 +5210,7 @@ void irgen::emitYieldOnce2CoroutineEntry(IRGenFunction &IGF,
51905210 IGF.setCoroutineAllocator (allocator);
51915211 auto isSwiftCoroCCAvailable =
51925212 IGF.IGM .SwiftCoroCC == llvm::CallingConv::SwiftCoro;
5193- auto allocFn = IGF.IGM .getOpaquePtr (isSwiftCoroCCAvailable
5194- ? getCoroAllocWrapperFn (IGF.IGM )
5195- : IGF.IGM .getCoroAllocFn ());
5213+ auto allocFn = IGF.IGM .getOpaquePtr (getCoroAllocFn (IGF.IGM ));
51965214 auto deallocFn = IGF.IGM .getOpaquePtr (isSwiftCoroCCAvailable
51975215 ? getCoroDeallocWrapperFn (IGF.IGM )
51985216 : IGF.IGM .getCoroDeallocFn ());
0 commit comments