35
35
#include " clang/CodeGen/ModuleBuilder.h"
36
36
#include " clang/Sema/Sema.h"
37
37
#include " llvm/Analysis/ValueTracking.h"
38
+ #include " llvm/IR/CallingConv.h"
39
+ #include " llvm/IR/Constant.h"
40
+ #include " llvm/IR/Function.h"
38
41
#include " llvm/IR/GlobalPtrAuthInfo.h"
39
42
#include " llvm/IR/GlobalValue.h"
40
43
#include " llvm/Support/Compiler.h"
@@ -220,7 +223,11 @@ IRGenFunction::getDefaultCoroutineAllocatorKind() {
220
223
if (isCoroutine ()) {
221
224
return CoroAllocatorKind::Malloc;
222
225
}
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;
224
231
}
225
232
226
233
llvm::Value *IRGenFunction::getAsyncTask () {
@@ -360,9 +367,10 @@ static llvm::CallingConv::ID getFreestandingConvention(IRGenModule &IGM) {
360
367
361
368
// / Expand the requirements of the given abstract calling convention
362
369
// / 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) {
366
374
switch (convention) {
367
375
case SILFunctionTypeRepresentation::CFunctionPointer:
368
376
case SILFunctionTypeRepresentation::ObjCMethod:
@@ -379,6 +387,8 @@ llvm::CallingConv::ID irgen::expandCallingConv(IRGenModule &IGM,
379
387
case SILFunctionTypeRepresentation::KeyPathAccessorSetter:
380
388
case SILFunctionTypeRepresentation::KeyPathAccessorEquals:
381
389
case SILFunctionTypeRepresentation::KeyPathAccessorHash:
390
+ if (isCalleeAllocatedCoro && !IGM.getOptions ().EmitYieldOnce2AsYieldOnce )
391
+ return IGM.SwiftCoroCC ;
382
392
if (isAsync)
383
393
return IGM.SwiftAsyncCC ;
384
394
return getFreestandingConvention (IGM);
@@ -2391,7 +2401,8 @@ Signature SignatureExpansion::getSignature() {
2391
2401
" C function type without C function info" );
2392
2402
2393
2403
auto callingConv =
2394
- expandCallingConv (IGM, FnType->getRepresentation (), FnType->isAsync ());
2404
+ expandCallingConv (IGM, FnType->getRepresentation (), FnType->isAsync (),
2405
+ FnType->isCalleeAllocatedCoroutine ());
2395
2406
2396
2407
Signature result;
2397
2408
result.Type = llvmType;
@@ -5118,6 +5129,40 @@ void irgen::emitYieldManyCoroutineEntry(
5118
5129
allocFn, deallocFn, {});
5119
5130
}
5120
5131
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
+
5121
5166
void irgen::emitYieldOnce2CoroutineEntry (
5122
5167
IRGenFunction &IGF, LinkEntity coroFunction, CanSILFunctionType fnType,
5123
5168
NativeCCEntryPointArgumentEmission &emission) {
@@ -5126,7 +5171,11 @@ void irgen::emitYieldOnce2CoroutineEntry(
5126
5171
IGF.IGM .getAddrOfCoroFunctionPointer (coroFunction));
5127
5172
llvm::Value *allocator = emission.getCoroutineAllocator ();
5128
5173
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 ());
5130
5179
auto deallocFn = IGF.IGM .getOpaquePtr (IGF.IGM .getCoroDeallocFn ());
5131
5180
emitRetconCoroutineEntry (
5132
5181
IGF, fnType, buffer, llvm::Intrinsic::coro_id_retcon_once_dynamic,
0 commit comments