mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[CoroutineAccessors] Open code dealloc fn.
This commit is contained in:
@@ -21,9 +21,6 @@
|
||||
#include "swift/Runtime/Config.h"
|
||||
#include <cstddef>
|
||||
|
||||
namespace swift {
|
||||
SWIFT_RUNTIME_EXPORT
|
||||
SWIFT_CC(swift) void swift_coro_dealloc(CoroAllocator *allocator, void *ptr);
|
||||
} // end namespace swift
|
||||
namespace swift {} // end namespace swift
|
||||
|
||||
#endif
|
||||
|
||||
@@ -3008,16 +3008,6 @@ FUNCTION(MemsetS, c, memset_s, C_CC, AlwaysAvailable,
|
||||
EFFECT(RuntimeEffect::NoEffect),
|
||||
UNKNOWN_MEMEFFECTS)
|
||||
|
||||
// void swift_coro_dealloc(CoroAllocator *, void *ptr);
|
||||
FUNCTION(CoroDealloc,
|
||||
Swift, swift_coro_dealloc, SwiftCC,
|
||||
CoroutineAccessorsAvailability,
|
||||
RETURNS(VoidTy),
|
||||
ARGS(CoroAllocatorPtrTy, Int8PtrTy),
|
||||
NO_ATTRS,
|
||||
EFFECT(RuntimeEffect::Deallocating, RuntimeEffect::Concurrency),
|
||||
UNKNOWN_MEMEFFECTS)
|
||||
|
||||
#undef RETURNS
|
||||
#undef ARGS
|
||||
#undef ATTRS
|
||||
|
||||
@@ -5173,33 +5173,78 @@ static llvm::Constant *getCoroAllocFn(IRGenModule &IGM) {
|
||||
/*optionalLinkageOverride=*/nullptr, IGM.SwiftCoroCC);
|
||||
}
|
||||
|
||||
static llvm::Constant *getCoroDeallocWrapperFn(IRGenModule &IGM) {
|
||||
static llvm::Constant *getCoroDeallocFn(IRGenModule &IGM) {
|
||||
auto isSwiftCoroCCAvailable = IGM.SwiftCoroCC == llvm::CallingConv::SwiftCoro;
|
||||
return IGM.getOrCreateHelperFunction(
|
||||
"__swift_coro_dealloc_", IGM.VoidTy,
|
||||
"_swift_coro_dealloc", IGM.VoidTy,
|
||||
{IGM.CoroAllocatorPtrTy, IGM.Int8PtrTy},
|
||||
[](IRGenFunction &IGF) {
|
||||
[isSwiftCoroCCAvailable](IRGenFunction &IGF) {
|
||||
auto parameters = IGF.collectParameters();
|
||||
auto *allocator = parameters.claimNext();
|
||||
auto *ptr = parameters.claimNext();
|
||||
auto *nullAllocator = IGF.Builder.CreateCmp(
|
||||
llvm::CmpInst::Predicate::ICMP_EQ, allocator,
|
||||
llvm::ConstantPointerNull::get(
|
||||
cast<llvm::PointerType>(allocator->getType())));
|
||||
auto *bailBlock = IGF.createBasicBlock("bail");
|
||||
auto *forwardBlock = IGF.createBasicBlock("forward");
|
||||
IGF.Builder.CreateCondBr(nullAllocator, bailBlock, forwardBlock);
|
||||
IGF.Builder.emitBlock(bailBlock);
|
||||
// Emit the dynamic alloca.
|
||||
if (isSwiftCoroCCAvailable) {
|
||||
// swiftcorocc is available, so if there's no allocator pointer,
|
||||
// storage was allocated on the stack which will be naturally cleaned
|
||||
// up when the coroutine's frame is "freed".
|
||||
auto *nullAllocator = IGF.Builder.CreateCmp(
|
||||
llvm::CmpInst::Predicate::ICMP_EQ, allocator,
|
||||
llvm::ConstantPointerNull::get(
|
||||
cast<llvm::PointerType>(allocator->getType())));
|
||||
auto *bailBlock = IGF.createBasicBlock("null_allocator");
|
||||
auto *normalBlock = IGF.createBasicBlock("nonnull_allocator");
|
||||
IGF.Builder.CreateCondBr(nullAllocator, bailBlock, normalBlock);
|
||||
IGF.Builder.emitBlock(bailBlock);
|
||||
// Nothing to do here.
|
||||
IGF.Builder.CreateRetVoid();
|
||||
// Start emitting the "normal" block.
|
||||
IGF.Builder.emitBlock(normalBlock);
|
||||
}
|
||||
auto shouldDeallocateImmediatelyFlag = CoroAllocatorFlags(0);
|
||||
shouldDeallocateImmediatelyFlag.setShouldDeallocateImmediately(true);
|
||||
auto *flagsPtr = IGF.Builder.CreateInBoundsGEP(
|
||||
IGF.IGM.CoroAllocatorTy, allocator,
|
||||
{llvm::ConstantInt::get(IGF.IGM.Int32Ty, 0),
|
||||
llvm::ConstantInt::get(IGF.IGM.Int32Ty, 0)});
|
||||
auto *flags = IGF.Builder.CreateLoad(
|
||||
Address(flagsPtr, IGF.IGM.Int32Ty, Alignment(4)), "");
|
||||
auto *deallocDeferringAllocator = IGF.Builder.CreateAnd(
|
||||
flags,
|
||||
llvm::APInt(IGF.IGM.Int32Ty->getBitWidth(),
|
||||
shouldDeallocateImmediatelyFlag.getOpaqueValue()));
|
||||
auto *isDeallocDeferringAllocator = IGF.Builder.CreateICmpNE(
|
||||
deallocDeferringAllocator,
|
||||
llvm::ConstantInt::get(IGF.IGM.Int32Ty, 0));
|
||||
auto *deferringAllocatorBlock =
|
||||
IGF.createBasicBlock("deferring_allocator");
|
||||
auto *normalBlock = IGF.createBasicBlock("normal");
|
||||
IGF.Builder.CreateCondBr(isDeallocDeferringAllocator,
|
||||
deferringAllocatorBlock, normalBlock);
|
||||
IGF.Builder.emitBlock(deferringAllocatorBlock);
|
||||
// Nothing to do here.
|
||||
IGF.Builder.CreateRetVoid();
|
||||
IGF.Builder.emitBlock(forwardBlock);
|
||||
IGF.Builder.CreateCall(
|
||||
IGF.IGM.getCoroDeallocFunctionPointer(), {allocator, ptr});
|
||||
// Start emitting the "normal" block.
|
||||
IGF.Builder.emitBlock(normalBlock);
|
||||
auto *calleePtr = IGF.Builder.CreateInBoundsGEP(
|
||||
IGF.IGM.CoroAllocatorTy, allocator,
|
||||
{llvm::ConstantInt::get(IGF.IGM.Int32Ty, 0),
|
||||
llvm::ConstantInt::get(IGF.IGM.Int32Ty, 2)});
|
||||
auto *callee = IGF.Builder.CreateLoad(
|
||||
Address(calleePtr, IGF.IGM.CoroDeallocateFnTy->getPointerTo(),
|
||||
IGF.IGM.getPointerAlignment()),
|
||||
"deallocate_fn");
|
||||
auto fnPtr = FunctionPointer::createUnsigned(
|
||||
FunctionPointer::Kind::Function, callee,
|
||||
Signature(cast<llvm::FunctionType>(IGF.IGM.CoroDeallocateFnTy), {},
|
||||
IGF.IGM.SwiftCC));
|
||||
auto *call = IGF.Builder.CreateCall(fnPtr, {ptr});
|
||||
call->setDoesNotThrow();
|
||||
call->setCallingConv(IGF.IGM.SwiftCC);
|
||||
IGF.Builder.CreateRetVoid();
|
||||
},
|
||||
/*setIsNoInline=*/false,
|
||||
/*setIsNoInline=*/true,
|
||||
/*forPrologue=*/false,
|
||||
/*isPerformanceConstraint=*/false,
|
||||
/*optionalLinkageOverride=*/nullptr, llvm::CallingConv::SwiftCoro);
|
||||
/*optionalLinkageOverride=*/nullptr, IGM.SwiftCoroCC);
|
||||
}
|
||||
|
||||
void irgen::emitYieldOnce2CoroutineEntry(IRGenFunction &IGF,
|
||||
@@ -5208,12 +5253,8 @@ void irgen::emitYieldOnce2CoroutineEntry(IRGenFunction &IGF,
|
||||
llvm::Value *allocator,
|
||||
llvm::GlobalVariable *cfp) {
|
||||
IGF.setCoroutineAllocator(allocator);
|
||||
auto isSwiftCoroCCAvailable =
|
||||
IGF.IGM.SwiftCoroCC == llvm::CallingConv::SwiftCoro;
|
||||
auto allocFn = IGF.IGM.getOpaquePtr(getCoroAllocFn(IGF.IGM));
|
||||
auto deallocFn = IGF.IGM.getOpaquePtr(isSwiftCoroCCAvailable
|
||||
? getCoroDeallocWrapperFn(IGF.IGM)
|
||||
: IGF.IGM.getCoroDeallocFn());
|
||||
auto deallocFn = IGF.IGM.getOpaquePtr(getCoroDeallocFn(IGF.IGM));
|
||||
emitRetconCoroutineEntry(
|
||||
IGF, fnType, buffer, llvm::Intrinsic::coro_id_retcon_once_dynamic,
|
||||
Size(-1) /*dynamic-to-IRGen size*/, IGF.IGM.getCoroStaticFrameAlignment(),
|
||||
|
||||
@@ -15,14 +15,3 @@
|
||||
#include "swift/Basic/FlagSet.h"
|
||||
|
||||
using namespace swift;
|
||||
|
||||
void swift::swift_coro_dealloc(CoroAllocator *allocator, void *ptr) {
|
||||
assert(allocator);
|
||||
// Calls to swift_coro_dealloc are emitted in resume funclets for every
|
||||
// live-across dynamic allocation. Whether such calls immediately deallocate
|
||||
// memory depends on the allocator.
|
||||
if (!allocator->shouldDeallocateImmediately()) {
|
||||
return;
|
||||
}
|
||||
allocator->deallocate(ptr);
|
||||
}
|
||||
|
||||
@@ -39,6 +39,34 @@
|
||||
// CHECK: ret ptr [[ALLOCATION]]
|
||||
// CHECK: }
|
||||
|
||||
// CHECK-LABEL: @_swift_coro_dealloc(
|
||||
// CHECK-SAME: ptr [[ALLOCATOR:%[^,]+]]
|
||||
// CHECK-SAME: ptr [[ADDRESS:%[^)]+]]
|
||||
// CHECK-SAME: )
|
||||
// CHECK-SAME: {
|
||||
// CHECK: entry:
|
||||
// CHECK: [[FLAGS_ADDR:%[^,]+]] = getelementptr inbounds %swift.coro_allocator
|
||||
// CHECK-SAME: ptr [[ALLOCATOR]]
|
||||
// CHECK-SAME: i32 0
|
||||
// CHECK-SAME: i32 0
|
||||
// CHECK: [[FLAGS:%[^,]+]] = load i32, ptr [[FLAGS_ADDR]], align 4
|
||||
// CHECK: [[DEALLOC_DEFERRING_ALLOCATOR:%[^,]+]] = and i32 [[FLAGS]], 256
|
||||
// CHECK: [[IS_DEALLOC_DEFERRING_ALLOCATOR:%[^,]+]] = icmp ne i32 [[DEALLOC_DEFERRING_ALLOCATOR]], 0
|
||||
// CHECK: br i1 [[IS_DEALLOC_DEFERRING_ALLOCATOR]]
|
||||
// CHECK-SAME: label %deferring_allocator
|
||||
// CHECK-SAME: label %normal
|
||||
// CHECK: deferring_allocator:
|
||||
// CHECK: ret void
|
||||
// CHECK: normal:
|
||||
// CHECK: [[DEALLOCATE_FN_PTR:%[^,]+]] = getelementptr inbounds %swift.coro_allocator
|
||||
// CHECK-SAME: ptr [[ALLOCATOR]]
|
||||
// CHECK-SAME: i32 0
|
||||
// CHECK-SAME: i32 2
|
||||
// CHECK: [[DEALLOCATE_FN:%[^,]+]] = load ptr, ptr [[DEALLOCATE_FN_PTR]]
|
||||
// CHECK: call swiftcc void [[DEALLOCATE_FN]](ptr [[ADDRESS]])
|
||||
// CHECK: ret void
|
||||
// CHECK: }
|
||||
|
||||
@frozen
|
||||
public struct S {
|
||||
public var o: any AnyObject
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
// CHECK: ret ptr [[ALLOCATION]]
|
||||
// CHECK: }
|
||||
|
||||
// CHECK-LABEL: @__swift_coro_dealloc_(
|
||||
// CHECK-LABEL: @_swift_coro_dealloc(
|
||||
// CHECK-SAME: ptr [[ALLOCATOR:%[^,]+]]
|
||||
// CHECK-SAME: ptr [[ADDRESS:%[^)]+]]
|
||||
// CHECK-SAME: )
|
||||
@@ -60,15 +60,30 @@
|
||||
// CHECK: entry:
|
||||
// CHECK: [[BAIL:%[^,]+]] = icmp eq ptr [[ALLOCATOR]], null
|
||||
// CHECK: br i1 [[USE_POPLESS]],
|
||||
// CHECK-SAME: label %bail
|
||||
// CHECK-SAME: label %forward
|
||||
// CHECK: bail:
|
||||
// CHECK-SAME: label %null_allocator
|
||||
// CHECK-SAME: label %nonnull_allocator
|
||||
// CHECK: null_allocator:
|
||||
// CHECK: ret void
|
||||
// CHECK: forward:
|
||||
// CHECK: call swiftcc void @swift_coro_dealloc(
|
||||
// CHECK: nonnull_allocator:
|
||||
// CHECK: [[FLAGS_ADDR:%[^,]+]] = getelementptr inbounds %swift.coro_allocator
|
||||
// CHECK-SAME: ptr [[ALLOCATOR]]
|
||||
// CHECK-SAME: ptr [[ADDRESS]]
|
||||
// CHECK-SAME: )
|
||||
// CHECK-SAME: i32 0
|
||||
// CHECK-SAME: i32 0
|
||||
// CHECK: [[FLAGS:%[^,]+]] = load i32, ptr [[FLAGS_ADDR]], align 4
|
||||
// CHECK: [[DEALLOC_DEFERRING_ALLOCATOR:%[^,]+]] = and i32 [[FLAGS]], 256
|
||||
// CHECK: [[IS_DEALLOC_DEFERRING_ALLOCATOR:%[^,]+]] = icmp ne i32 [[DEALLOC_DEFERRING_ALLOCATOR]], 0
|
||||
// CHECK: br i1 [[IS_DEALLOC_DEFERRING_ALLOCATOR]]
|
||||
// CHECK-SAME: label %deferring_allocator
|
||||
// CHECK-SAME: label %normal
|
||||
// CHECK: deferring_allocator:
|
||||
// CHECK: ret void
|
||||
// CHECK: normal:
|
||||
// CHECK: [[DEALLOCATE_FN_PTR:%[^,]+]] = getelementptr inbounds %swift.coro_allocator
|
||||
// CHECK-SAME: ptr [[ALLOCATOR]]
|
||||
// CHECK-SAME: i32 0
|
||||
// CHECK-SAME: i32 2
|
||||
// CHECK: [[DEALLOCATE_FN:%[^,]+]] = load ptr, ptr [[DEALLOCATE_FN_PTR]]
|
||||
// CHECK: call swiftcc void [[DEALLOCATE_FN]](ptr [[ADDRESS]])
|
||||
// CHECK: ret void
|
||||
// CHECK: }
|
||||
|
||||
|
||||
@@ -942,7 +942,3 @@ Added: _$ss18EnumeratedSequenceVsSlRzrlE7isEmptySbvpMV
|
||||
Added: _$ss18EnumeratedSequenceVsSlRzrlE8endIndexABsSlRzrlE0D0Vyx_GvpMV
|
||||
Added: _$ss18EnumeratedSequenceVsSlRzrlEySi6offset_7ElementQz7elementtABsSlRzrlE5IndexVyx_GcipMV
|
||||
Added: _$ss18EnumeratedSequenceVyxGSKsSkRzrlMc
|
||||
|
||||
// CoroutineAccessors
|
||||
Added: _swift_coro_alloc
|
||||
Added: _swift_coro_dealloc
|
||||
|
||||
@@ -942,7 +942,3 @@ Added: _$ss18EnumeratedSequenceVsSlRzrlE7isEmptySbvpMV
|
||||
Added: _$ss18EnumeratedSequenceVsSlRzrlE8endIndexABsSlRzrlE0D0Vyx_GvpMV
|
||||
Added: _$ss18EnumeratedSequenceVsSlRzrlEySi6offset_7ElementQz7elementtABsSlRzrlE5IndexVyx_GcipMV
|
||||
Added: _$ss18EnumeratedSequenceVyxGSKsSkRzrlMc
|
||||
|
||||
// CoroutineAccessors
|
||||
Added: _swift_coro_alloc
|
||||
Added: _swift_coro_dealloc
|
||||
|
||||
Reference in New Issue
Block a user