Skip to content

Commit b878155

Browse files
Merge pull request #80335 from nate-chandler/general-coro/20250326/2
[CoroutineAccessors] Move functions and add dealloc bit.
2 parents 74e9668 + 2412ac3 commit b878155

File tree

13 files changed

+104
-46
lines changed

13 files changed

+104
-46
lines changed

include/swift/ABI/Coro.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ class CoroAllocatorFlags : public FlagSet<uint32_t> {
3939
Kind = 0,
4040
Kind_width = 8,
4141

42+
ShouldDeallocateImmediately = 8,
43+
4244
// 24 reserved bits
4345
};
4446
// clang-format on
@@ -49,6 +51,9 @@ class CoroAllocatorFlags : public FlagSet<uint32_t> {
4951

5052
FLAGSET_DEFINE_FIELD_ACCESSORS(Kind, Kind_width, CoroAllocatorKind, getKind,
5153
setKind)
54+
FLAGSET_DEFINE_FLAG_ACCESSORS(ShouldDeallocateImmediately,
55+
shouldDeallocateImmediately,
56+
setShouldDeallocateImmediately)
5257
};
5358

5459
using CoroAllocation = void *;
@@ -62,16 +67,16 @@ struct CoroAllocator {
6267

6368
/// Whether the allocator should deallocate memory on calls to
6469
/// swift_coro_dealloc.
65-
constexpr bool shouldDeallocateImmediately() {
66-
// Only the "mallocator" should immediately deallocate in
70+
bool shouldDeallocateImmediately() {
71+
// Currently, only the "mallocator" should immediately deallocate in
6772
// swift_coro_dealloc. It must because the ABI does not provide a means for
6873
// the callee to return its allocations to the caller.
6974
//
7075
// Async allocations can be deferred until the first non-coroutine caller
7176
// from where swift_task_dealloc_through can be called and passed the
7277
// caller-allocated fixed-per-callee-sized-frame.
7378
// Stack allocations just pop the stack.
74-
return flags.getKind() == CoroAllocatorKind::Malloc;
79+
return flags.shouldDeallocateImmediately();
7580
}
7681
};
7782

include/swift/Runtime/Concurrency.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
#define SWIFT_RUNTIME_CONCURRENCY_H
1919

2020
#include "swift/ABI/AsyncLet.h"
21-
#include "swift/ABI/Coro.h"
2221
#include "swift/ABI/Task.h"
2322
#include "swift/ABI/TaskGroup.h"
2423

@@ -128,13 +127,6 @@ void swift_task_dealloc(void *ptr);
128127
SWIFT_EXPORT_FROM(swift_Concurrency)
129128
SWIFT_CC(swift) void swift_task_dealloc_through(void *ptr);
130129

131-
// TODO: CoroutineAccessors: Move these declarations back to swiftCore {{
132-
SWIFT_EXPORT_FROM(swift_Concurrency)
133-
SWIFT_CC(swift) void *swift_coro_alloc(CoroAllocator *allocator, size_t size);
134-
SWIFT_EXPORT_FROM(swift_Concurrency)
135-
SWIFT_CC(swift) void swift_coro_dealloc(CoroAllocator *allocator, void *ptr);
136-
// }} TODO: CoroutineAccessors
137-
138130
/// Cancel a task and all of its child tasks.
139131
///
140132
/// This can be called from any thread.

include/swift/Runtime/Coro.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@
2121
#include "swift/Runtime/Config.h"
2222
#include <cstddef>
2323

24-
namespace swift {} // end namespace swift
24+
namespace swift {
25+
SWIFT_RUNTIME_EXPORT
26+
SWIFT_CC(swift) void *swift_coro_alloc(CoroAllocator *allocator, size_t size);
27+
28+
SWIFT_RUNTIME_EXPORT
29+
SWIFT_CC(swift) void swift_coro_dealloc(CoroAllocator *allocator, void *ptr);
30+
} // end namespace swift
2531

2632
#endif

include/swift/Runtime/RuntimeFunctions.def

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3010,7 +3010,7 @@ FUNCTION(MemsetS, c, memset_s, C_CC, AlwaysAvailable,
30103010

30113011
// void *swift_coro_alloc(CoroAllocator *, size_t size);
30123012
FUNCTION(CoroAlloc,
3013-
_Concurrency, swift_coro_alloc, SwiftCC,
3013+
Swift, swift_coro_alloc, SwiftCC,
30143014
CoroutineAccessorsAvailability,
30153015
RETURNS(Int8PtrTy),
30163016
ARGS(CoroAllocatorPtrTy, SizeTy),
@@ -3020,7 +3020,7 @@ FUNCTION(CoroAlloc,
30203020

30213021
// void swift_coro_dealloc(CoroAllocator *, void *ptr);
30223022
FUNCTION(CoroDealloc,
3023-
_Concurrency, swift_coro_dealloc, SwiftCC,
3023+
Swift, swift_coro_dealloc, SwiftCC,
30243024
CoroutineAccessorsAvailability,
30253025
RETURNS(VoidTy),
30263026
ARGS(CoroAllocatorPtrTy, Int8PtrTy),

lib/IRGen/GenCall.cpp

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5153,6 +5153,35 @@ static llvm::Constant *getCoroAllocWrapperFn(IRGenModule &IGM) {
51535153
/*optionalLinkageOverride=*/nullptr, llvm::CallingConv::SwiftCoro);
51545154
}
51555155

5156+
static llvm::Constant *getCoroDeallocWrapperFn(IRGenModule &IGM) {
5157+
return IGM.getOrCreateHelperFunction(
5158+
"__swift_coro_dealloc_", IGM.VoidTy,
5159+
{IGM.CoroAllocatorPtrTy, IGM.Int8PtrTy},
5160+
[](IRGenFunction &IGF) {
5161+
auto parameters = IGF.collectParameters();
5162+
auto *allocator = parameters.claimNext();
5163+
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.
5173+
IGF.Builder.CreateRetVoid();
5174+
IGF.Builder.emitBlock(forwardBlock);
5175+
IGF.Builder.CreateCall(
5176+
IGF.IGM.getCoroDeallocFunctionPointer(), {allocator, ptr});
5177+
IGF.Builder.CreateRetVoid();
5178+
},
5179+
/*setIsNoInline=*/false,
5180+
/*forPrologue=*/false,
5181+
/*isPerformanceConstraint=*/false,
5182+
/*optionalLinkageOverride=*/nullptr, llvm::CallingConv::SwiftCoro);
5183+
}
5184+
51565185
void irgen::emitYieldOnce2CoroutineEntry(IRGenFunction &IGF,
51575186
CanSILFunctionType fnType,
51585187
llvm::Value *buffer,
@@ -5164,7 +5193,9 @@ void irgen::emitYieldOnce2CoroutineEntry(IRGenFunction &IGF,
51645193
auto allocFn = IGF.IGM.getOpaquePtr(isSwiftCoroCCAvailable
51655194
? getCoroAllocWrapperFn(IGF.IGM)
51665195
: IGF.IGM.getCoroAllocFn());
5167-
auto deallocFn = IGF.IGM.getOpaquePtr(IGF.IGM.getCoroDeallocFn());
5196+
auto deallocFn = IGF.IGM.getOpaquePtr(isSwiftCoroCCAvailable
5197+
? getCoroDeallocWrapperFn(IGF.IGM)
5198+
: IGF.IGM.getCoroDeallocFn());
51685199
emitRetconCoroutineEntry(
51695200
IGF, fnType, buffer, llvm::Intrinsic::coro_id_retcon_once_dynamic,
51705201
Size(-1) /*dynamic-to-IRGen size*/, IGF.IGM.getCoroStaticFrameAlignment(),
@@ -5199,16 +5230,17 @@ Address irgen::emitAllocYieldManyCoroutineBuffer(IRGenFunction &IGF) {
51995230
getYieldManyCoroutineBufferAlignment(IGF.IGM));
52005231
}
52015232

5202-
static llvm::Constant *getAddrOfGlobalCoroAllocator(IRGenModule &IGM,
5203-
CoroAllocatorKind kind,
5204-
llvm::Constant *allocFn,
5205-
llvm::Constant *deallocFn) {
5233+
static llvm::Constant *getAddrOfGlobalCoroAllocator(
5234+
IRGenModule &IGM, CoroAllocatorKind kind, bool shouldDeallocateImmediately,
5235+
llvm::Constant *allocFn, llvm::Constant *deallocFn) {
52065236
auto entity = LinkEntity::forCoroAllocator(kind);
52075237
auto taskAllocator = IGM.getOrCreateLazyGlobalVariable(
52085238
entity,
52095239
[&](ConstantInitBuilder &builder) -> ConstantInitFuture {
52105240
auto allocator = builder.beginStruct(IGM.CoroAllocatorTy);
5211-
allocator.addInt32(CoroAllocatorFlags(kind).getOpaqueValue());
5241+
auto flags = CoroAllocatorFlags(kind);
5242+
flags.setShouldDeallocateImmediately(shouldDeallocateImmediately);
5243+
allocator.addInt32(flags.getOpaqueValue());
52125244
allocator.add(allocFn);
52135245
allocator.add(deallocFn);
52145246
return allocator.finishAndCreateFuture();
@@ -5218,10 +5250,12 @@ static llvm::Constant *getAddrOfGlobalCoroAllocator(IRGenModule &IGM,
52185250
}
52195251
llvm::Constant *IRGenModule::getAddrOfGlobalCoroMallocAllocator() {
52205252
return getAddrOfGlobalCoroAllocator(*this, CoroAllocatorKind::Malloc,
5253+
/*shouldDeallocateImmediately=*/true,
52215254
getMallocFn(), getFreeFn());
52225255
}
52235256
llvm::Constant *IRGenModule::getAddrOfGlobalCoroAsyncTaskAllocator() {
52245257
return getAddrOfGlobalCoroAllocator(*this, CoroAllocatorKind::Async,
5258+
/*shouldDeallocateImmediately=*/false,
52255259
getTaskAllocFn(), getTaskDeallocFn());
52265260
}
52275261
llvm::Value *

stdlib/public/Concurrency/TaskAlloc.cpp

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -72,19 +72,3 @@ void swift::_swift_task_dealloc_specific(AsyncTask *task, void *ptr) {
7272
void swift::swift_task_dealloc_through(void *ptr) {
7373
allocator(swift_task_getCurrent()).deallocThrough(ptr);
7474
}
75-
76-
void *swift::swift_coro_alloc(CoroAllocator *allocator, size_t size) {
77-
return allocator->allocate(size);
78-
}
79-
80-
void swift::swift_coro_dealloc(CoroAllocator *allocator, void *ptr) {
81-
if (!allocator)
82-
return;
83-
// Calls to swift_coro_dealloc are emitted in resume funclets for every
84-
// live-across dynamic allocation. Whether such calls immediately deallocate
85-
// memory depends on the allocator.
86-
if (!allocator->shouldDeallocateImmediately()) {
87-
return;
88-
}
89-
allocator->deallocate(ptr);
90-
}

stdlib/public/runtime/Coro.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,18 @@
1515
#include "swift/Basic/FlagSet.h"
1616

1717
using namespace swift;
18+
19+
void *swift::swift_coro_alloc(CoroAllocator *allocator, size_t size) {
20+
return allocator->allocate(size);
21+
}
22+
23+
void swift::swift_coro_dealloc(CoroAllocator *allocator, void *ptr) {
24+
assert(allocator);
25+
// Calls to swift_coro_dealloc are emitted in resume funclets for every
26+
// live-across dynamic allocation. Whether such calls immediately deallocate
27+
// memory depends on the allocator.
28+
if (!allocator->shouldDeallocateImmediately()) {
29+
return;
30+
}
31+
allocator->deallocate(ptr);
32+
}

test/IRGen/coroutine_accessors.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
// CHECK-SAME: }>
1515

1616
// CHECK-LABEL: _swift_coro_malloc_allocator = linkonce_odr hidden constant %swift.coro_allocator {
17-
// CHECK-SAME: i32 2,
17+
// CHECK-SAME: i32 258,
1818
// CHECK-SAME: malloc,
1919
// CHECK-SAME: free
2020
// CHECK-SAME: }

test/IRGen/coroutine_accessors_popless.swift

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
// CHECK-SAME: swift_task_dealloc
2424
// CHECK-SAME: }
2525
// CHECK-LABEL: _swift_coro_malloc_allocator = linkonce_odr hidden constant %swift.coro_allocator {
26-
// CHECK-SAME: i32 2,
26+
// CHECK-SAME: i32 258,
2727
// CHECK-SAME: malloc,
2828
// CHECK-SAME: free
2929
// CHECK-SAME: }
@@ -50,6 +50,26 @@
5050
// CHECK: ret ptr [[OTHER_ALLOCATION]]
5151
// CHECK: }
5252

53+
// CHECK-LABEL: @__swift_coro_dealloc_(
54+
// CHECK-SAME: ptr [[ALLOCATOR:%[^,]+]]
55+
// CHECK-SAME: ptr [[ADDRESS:%[^)]+]]
56+
// CHECK-SAME: )
57+
// CHECK-SAME: {
58+
// CHECK: entry:
59+
// CHECK: [[BAIL:%[^,]+]] = icmp eq ptr [[ALLOCATOR]], null
60+
// CHECK: br i1 [[USE_POPLESS]],
61+
// CHECK-SAME: label %bail
62+
// CHECK-SAME: label %forward
63+
// CHECK: bail:
64+
// CHECK: ret void
65+
// CHECK: forward:
66+
// CHECK: call swiftcc void @swift_coro_dealloc(
67+
// CHECK-SAME: ptr [[ALLOCATOR]]
68+
// CHECK-SAME: ptr [[ADDRESS]]
69+
// CHECK-SAME: )
70+
// CHECK: ret void
71+
// CHECK: }
72+
5373
public var _i: Int = 0
5474

5575
public var i: Int {

test/abi/macOS/arm64/concurrency.swift

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -408,10 +408,7 @@ Added: _$sScf25isIsolatingCurrentContextSbyFTj
408408
Added: _$sScf25isIsolatingCurrentContextSbyFTq
409409
Added: _$sScfsE25isIsolatingCurrentContextSbyF
410410

411-
// add callee-allocated coro entrypoints
412-
// TODO: CoroutineAccessors: several of these symbols should be in swiftCore
413-
Added: _swift_coro_alloc
414-
Added: _swift_coro_dealloc
411+
// CoroutineAccessors
415412
Added: _swift_task_dealloc_through
416413

417414
// SwiftSettings

0 commit comments

Comments
 (0)