Skip to content

Commit 2271d4d

Browse files
committed
Use taskAlloc for dynamic allocas
Async coroutines don't support dynamic allocas.
1 parent 74419d0 commit 2271d4d

File tree

6 files changed

+54
-69
lines changed

6 files changed

+54
-69
lines changed

lib/IRGen/Address.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ class StackAddress {
112112

113113
/// In a normal function, the result of llvm.stacksave or null.
114114
/// In a coroutine, the result of llvm.coro.alloca.alloc.
115+
/// In an async function, the result of the taskAlloc call.
115116
llvm::Value *ExtraInfo;
116117

117118
public:

lib/IRGen/GenCall.cpp

Lines changed: 11 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -330,10 +330,6 @@ AsyncContextLayout::AsyncContextLayout(
330330
#endif
331331
}
332332

333-
static Size getAsyncContextSize(AsyncContextLayout layout) {
334-
return layout.getSize();
335-
}
336-
337333
static Alignment getAsyncContextAlignment(IRGenModule &IGM) {
338334
return IGM.getPointerAlignment();
339335
}
@@ -2240,7 +2236,6 @@ class AsyncCallEmission final : public CallEmission {
22402236
using super = CallEmission;
22412237

22422238
Address contextBuffer;
2243-
Size contextSize;
22442239
Address context;
22452240
llvm::Value *calleeFunction = nullptr;
22462241
llvm::Value *currentResumeFn = nullptr;
@@ -2285,8 +2280,7 @@ class AsyncCallEmission final : public CallEmission {
22852280
CurCallee.getFunctionPointer(), thickContext);
22862281
auto *dynamicContextSize =
22872282
IGF.Builder.CreateZExt(dynamicContextSize32, IGF.IGM.SizeTy);
2288-
std::tie(contextBuffer, contextSize) = emitAllocAsyncContext(
2289-
IGF, layout, dynamicContextSize, getAsyncContextSize(layout));
2283+
contextBuffer = emitAllocAsyncContext(IGF, dynamicContextSize);
22902284
context = layout.emitCastTo(IGF, contextBuffer.getAddress());
22912285
if (layout.canHaveError()) {
22922286
auto fieldLayout = layout.getErrorLayout();
@@ -2299,7 +2293,7 @@ class AsyncCallEmission final : public CallEmission {
22992293
void end() override {
23002294
assert(contextBuffer.isValid());
23012295
assert(context.isValid());
2302-
emitDeallocAsyncContext(IGF, contextBuffer, contextSize);
2296+
emitDeallocAsyncContext(IGF, contextBuffer);
23032297
super::end();
23042298
}
23052299
void setFromCallee() override {
@@ -3523,8 +3517,7 @@ void irgen::emitAsyncFunctionEntry(IRGenFunction &IGF,
35233517
auto &IGM = IGF.IGM;
35243518
auto size = getAsyncContextLayout(IGM, asyncFunction).getSize();
35253519
auto asyncFuncPointer = IGF.Builder.CreateBitOrPointerCast(
3526-
IGM.getAddrOfAsyncFunctionPointer(asyncFunction, NotForDefinition),
3527-
IGM.Int8PtrTy);
3520+
IGM.getAddrOfAsyncFunctionPointer(asyncFunction), IGM.Int8PtrTy);
35283521
auto *id = IGF.Builder.CreateIntrinsicCall(
35293522
llvm::Intrinsic::coro_id_async,
35303523
{llvm::ConstantInt::get(IGM.Int32Ty, size.getValue()),
@@ -3590,28 +3583,6 @@ void irgen::emitDeallocYieldManyCoroutineBuffer(IRGenFunction &IGF,
35903583
IGF.Builder.CreateLifetimeEnd(buffer, bufferSize);
35913584
}
35923585

3593-
Address irgen::emitTaskAlloc(IRGenFunction &IGF, llvm::Value *size,
3594-
Alignment alignment) {
3595-
auto *call = IGF.Builder.CreateCall(IGF.IGM.getTaskAllocFn(),
3596-
{IGF.getAsyncTask(), size});
3597-
call->setDoesNotThrow();
3598-
call->setCallingConv(IGF.IGM.SwiftCC);
3599-
call->addAttribute(llvm::AttributeList::FunctionIndex,
3600-
llvm::Attribute::ReadNone);
3601-
auto address = Address(call, alignment);
3602-
return address;
3603-
}
3604-
3605-
void irgen::emitTaskDealloc(IRGenFunction &IGF, Address address,
3606-
llvm::Value *size) {
3607-
auto *call = IGF.Builder.CreateCall(
3608-
IGF.IGM.getTaskDeallocFn(), {IGF.getAsyncTask(), address.getAddress()});
3609-
call->setDoesNotThrow();
3610-
call->setCallingConv(IGF.IGM.SwiftCC);
3611-
call->addAttribute(llvm::AttributeList::FunctionIndex,
3612-
llvm::Attribute::ReadNone);
3613-
}
3614-
36153586
void irgen::emitTaskCancel(IRGenFunction &IGF, llvm::Value *task) {
36163587
if (task->getType() != IGF.IGM.SwiftTaskPtrTy) {
36173588
task = IGF.Builder.CreateBitCast(task, IGF.IGM.SwiftTaskPtrTy);
@@ -3663,28 +3634,17 @@ llvm::Value *irgen::emitTaskCreate(
36633634
return result;
36643635
}
36653636

3666-
std::pair<Address, Size> irgen::emitAllocAsyncContext(IRGenFunction &IGF,
3667-
AsyncContextLayout layout,
3668-
llvm::Value *sizeValue,
3669-
Size sizeLowerBound) {
3637+
Address irgen::emitAllocAsyncContext(IRGenFunction &IGF,
3638+
llvm::Value *sizeValue) {
36703639
auto alignment = getAsyncContextAlignment(IGF.IGM);
3671-
auto address = emitTaskAlloc(IGF, sizeValue, alignment);
3672-
IGF.Builder.CreateLifetimeStart(address, sizeLowerBound);
3673-
return {address, sizeLowerBound};
3674-
}
3675-
3676-
std::pair<Address, Size>
3677-
irgen::emitAllocAsyncContext(IRGenFunction &IGF, AsyncContextLayout layout) {
3678-
auto size = getAsyncContextSize(layout);
3679-
auto *sizeValue = llvm::ConstantInt::get(IGF.IGM.SizeTy, size.getValue());
3680-
return emitAllocAsyncContext(IGF, layout, sizeValue, size);
3640+
auto address = IGF.emitTaskAlloc(sizeValue, alignment);
3641+
IGF.Builder.CreateLifetimeStart(address, Size(-1) /*dynamic size*/);
3642+
return address;
36813643
}
36823644

3683-
void irgen::emitDeallocAsyncContext(IRGenFunction &IGF, Address context,
3684-
Size size) {
3685-
auto *sizeValue = llvm::ConstantInt::get(IGF.IGM.SizeTy, size.getValue());
3686-
emitTaskDealloc(IGF, context, sizeValue);
3687-
IGF.Builder.CreateLifetimeEnd(context, size);
3645+
void irgen::emitDeallocAsyncContext(IRGenFunction &IGF, Address context) {
3646+
IGF.emitTaskDealloc(context);
3647+
IGF.Builder.CreateLifetimeEnd(context, Size(-1) /*dynamic size*/);
36883648
}
36893649

36903650
llvm::Value *irgen::emitYield(IRGenFunction &IGF,

lib/IRGen/GenCall.h

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -397,9 +397,6 @@ namespace irgen {
397397
CanSILFunctionType coroutineType,
398398
NativeCCEntryPointArgumentEmission &emission);
399399

400-
Address emitTaskAlloc(IRGenFunction &IGF, llvm::Value *size,
401-
Alignment alignment);
402-
void emitTaskDealloc(IRGenFunction &IGF, Address address, llvm::Value *size);
403400
void emitTaskCancel(IRGenFunction &IGF, llvm::Value *task);
404401

405402
/// Emit a class to swift_task_create[_f] with the given flags, parent task,
@@ -408,19 +405,9 @@ namespace irgen {
408405
IRGenFunction &IGF, llvm::Value *flags, llvm::Value *parentTask,
409406
llvm::Value *taskFunction, llvm::Value *localContextInfo);
410407

411-
/// Allocate task local storage for the specified layout but using the
412-
/// provided dynamic size. Allowing the size to be specified dynamically is
413-
/// necessary for applies of thick functions the sizes of whose async contexts
414-
/// are dependent on the underlying, already partially applied, called
415-
/// function. The provided sizeLowerBound will be used to track the lifetime
416-
/// of the allocation that is known statically.
417-
std::pair<Address, Size> emitAllocAsyncContext(IRGenFunction &IGF,
418-
AsyncContextLayout layout,
419-
llvm::Value *sizeValue,
420-
Size sizeLowerBound);
421-
std::pair<Address, Size> emitAllocAsyncContext(IRGenFunction &IGF,
422-
AsyncContextLayout layout);
423-
void emitDeallocAsyncContext(IRGenFunction &IGF, Address context, Size size);
408+
/// Allocate task local storage for the provided dynamic size.
409+
Address emitAllocAsyncContext(IRGenFunction &IGF, llvm::Value *sizeValue);
410+
void emitDeallocAsyncContext(IRGenFunction &IGF, Address context);
424411

425412
void emitAsyncFunctionEntry(IRGenFunction &IGF, SILFunction *asyncFunc);
426413

lib/IRGen/GenOpaque.cpp

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -536,8 +536,19 @@ StackAddress IRGenFunction::emitDynamicAlloca(llvm::Type *eltTy,
536536
llvm::Value *arraySize,
537537
Alignment align,
538538
const llvm::Twine &name) {
539+
// Async functions call task alloc.
540+
if (isAsync()) {
541+
llvm::Value *byteCount;
542+
auto eltSize = IGM.DataLayout.getTypeAllocSize(eltTy);
543+
if (eltSize == 1) {
544+
byteCount = arraySize;
545+
} else {
546+
byteCount = Builder.CreateMul(arraySize, IGM.getSize(Size(eltSize)));
547+
}
548+
auto address = emitTaskAlloc(byteCount, align);
549+
return {address, address.getAddress()};
539550
// In coroutines, call llvm.coro.alloca.alloc.
540-
if (isCoroutine()) {
551+
} else if (isCoroutine()) {
541552
// Compute the number of bytes to allocate.
542553
llvm::Value *byteCount;
543554
auto eltSize = IGM.DataLayout.getTypeAllocSize(eltTy);
@@ -589,11 +600,16 @@ StackAddress IRGenFunction::emitDynamicAlloca(llvm::Type *eltTy,
589600
/// Deallocate dynamic alloca's memory if requested by restoring the stack
590601
/// location before the dynamic alloca's call.
591602
void IRGenFunction::emitDeallocateDynamicAlloca(StackAddress address) {
603+
// Async function use taskDealloc.
604+
if (isAsync() && address.getAddress().isValid()) {
605+
emitTaskDealloc(Address(address.getExtraInfo(), address.getAlignment()));
606+
return;
607+
}
592608
// In coroutines, unconditionally call llvm.coro.alloca.free.
593609
// Except if the address is invalid, this happens when this is a StackAddress
594610
// for a partial_apply [stack] that did not need a context object on the
595611
// stack.
596-
if (isCoroutine() && address.getAddress().isValid()) {
612+
else if (isCoroutine() && address.getAddress().isValid()) {
597613
auto allocToken = address.getExtraInfo();
598614
assert(allocToken && "dynamic alloca in coroutine without alloc token?");
599615
auto freeFn = llvm::Intrinsic::getDeclaration(

lib/IRGen/IRGenFunction.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,3 +490,20 @@ void IRGenFunction::emitTrap(StringRef failureMessage, bool EmitUnreachable) {
490490
if (EmitUnreachable)
491491
Builder.CreateUnreachable();
492492
}
493+
494+
Address IRGenFunction::emitTaskAlloc(llvm::Value *size, Alignment alignment) {
495+
auto *call = Builder.CreateCall(IGM.getTaskAllocFn(), {getAsyncTask(), size});
496+
call->setDoesNotThrow();
497+
call->setCallingConv(IGM.SwiftCC);
498+
call->addAttribute(llvm::AttributeList::FunctionIndex,
499+
llvm::Attribute::ReadNone);
500+
auto address = Address(call, alignment);
501+
return address;
502+
}
503+
504+
void IRGenFunction::emitTaskDealloc(Address address) {
505+
auto *call = Builder.CreateCall(IGM.getTaskDeallocFn(),
506+
{getAsyncTask(), address.getAddress()});
507+
call->setDoesNotThrow();
508+
call->setCallingConv(IGM.SwiftCC);
509+
}

lib/IRGen/IRGenFunction.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,10 @@ class IRGenFunction {
456456
llvm::Value *emitIsEscapingClosureCall(llvm::Value *value, SourceLoc loc,
457457
unsigned verificationType);
458458

459+
Address emitTaskAlloc(llvm::Value *size,
460+
Alignment alignment);
461+
void emitTaskDealloc(Address address);
462+
459463
//--- Expression emission
460464
//------------------------------------------------------
461465
public:

0 commit comments

Comments
 (0)