@@ -5118,68 +5118,133 @@ 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
5156- static llvm::Constant *getCoroDeallocWrapperFn (IRGenModule &IGM) {
5176+ static llvm::Constant *getCoroDeallocFn (IRGenModule &IGM) {
5177+ auto isSwiftCoroCCAvailable = IGM.SwiftCoroCC == llvm::CallingConv::SwiftCoro;
51575178 return IGM.getOrCreateHelperFunction (
5158- " __swift_coro_dealloc_ " , IGM.VoidTy ,
5179+ " _swift_coro_dealloc " , IGM.VoidTy ,
51595180 {IGM.CoroAllocatorPtrTy , IGM.Int8PtrTy },
5160- [](IRGenFunction &IGF) {
5181+ [isSwiftCoroCCAvailable ](IRGenFunction &IGF) {
51615182 auto parameters = IGF.collectParameters ();
51625183 auto *allocator = parameters.claimNext ();
51635184 auto *ptr = parameters.claimNext ();
5164- auto *nullAllocator = IGF.Builder .CreateCmp (
5165- llvm::CmpInst::Predicate::ICMP_EQ, allocator,
5166- llvm::ConstantPointerNull::get (
5167- cast<llvm::PointerType>(allocator->getType ())));
5168- auto *bailBlock = IGF.createBasicBlock (" bail" );
5169- auto *forwardBlock = IGF.createBasicBlock (" forward" );
5170- IGF.Builder .CreateCondBr (nullAllocator, bailBlock, forwardBlock);
5171- IGF.Builder .emitBlock (bailBlock);
5172- // Emit the dynamic alloca.
5185+ if (isSwiftCoroCCAvailable) {
5186+ // swiftcorocc is available, so if there's no allocator pointer,
5187+ // storage was allocated on the stack which will be naturally cleaned
5188+ // up when the coroutine's frame is "freed".
5189+ auto *nullAllocator = IGF.Builder .CreateCmp (
5190+ llvm::CmpInst::Predicate::ICMP_EQ, allocator,
5191+ llvm::ConstantPointerNull::get (
5192+ cast<llvm::PointerType>(allocator->getType ())));
5193+ auto *bailBlock = IGF.createBasicBlock (" null_allocator" );
5194+ auto *normalBlock = IGF.createBasicBlock (" nonnull_allocator" );
5195+ IGF.Builder .CreateCondBr (nullAllocator, bailBlock, normalBlock);
5196+ IGF.Builder .emitBlock (bailBlock);
5197+ // Nothing to do here.
5198+ IGF.Builder .CreateRetVoid ();
5199+ // Start emitting the "normal" block.
5200+ IGF.Builder .emitBlock (normalBlock);
5201+ }
5202+ auto shouldDeallocateImmediatelyFlag = CoroAllocatorFlags (0 );
5203+ shouldDeallocateImmediatelyFlag.setShouldDeallocateImmediately (true );
5204+ auto *flagsPtr = IGF.Builder .CreateInBoundsGEP (
5205+ IGF.IGM .CoroAllocatorTy , allocator,
5206+ {llvm::ConstantInt::get (IGF.IGM .Int32Ty , 0 ),
5207+ llvm::ConstantInt::get (IGF.IGM .Int32Ty , 0 )});
5208+ auto *flags = IGF.Builder .CreateLoad (
5209+ Address (flagsPtr, IGF.IGM .Int32Ty , Alignment (4 )), " " );
5210+ auto *deallocDeferringAllocator = IGF.Builder .CreateAnd (
5211+ flags,
5212+ llvm::APInt (IGF.IGM .Int32Ty ->getBitWidth (),
5213+ shouldDeallocateImmediatelyFlag.getOpaqueValue ()));
5214+ auto *isDeallocDeferringAllocator = IGF.Builder .CreateICmpNE (
5215+ deallocDeferringAllocator,
5216+ llvm::ConstantInt::get (IGF.IGM .Int32Ty , 0 ));
5217+ auto *deferringAllocatorBlock =
5218+ IGF.createBasicBlock (" deferring_allocator" );
5219+ auto *normalBlock = IGF.createBasicBlock (" normal" );
5220+ IGF.Builder .CreateCondBr (isDeallocDeferringAllocator,
5221+ deferringAllocatorBlock, normalBlock);
5222+ IGF.Builder .emitBlock (deferringAllocatorBlock);
5223+ // Nothing to do here.
51735224 IGF.Builder .CreateRetVoid ();
5174- IGF.Builder .emitBlock (forwardBlock);
5175- IGF.Builder .CreateCall (
5176- IGF.IGM .getCoroDeallocFunctionPointer (), {allocator, ptr});
5225+ // Start emitting the "normal" block.
5226+ IGF.Builder .emitBlock (normalBlock);
5227+ auto *calleePtr = IGF.Builder .CreateInBoundsGEP (
5228+ IGF.IGM .CoroAllocatorTy , allocator,
5229+ {llvm::ConstantInt::get (IGF.IGM .Int32Ty , 0 ),
5230+ llvm::ConstantInt::get (IGF.IGM .Int32Ty , 2 )});
5231+ auto *callee = IGF.Builder .CreateLoad (
5232+ Address (calleePtr, IGF.IGM .CoroDeallocateFnTy ->getPointerTo (),
5233+ IGF.IGM .getPointerAlignment ()),
5234+ " deallocate_fn" );
5235+ auto fnPtr = FunctionPointer::createUnsigned (
5236+ FunctionPointer::Kind::Function, callee,
5237+ Signature (cast<llvm::FunctionType>(IGF.IGM .CoroDeallocateFnTy ), {},
5238+ IGF.IGM .SwiftCC ));
5239+ auto *call = IGF.Builder .CreateCall (fnPtr, {ptr});
5240+ call->setDoesNotThrow ();
5241+ call->setCallingConv (IGF.IGM .SwiftCC );
51775242 IGF.Builder .CreateRetVoid ();
51785243 },
5179- /* setIsNoInline=*/ false ,
5244+ /* setIsNoInline=*/ true ,
51805245 /* forPrologue=*/ false ,
51815246 /* isPerformanceConstraint=*/ false ,
5182- /* optionalLinkageOverride=*/ nullptr , llvm::CallingConv::SwiftCoro );
5247+ /* optionalLinkageOverride=*/ nullptr , IGM. SwiftCoroCC );
51835248}
51845249
51855250void irgen::emitYieldOnce2CoroutineEntry (IRGenFunction &IGF,
@@ -5188,14 +5253,8 @@ void irgen::emitYieldOnce2CoroutineEntry(IRGenFunction &IGF,
51885253 llvm::Value *allocator,
51895254 llvm::GlobalVariable *cfp) {
51905255 IGF.setCoroutineAllocator (allocator);
5191- auto isSwiftCoroCCAvailable =
5192- IGF.IGM .SwiftCoroCC == llvm::CallingConv::SwiftCoro;
5193- auto allocFn = IGF.IGM .getOpaquePtr (isSwiftCoroCCAvailable
5194- ? getCoroAllocWrapperFn (IGF.IGM )
5195- : IGF.IGM .getCoroAllocFn ());
5196- auto deallocFn = IGF.IGM .getOpaquePtr (isSwiftCoroCCAvailable
5197- ? getCoroDeallocWrapperFn (IGF.IGM )
5198- : IGF.IGM .getCoroDeallocFn ());
5256+ auto allocFn = IGF.IGM .getOpaquePtr (getCoroAllocFn (IGF.IGM ));
5257+ auto deallocFn = IGF.IGM .getOpaquePtr (getCoroDeallocFn (IGF.IGM ));
51995258 emitRetconCoroutineEntry (
52005259 IGF, fnType, buffer, llvm::Intrinsic::coro_id_retcon_once_dynamic,
52015260 Size (-1 ) /* dynamic-to-IRGen size*/ , IGF.IGM .getCoroStaticFrameAlignment (),
@@ -5230,6 +5289,40 @@ Address irgen::emitAllocYieldManyCoroutineBuffer(IRGenFunction &IGF) {
52305289 getYieldManyCoroutineBufferAlignment (IGF.IGM ));
52315290}
52325291
5292+ static llvm::Constant *getAddrOfSwiftCCMalloc (IRGenModule &IGM) {
5293+ auto mallocFnPtr = IGM.getMallocFunctionPointer ();
5294+ auto sig = mallocFnPtr.getSignature ();
5295+ if (sig.getCallingConv () == IGM.SwiftCC ) {
5296+ return IGM.getMallocFn ();
5297+ }
5298+ return IGM.getOrCreateHelperFunction (
5299+ " _swift_malloc" , sig.getType ()->getReturnType (), sig.getType ()->params (),
5300+ [](IRGenFunction &IGF) {
5301+ auto parameters = IGF.collectParameters ();
5302+ auto *size = parameters.claimNext ();
5303+ auto malloc = IGF.IGM .getMallocFunctionPointer ();
5304+ auto *call = IGF.Builder .CreateCall (malloc, {size});
5305+ IGF.Builder .CreateRet (call);
5306+ });
5307+ }
5308+
5309+ static llvm::Constant *getAddrOfSwiftCCFree (IRGenModule &IGM) {
5310+ auto freeFnPtr = IGM.getFreeFunctionPointer ();
5311+ auto sig = freeFnPtr.getSignature ();
5312+ if (sig.getCallingConv () == IGM.SwiftCC ) {
5313+ return IGM.getFreeFn ();
5314+ }
5315+ return IGM.getOrCreateHelperFunction (
5316+ " _swift_free" , sig.getType ()->getReturnType (), sig.getType ()->params (),
5317+ [](IRGenFunction &IGF) {
5318+ auto parameters = IGF.collectParameters ();
5319+ auto *ptr = parameters.claimNext ();
5320+ auto free = IGF.IGM .getFreeFunctionPointer ();
5321+ IGF.Builder .CreateCall (free, {ptr});
5322+ IGF.Builder .CreateRetVoid ();
5323+ });
5324+ }
5325+
52335326static llvm::Constant *getAddrOfGlobalCoroAllocator (
52345327 IRGenModule &IGM, CoroAllocatorKind kind, bool shouldDeallocateImmediately,
52355328 llvm::Constant *allocFn, llvm::Constant *deallocFn) {
@@ -5251,7 +5344,8 @@ static llvm::Constant *getAddrOfGlobalCoroAllocator(
52515344llvm::Constant *IRGenModule::getAddrOfGlobalCoroMallocAllocator () {
52525345 return getAddrOfGlobalCoroAllocator (*this , CoroAllocatorKind::Malloc,
52535346 /* shouldDeallocateImmediately=*/ true ,
5254- getMallocFn (), getFreeFn ());
5347+ getAddrOfSwiftCCMalloc (*this ),
5348+ getAddrOfSwiftCCFree (*this ));
52555349}
52565350llvm::Constant *IRGenModule::getAddrOfGlobalCoroAsyncTaskAllocator () {
52575351 return getAddrOfGlobalCoroAllocator (*this , CoroAllocatorKind::Async,
0 commit comments