Skip to content

Commit a38adb3

Browse files
Merge pull request #85207 from nate-chandler/general-coro/20251023/1
[CoroutineAccessors] Use typed-malloc.
2 parents 9c63a56 + e0ead75 commit a38adb3

20 files changed

+246
-157
lines changed

include/swift/ABI/Coro.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ enum class CoroAllocatorKind : uint8_t {
3030
Async = 1,
3131
// malloc/free
3232
Malloc = 2,
33+
// swift_coroFrameAlloc/free
34+
TypedMalloc = 3,
3335
};
3436

3537
class CoroAllocatorFlags : public FlagSet<uint32_t> {

include/swift/Runtime/RuntimeFunctions.def

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2100,12 +2100,6 @@ FUNCTION(CoroFrameAlloc, Swift, swift_coroFrameAlloc, C_CC,
21002100
NO_ATTRS,
21012101
EFFECT(RuntimeEffect::Allocating),
21022102
UNKNOWN_MEMEFFECTS)
2103-
FUNCTION(coroFrameAllocStub, Swift, swift_coroFrameAllocStub, C_CC,
2104-
AlwaysAvailable, RETURNS(Int8PtrTy),
2105-
ARGS(SizeTy, Int64Ty),
2106-
ATTRS(NoUnwind),
2107-
EFFECT(RuntimeEffect::Allocating),
2108-
UNKNOWN_MEMEFFECTS)
21092103

21102104
// void *_Block_copy(void *block);
21112105
FUNCTION(BlockCopy, BlocksRuntime, _Block_copy, C_CC, AlwaysAvailable,

lib/IRGen/GenCall.cpp

Lines changed: 46 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,11 @@ IRGenFunction::getDefaultCoroutineAllocatorKind() {
221221
return CoroAllocatorKind::Async;
222222
}
223223
if (isCoroutine()) {
224-
return CoroAllocatorKind::Malloc;
224+
if (getOptions().EmitTypeMallocForCoroFrame) {
225+
return CoroAllocatorKind::TypedMalloc;
226+
} else {
227+
return CoroAllocatorKind::Malloc;
228+
}
225229
}
226230
if (IGM.SwiftCoroCC != llvm::CallingConv::SwiftCoro) {
227231
// If the swiftcorocc isn't available, fall back to malloc.
@@ -2491,6 +2495,12 @@ SignatureExpansionABIDetails Signature::getUncachedABIDetails(
24912495
return result;
24922496
}
24932497

2498+
Signature Signature::forFunction(llvm::Function *fn) {
2499+
auto sig = Signature(fn->getFunctionType(), fn->getAttributes(),
2500+
fn->getCallingConv());
2501+
return sig;
2502+
}
2503+
24942504
Signature Signature::forCoroutineContinuation(IRGenModule &IGM,
24952505
CanSILFunctionType fnType) {
24962506
assert(fnType->isCoroutine());
@@ -2701,17 +2711,14 @@ irgen::getAsyncFunctionAndSize(IRGenFunction &IGF,
27012711
return {fn, size};
27022712
}
27032713

2704-
std::pair<llvm::Value *, llvm::Value *>
2705-
irgen::getCoroFunctionAndSize(IRGenFunction &IGF,
2706-
FunctionPointer functionPointer,
2707-
std::pair<bool, bool> values) {
2708-
assert(values.first || values.second);
2714+
std::tuple<llvm::Value *, llvm::Value *, llvm::Value *>
2715+
irgen::getCoroFunctionValues(IRGenFunction &IGF,
2716+
FunctionPointer functionPointer,
2717+
std::tuple<bool, bool, bool> values) {
2718+
auto [emitFunction, emitSize, emitTypeID] = values;
2719+
assert(emitFunction || emitSize || emitTypeID);
27092720
assert(functionPointer.getKind() != FunctionPointer::Kind::Function);
27102721

2711-
bool emitFunction = values.first;
2712-
bool emitSize = values.second;
2713-
assert(emitFunction || emitSize);
2714-
27152722
// Ensure that the CoroFunctionPointer is not auth'd if it is not used and
27162723
// that it is not auth'd more than once if it is needed.
27172724
//
@@ -2764,7 +2771,15 @@ irgen::getCoroFunctionAndSize(IRGenFunction &IGF,
27642771
size = IGF.Builder.CreateLoad(sizePtr, IGF.IGM.Int32Ty,
27652772
IGF.IGM.getPointerAlignment());
27662773
}
2767-
return {fn, size};
2774+
2775+
llvm::Value *typeID = nullptr;
2776+
if (emitTypeID) {
2777+
auto *sizePtr = IGF.Builder.CreateStructGEP(IGF.IGM.CoroFunctionPointerTy,
2778+
getCoroPtr(), 2);
2779+
typeID = IGF.Builder.CreateLoad(sizePtr, IGF.IGM.Int64Ty,
2780+
IGF.IGM.getPointerAlignment());
2781+
}
2782+
return {fn, size, typeID};
27682783
}
27692784

27702785
namespace {
@@ -2804,16 +2819,17 @@ class SyncCallEmission final : public CallEmission {
28042819
assert(!coroAllocator);
28052820

28062821
if (IsCalleeAllocatedCoroutine) {
2807-
llvm::Value *bufferSize32;
2808-
std::tie(calleeFunction, bufferSize32) =
2809-
getCoroFunctionAndSize(IGF, CurCallee.getFunctionPointer());
2822+
auto kind = IGF.getDefaultCoroutineAllocatorKind();
2823+
llvm::Value *bufferSize32, *mallocTypeId;
2824+
std::tie(calleeFunction, bufferSize32, mallocTypeId) =
2825+
getCoroFunctionValues(IGF, CurCallee.getFunctionPointer());
28102826
auto *bufferSize = IGF.Builder.CreateZExt(bufferSize32, IGF.IGM.SizeTy);
2811-
coroStaticFrame = emitAllocYieldOnce2CoroutineFrame(IGF, bufferSize);
2827+
coroStaticFrame =
2828+
emitAllocYieldOnce2CoroutineFrame(IGF, bufferSize, mallocTypeId);
28122829
// TODO: CoroutineAccessors: Optimize allocator kind (e.g. async callers
28132830
// only need to use the TaskAllocator if the
28142831
// coroutine is suspended across an await).
2815-
coroAllocator = emitYieldOnce2CoroutineAllocator(
2816-
IGF, IGF.getDefaultCoroutineAllocatorKind());
2832+
coroAllocator = emitYieldOnce2CoroutineAllocator(IGF, kind);
28172833
}
28182834
}
28192835
void end() override { super::end(); }
@@ -5179,10 +5195,12 @@ void irgen::emitYieldOnce2CoroutineEntry(IRGenFunction &IGF,
51795195
auto deallocFn = IGF.IGM.getOpaquePtr(getCoroDeallocFn(IGF.IGM));
51805196
auto allocFrameFn = IGF.IGM.getOpaquePtr(getCoroAllocFrameFn(IGF.IGM));
51815197
auto deallocFrameFn = IGF.IGM.getOpaquePtr(getCoroDeallocFrameFn(IGF.IGM));
5198+
auto *typeID = IGF.getMallocTypeId();
51825199
emitRetconCoroutineEntry(
51835200
IGF, fnType, buffer, llvm::Intrinsic::coro_id_retcon_once_dynamic,
51845201
Size(-1) /*dynamic-to-IRGen size*/, IGF.IGM.getCoroStaticFrameAlignment(),
5185-
{cfp, allocator}, allocFn, deallocFn, {allocFrameFn, deallocFrameFn});
5202+
{cfp, allocator}, allocFn, deallocFn,
5203+
{allocFrameFn, deallocFrameFn, typeID});
51865204
}
51875205
void irgen::emitYieldOnce2CoroutineEntry(
51885206
IRGenFunction &IGF, LinkEntity coroFunction, CanSILFunctionType fnType,
@@ -5213,9 +5231,10 @@ Address irgen::emitAllocYieldManyCoroutineBuffer(IRGenFunction &IGF) {
52135231
getYieldManyCoroutineBufferAlignment(IGF.IGM));
52145232
}
52155233

5216-
StackAddress irgen::emitAllocYieldOnce2CoroutineFrame(IRGenFunction &IGF,
5217-
llvm::Value *size) {
5218-
return emitAllocCoroStaticFrame(IGF, size);
5234+
StackAddress
5235+
irgen::emitAllocYieldOnce2CoroutineFrame(IRGenFunction &IGF, llvm::Value *size,
5236+
llvm::Value *mallocTypeId) {
5237+
return emitAllocCoroStaticFrame(IGF, size, mallocTypeId);
52195238
}
52205239

52215240
void irgen::emitDeallocYieldOnceCoroutineBuffer(IRGenFunction &IGF,
@@ -5264,14 +5283,15 @@ void irgen::emitStaticDeallocAsyncContext(IRGenFunction &IGF, Address context,
52645283
}
52655284

52665285
StackAddress irgen::emitAllocCoroStaticFrame(IRGenFunction &IGF,
5267-
llvm::Value *size) {
5286+
llvm::Value *size,
5287+
llvm::Value *mallocTypeId) {
5288+
ASSERT(mallocTypeId);
52685289
// TODO: Avoid swift_task_alloc (async) and malloc (yield_once) if the
52695290
// suspension doesn't span an apply of an async function or a yield
52705291
// respectively.
5271-
auto retval = IGF.emitDynamicAlloca(
5272-
IGF.IGM.Int8Ty, size, Alignment(MaximumAlignment), AllowsTaskAlloc,
5273-
IsForCalleeCoroutineFrame_t(IGF.isCalleeAllocatedCoroutine()),
5274-
"callee-coro-frame");
5292+
auto retval =
5293+
IGF.emitDynamicAlloca(IGF.IGM.Int8Ty, size, Alignment(MaximumAlignment),
5294+
AllowsTaskAlloc, mallocTypeId, "callee-coro-frame");
52755295
IGF.Builder.CreateLifetimeStart(retval.getAddress(),
52765296
Size(-1) /*dynamic size*/);
52775297
return retval;

lib/IRGen/GenCall.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -143,9 +143,9 @@ namespace irgen {
143143
std::pair<llvm::Value *, llvm::Value *>
144144
getAsyncFunctionAndSize(IRGenFunction &IGF, FunctionPointer functionPointer,
145145
std::pair<bool, bool> values = {true, true});
146-
std::pair<llvm::Value *, llvm::Value *>
147-
getCoroFunctionAndSize(IRGenFunction &IGF, FunctionPointer functionPointer,
148-
std::pair<bool, bool> values = {true, true});
146+
std::tuple<llvm::Value *, llvm::Value *, llvm::Value *> getCoroFunctionValues(
147+
IRGenFunction &IGF, FunctionPointer functionPointer,
148+
std::tuple<bool, bool, bool> values = {true, true, true});
149149
llvm::CallingConv::ID
150150
expandCallingConv(IRGenModule &IGM, SILFunctionTypeRepresentation convention,
151151
bool isAsync, bool isCalleeAllocatedCoro);
@@ -221,7 +221,8 @@ namespace irgen {
221221
NativeCCEntryPointArgumentEmission &emission);
222222

223223
StackAddress emitAllocYieldOnce2CoroutineFrame(IRGenFunction &IGF,
224-
llvm::Value *size);
224+
llvm::Value *size,
225+
llvm::Value *mallocTypeId);
225226
void emitDeallocYieldOnce2CoroutineFrame(IRGenFunction &IGF,
226227
StackAddress allocation);
227228
void
@@ -252,7 +253,8 @@ namespace irgen {
252253
LinkEntity asyncFunction,
253254
unsigned asyncContextIndex);
254255

255-
StackAddress emitAllocCoroStaticFrame(IRGenFunction &IGF, llvm::Value *size);
256+
StackAddress emitAllocCoroStaticFrame(IRGenFunction &IGF, llvm::Value *size,
257+
llvm::Value *mallocTypeId);
256258
void emitDeallocCoroStaticFrame(IRGenFunction &IGF, StackAddress frame);
257259

258260
/// Yield the given values from the current continuation.

0 commit comments

Comments
 (0)