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 "swift/Runtime/Config.h"
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
||||||
namespace swift {
|
namespace swift {} // end namespace swift
|
||||||
SWIFT_RUNTIME_EXPORT
|
|
||||||
SWIFT_CC(swift) void swift_coro_dealloc(CoroAllocator *allocator, void *ptr);
|
|
||||||
} // end namespace swift
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -3008,16 +3008,6 @@ FUNCTION(MemsetS, c, memset_s, C_CC, AlwaysAvailable,
|
|||||||
EFFECT(RuntimeEffect::NoEffect),
|
EFFECT(RuntimeEffect::NoEffect),
|
||||||
UNKNOWN_MEMEFFECTS)
|
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 RETURNS
|
||||||
#undef ARGS
|
#undef ARGS
|
||||||
#undef ATTRS
|
#undef ATTRS
|
||||||
|
|||||||
@@ -5173,33 +5173,78 @@ static llvm::Constant *getCoroAllocFn(IRGenModule &IGM) {
|
|||||||
/*optionalLinkageOverride=*/nullptr, IGM.SwiftCoroCC);
|
/*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(
|
return IGM.getOrCreateHelperFunction(
|
||||||
"__swift_coro_dealloc_", IGM.VoidTy,
|
"_swift_coro_dealloc", IGM.VoidTy,
|
||||||
{IGM.CoroAllocatorPtrTy, IGM.Int8PtrTy},
|
{IGM.CoroAllocatorPtrTy, IGM.Int8PtrTy},
|
||||||
[](IRGenFunction &IGF) {
|
[isSwiftCoroCCAvailable](IRGenFunction &IGF) {
|
||||||
auto parameters = IGF.collectParameters();
|
auto parameters = IGF.collectParameters();
|
||||||
auto *allocator = parameters.claimNext();
|
auto *allocator = parameters.claimNext();
|
||||||
auto *ptr = parameters.claimNext();
|
auto *ptr = parameters.claimNext();
|
||||||
auto *nullAllocator = IGF.Builder.CreateCmp(
|
if (isSwiftCoroCCAvailable) {
|
||||||
llvm::CmpInst::Predicate::ICMP_EQ, allocator,
|
// swiftcorocc is available, so if there's no allocator pointer,
|
||||||
llvm::ConstantPointerNull::get(
|
// storage was allocated on the stack which will be naturally cleaned
|
||||||
cast<llvm::PointerType>(allocator->getType())));
|
// up when the coroutine's frame is "freed".
|
||||||
auto *bailBlock = IGF.createBasicBlock("bail");
|
auto *nullAllocator = IGF.Builder.CreateCmp(
|
||||||
auto *forwardBlock = IGF.createBasicBlock("forward");
|
llvm::CmpInst::Predicate::ICMP_EQ, allocator,
|
||||||
IGF.Builder.CreateCondBr(nullAllocator, bailBlock, forwardBlock);
|
llvm::ConstantPointerNull::get(
|
||||||
IGF.Builder.emitBlock(bailBlock);
|
cast<llvm::PointerType>(allocator->getType())));
|
||||||
// Emit the dynamic alloca.
|
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.CreateRetVoid();
|
||||||
IGF.Builder.emitBlock(forwardBlock);
|
// Start emitting the "normal" block.
|
||||||
IGF.Builder.CreateCall(
|
IGF.Builder.emitBlock(normalBlock);
|
||||||
IGF.IGM.getCoroDeallocFunctionPointer(), {allocator, ptr});
|
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();
|
IGF.Builder.CreateRetVoid();
|
||||||
},
|
},
|
||||||
/*setIsNoInline=*/false,
|
/*setIsNoInline=*/true,
|
||||||
/*forPrologue=*/false,
|
/*forPrologue=*/false,
|
||||||
/*isPerformanceConstraint=*/false,
|
/*isPerformanceConstraint=*/false,
|
||||||
/*optionalLinkageOverride=*/nullptr, llvm::CallingConv::SwiftCoro);
|
/*optionalLinkageOverride=*/nullptr, IGM.SwiftCoroCC);
|
||||||
}
|
}
|
||||||
|
|
||||||
void irgen::emitYieldOnce2CoroutineEntry(IRGenFunction &IGF,
|
void irgen::emitYieldOnce2CoroutineEntry(IRGenFunction &IGF,
|
||||||
@@ -5208,12 +5253,8 @@ void irgen::emitYieldOnce2CoroutineEntry(IRGenFunction &IGF,
|
|||||||
llvm::Value *allocator,
|
llvm::Value *allocator,
|
||||||
llvm::GlobalVariable *cfp) {
|
llvm::GlobalVariable *cfp) {
|
||||||
IGF.setCoroutineAllocator(allocator);
|
IGF.setCoroutineAllocator(allocator);
|
||||||
auto isSwiftCoroCCAvailable =
|
|
||||||
IGF.IGM.SwiftCoroCC == llvm::CallingConv::SwiftCoro;
|
|
||||||
auto allocFn = IGF.IGM.getOpaquePtr(getCoroAllocFn(IGF.IGM));
|
auto allocFn = IGF.IGM.getOpaquePtr(getCoroAllocFn(IGF.IGM));
|
||||||
auto deallocFn = IGF.IGM.getOpaquePtr(isSwiftCoroCCAvailable
|
auto deallocFn = IGF.IGM.getOpaquePtr(getCoroDeallocFn(IGF.IGM));
|
||||||
? getCoroDeallocWrapperFn(IGF.IGM)
|
|
||||||
: IGF.IGM.getCoroDeallocFn());
|
|
||||||
emitRetconCoroutineEntry(
|
emitRetconCoroutineEntry(
|
||||||
IGF, fnType, buffer, llvm::Intrinsic::coro_id_retcon_once_dynamic,
|
IGF, fnType, buffer, llvm::Intrinsic::coro_id_retcon_once_dynamic,
|
||||||
Size(-1) /*dynamic-to-IRGen size*/, IGF.IGM.getCoroStaticFrameAlignment(),
|
Size(-1) /*dynamic-to-IRGen size*/, IGF.IGM.getCoroStaticFrameAlignment(),
|
||||||
|
|||||||
@@ -15,14 +15,3 @@
|
|||||||
#include "swift/Basic/FlagSet.h"
|
#include "swift/Basic/FlagSet.h"
|
||||||
|
|
||||||
using namespace swift;
|
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: ret ptr [[ALLOCATION]]
|
||||||
// CHECK: }
|
// 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
|
@frozen
|
||||||
public struct S {
|
public struct S {
|
||||||
public var o: any AnyObject
|
public var o: any AnyObject
|
||||||
|
|||||||
@@ -52,7 +52,7 @@
|
|||||||
// CHECK: ret ptr [[ALLOCATION]]
|
// CHECK: ret ptr [[ALLOCATION]]
|
||||||
// CHECK: }
|
// CHECK: }
|
||||||
|
|
||||||
// CHECK-LABEL: @__swift_coro_dealloc_(
|
// CHECK-LABEL: @_swift_coro_dealloc(
|
||||||
// CHECK-SAME: ptr [[ALLOCATOR:%[^,]+]]
|
// CHECK-SAME: ptr [[ALLOCATOR:%[^,]+]]
|
||||||
// CHECK-SAME: ptr [[ADDRESS:%[^)]+]]
|
// CHECK-SAME: ptr [[ADDRESS:%[^)]+]]
|
||||||
// CHECK-SAME: )
|
// CHECK-SAME: )
|
||||||
@@ -60,15 +60,30 @@
|
|||||||
// CHECK: entry:
|
// CHECK: entry:
|
||||||
// CHECK: [[BAIL:%[^,]+]] = icmp eq ptr [[ALLOCATOR]], null
|
// CHECK: [[BAIL:%[^,]+]] = icmp eq ptr [[ALLOCATOR]], null
|
||||||
// CHECK: br i1 [[USE_POPLESS]],
|
// CHECK: br i1 [[USE_POPLESS]],
|
||||||
// CHECK-SAME: label %bail
|
// CHECK-SAME: label %null_allocator
|
||||||
// CHECK-SAME: label %forward
|
// CHECK-SAME: label %nonnull_allocator
|
||||||
// CHECK: bail:
|
// CHECK: null_allocator:
|
||||||
// CHECK: ret void
|
// CHECK: ret void
|
||||||
// CHECK: forward:
|
// CHECK: nonnull_allocator:
|
||||||
// CHECK: call swiftcc void @swift_coro_dealloc(
|
// CHECK: [[FLAGS_ADDR:%[^,]+]] = getelementptr inbounds %swift.coro_allocator
|
||||||
// CHECK-SAME: ptr [[ALLOCATOR]]
|
// CHECK-SAME: ptr [[ALLOCATOR]]
|
||||||
// CHECK-SAME: ptr [[ADDRESS]]
|
// CHECK-SAME: i32 0
|
||||||
// CHECK-SAME: )
|
// 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: ret void
|
||||||
// CHECK: }
|
// CHECK: }
|
||||||
|
|
||||||
|
|||||||
@@ -942,7 +942,3 @@ Added: _$ss18EnumeratedSequenceVsSlRzrlE7isEmptySbvpMV
|
|||||||
Added: _$ss18EnumeratedSequenceVsSlRzrlE8endIndexABsSlRzrlE0D0Vyx_GvpMV
|
Added: _$ss18EnumeratedSequenceVsSlRzrlE8endIndexABsSlRzrlE0D0Vyx_GvpMV
|
||||||
Added: _$ss18EnumeratedSequenceVsSlRzrlEySi6offset_7ElementQz7elementtABsSlRzrlE5IndexVyx_GcipMV
|
Added: _$ss18EnumeratedSequenceVsSlRzrlEySi6offset_7ElementQz7elementtABsSlRzrlE5IndexVyx_GcipMV
|
||||||
Added: _$ss18EnumeratedSequenceVyxGSKsSkRzrlMc
|
Added: _$ss18EnumeratedSequenceVyxGSKsSkRzrlMc
|
||||||
|
|
||||||
// CoroutineAccessors
|
|
||||||
Added: _swift_coro_alloc
|
|
||||||
Added: _swift_coro_dealloc
|
|
||||||
|
|||||||
@@ -942,7 +942,3 @@ Added: _$ss18EnumeratedSequenceVsSlRzrlE7isEmptySbvpMV
|
|||||||
Added: _$ss18EnumeratedSequenceVsSlRzrlE8endIndexABsSlRzrlE0D0Vyx_GvpMV
|
Added: _$ss18EnumeratedSequenceVsSlRzrlE8endIndexABsSlRzrlE0D0Vyx_GvpMV
|
||||||
Added: _$ss18EnumeratedSequenceVsSlRzrlEySi6offset_7ElementQz7elementtABsSlRzrlE5IndexVyx_GcipMV
|
Added: _$ss18EnumeratedSequenceVsSlRzrlEySi6offset_7ElementQz7elementtABsSlRzrlE5IndexVyx_GcipMV
|
||||||
Added: _$ss18EnumeratedSequenceVyxGSKsSkRzrlMc
|
Added: _$ss18EnumeratedSequenceVyxGSKsSkRzrlMc
|
||||||
|
|
||||||
// CoroutineAccessors
|
|
||||||
Added: _swift_coro_alloc
|
|
||||||
Added: _swift_coro_dealloc
|
|
||||||
|
|||||||
Reference in New Issue
Block a user