@@ -5118,39 +5118,59 @@ void irgen::emitYieldManyCoroutineEntry(
5118
5118
allocFn, deallocFn, {});
5119
5119
}
5120
5120
5121
- static llvm::Constant *getCoroAllocWrapperFn (IRGenModule &IGM) {
5121
+ static llvm::Constant *getCoroAllocFn (IRGenModule &IGM) {
5122
+ auto isSwiftCoroCCAvailable = IGM.SwiftCoroCC == llvm::CallingConv::SwiftCoro;
5122
5123
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) {
5126
5126
auto parameters = IGF.collectParameters ();
5127
5127
auto *allocator = parameters.claimNext ();
5128
5128
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 );
5148
5168
IGF.Builder .CreateRet (call);
5149
5169
},
5150
- /* setIsNoInline=*/ false ,
5170
+ /* setIsNoInline=*/ true ,
5151
5171
/* forPrologue=*/ false ,
5152
5172
/* isPerformanceConstraint=*/ false ,
5153
- /* optionalLinkageOverride=*/ nullptr , llvm::CallingConv::SwiftCoro );
5173
+ /* optionalLinkageOverride=*/ nullptr , IGM. SwiftCoroCC );
5154
5174
}
5155
5175
5156
5176
static llvm::Constant *getCoroDeallocWrapperFn (IRGenModule &IGM) {
@@ -5190,9 +5210,7 @@ void irgen::emitYieldOnce2CoroutineEntry(IRGenFunction &IGF,
5190
5210
IGF.setCoroutineAllocator (allocator);
5191
5211
auto isSwiftCoroCCAvailable =
5192
5212
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 ));
5196
5214
auto deallocFn = IGF.IGM .getOpaquePtr (isSwiftCoroCCAvailable
5197
5215
? getCoroDeallocWrapperFn (IGF.IGM )
5198
5216
: IGF.IGM .getCoroDeallocFn ());
0 commit comments