@@ -5173,33 +5173,78 @@ static llvm::Constant *getCoroAllocFn(IRGenModule &IGM) {
5173
5173
/* optionalLinkageOverride=*/ nullptr , IGM.SwiftCoroCC );
5174
5174
}
5175
5175
5176
- static llvm::Constant *getCoroDeallocWrapperFn (IRGenModule &IGM) {
5176
+ static llvm::Constant *getCoroDeallocFn (IRGenModule &IGM) {
5177
+ auto isSwiftCoroCCAvailable = IGM.SwiftCoroCC == llvm::CallingConv::SwiftCoro;
5177
5178
return IGM.getOrCreateHelperFunction (
5178
- " __swift_coro_dealloc_ " , IGM.VoidTy ,
5179
+ " _swift_coro_dealloc " , IGM.VoidTy ,
5179
5180
{IGM.CoroAllocatorPtrTy , IGM.Int8PtrTy },
5180
- [](IRGenFunction &IGF) {
5181
+ [isSwiftCoroCCAvailable ](IRGenFunction &IGF) {
5181
5182
auto parameters = IGF.collectParameters ();
5182
5183
auto *allocator = parameters.claimNext ();
5183
5184
auto *ptr = parameters.claimNext ();
5184
- auto *nullAllocator = IGF.Builder .CreateCmp (
5185
- llvm::CmpInst::Predicate::ICMP_EQ, allocator,
5186
- llvm::ConstantPointerNull::get (
5187
- cast<llvm::PointerType>(allocator->getType ())));
5188
- auto *bailBlock = IGF.createBasicBlock (" bail" );
5189
- auto *forwardBlock = IGF.createBasicBlock (" forward" );
5190
- IGF.Builder .CreateCondBr (nullAllocator, bailBlock, forwardBlock);
5191
- IGF.Builder .emitBlock (bailBlock);
5192
- // 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.
5193
5224
IGF.Builder .CreateRetVoid ();
5194
- IGF.Builder .emitBlock (forwardBlock);
5195
- IGF.Builder .CreateCall (
5196
- 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 );
5197
5242
IGF.Builder .CreateRetVoid ();
5198
5243
},
5199
- /* setIsNoInline=*/ false ,
5244
+ /* setIsNoInline=*/ true ,
5200
5245
/* forPrologue=*/ false ,
5201
5246
/* isPerformanceConstraint=*/ false ,
5202
- /* optionalLinkageOverride=*/ nullptr , llvm::CallingConv::SwiftCoro );
5247
+ /* optionalLinkageOverride=*/ nullptr , IGM. SwiftCoroCC );
5203
5248
}
5204
5249
5205
5250
void irgen::emitYieldOnce2CoroutineEntry (IRGenFunction &IGF,
@@ -5208,12 +5253,8 @@ void irgen::emitYieldOnce2CoroutineEntry(IRGenFunction &IGF,
5208
5253
llvm::Value *allocator,
5209
5254
llvm::GlobalVariable *cfp) {
5210
5255
IGF.setCoroutineAllocator (allocator);
5211
- auto isSwiftCoroCCAvailable =
5212
- IGF.IGM .SwiftCoroCC == llvm::CallingConv::SwiftCoro;
5213
5256
auto allocFn = IGF.IGM .getOpaquePtr (getCoroAllocFn (IGF.IGM ));
5214
- auto deallocFn = IGF.IGM .getOpaquePtr (isSwiftCoroCCAvailable
5215
- ? getCoroDeallocWrapperFn (IGF.IGM )
5216
- : IGF.IGM .getCoroDeallocFn ());
5257
+ auto deallocFn = IGF.IGM .getOpaquePtr (getCoroDeallocFn (IGF.IGM ));
5217
5258
emitRetconCoroutineEntry (
5218
5259
IGF, fnType, buffer, llvm::Intrinsic::coro_id_retcon_once_dynamic,
5219
5260
Size (-1 ) /* dynamic-to-IRGen size*/ , IGF.IGM .getCoroStaticFrameAlignment (),
0 commit comments