10
10
//
11
11
// ===----------------------------------------------------------------------===//
12
12
13
+ #include " Cleanup.h"
13
14
#include " Initialization.h"
14
15
#include " LValue.h"
15
16
#include " RValue.h"
@@ -682,10 +683,18 @@ namespace {
682
683
683
684
static void deallocateAddressable (SILGenFunction &SGF,
684
685
SILLocation l,
685
- const SILGenFunction::AddressableBuffer::State &state) {
686
- SGF.B .createEndBorrow (l, state.storeBorrow );
686
+ const SILGenFunction::AddressableBuffer::State &state,
687
+ CleanupState cleanupState) {
688
+ // Only delete the value if the variable was active on this path.
689
+ // The stack slot exists within the variable scope regardless, so always
690
+ // needs to be cleaned up.
691
+ bool active = isActiveCleanupState (cleanupState);
692
+ if (active) {
693
+ SGF.B .createEndBorrow (l, state.storeBorrow );
694
+ }
687
695
SGF.B .createDeallocStack (l, state.allocStack );
688
- if (state.reabstraction
696
+ if (active
697
+ && state.reabstraction
689
698
&& !state.reabstraction ->getType ().isTrivial (SGF.F )) {
690
699
SGF.B .createDestroyValue (l, state.reabstraction );
691
700
}
@@ -695,8 +704,11 @@ static void deallocateAddressable(SILGenFunction &SGF,
695
704
// / binding.
696
705
class DeallocateLocalVariableAddressableBuffer : public Cleanup {
697
706
ValueDecl *vd;
707
+ CleanupHandle destroyVarHandle;
698
708
public:
699
- DeallocateLocalVariableAddressableBuffer (ValueDecl *vd) : vd(vd) {}
709
+ DeallocateLocalVariableAddressableBuffer (ValueDecl *vd,
710
+ CleanupHandle destroyVarHandle)
711
+ : vd(vd), destroyVarHandle(destroyVarHandle) {}
700
712
701
713
void emit (SILGenFunction &SGF, CleanupLocation l,
702
714
ForUnwind_t forUnwind) override {
@@ -705,14 +717,20 @@ class DeallocateLocalVariableAddressableBuffer : public Cleanup {
705
717
return ;
706
718
}
707
719
720
+ // Reflect the state of the variable's original cleanup.
721
+ CleanupState cleanupState = CleanupState::Active;
722
+ if (destroyVarHandle.isValid ()) {
723
+ cleanupState = SGF.Cleanups .getCleanup (destroyVarHandle).getState ();
724
+ }
725
+
708
726
if (auto *state = addressableBuffer->getState ()) {
709
- // The addressable buffer was forced, so clean it up now.
710
- deallocateAddressable (SGF, l, *state);
727
+ // The addressable buffer was already forced, so clean up now.
728
+ deallocateAddressable (SGF, l, *state, cleanupState );
711
729
} else {
712
730
// Remember this insert location in case we need to force the addressable
713
731
// buffer later.
714
732
SILInstruction *marker = SGF.B .createTuple (l, {});
715
- addressableBuffer->cleanupPoints .emplace_back ( marker);
733
+ addressableBuffer->cleanupPoints .push_back ({ marker, cleanupState} );
716
734
}
717
735
}
718
736
@@ -820,7 +838,7 @@ class LetValueInitialization : public Initialization {
820
838
821
839
// If the binding has an addressable buffer forced, it should be cleaned
822
840
// up at this scope.
823
- SGF.enterLocalVariableAddressableBufferScope (vd);
841
+ SGF.enterLocalVariableAddressableBufferScope (vd, DestroyCleanup );
824
842
}
825
843
826
844
~LetValueInitialization () override {
@@ -2237,10 +2255,11 @@ void SILGenFunction::destroyLocalVariable(SILLocation silLoc, VarDecl *vd) {
2237
2255
}
2238
2256
2239
2257
void
2240
- SILGenFunction::enterLocalVariableAddressableBufferScope (VarDecl *decl) {
2258
+ SILGenFunction::enterLocalVariableAddressableBufferScope (VarDecl *decl,
2259
+ CleanupHandle destroyCleanup) {
2241
2260
auto marker = B.createTuple (decl, {});
2242
2261
AddressableBuffers[decl].insertPoint = marker;
2243
- Cleanups.pushCleanup <DeallocateLocalVariableAddressableBuffer>(decl);
2262
+ Cleanups.pushCleanup <DeallocateLocalVariableAddressableBuffer>(decl, destroyCleanup );
2244
2263
}
2245
2264
2246
2265
SILValue
@@ -2355,10 +2374,11 @@ SILGenFunction::getLocalVariableAddressableBuffer(VarDecl *decl,
2355
2374
decltype (addressableBuffer->cleanupPoints ) cleanupPoints;
2356
2375
cleanupPoints.swap (addressableBuffer->cleanupPoints );
2357
2376
2358
- for (SILInstruction *cleanupPoint : cleanupPoints) {
2359
- SavedInsertionPointRAII insertCleanup (B, cleanupPoint);
2360
- deallocateAddressable (*this , cleanupPoint->getLoc (), *newState);
2361
- cleanupPoint->eraseFromParent ();
2377
+ for (auto &cleanupPoint : cleanupPoints) {
2378
+ SavedInsertionPointRAII insertCleanup (B, cleanupPoint.inst );
2379
+ deallocateAddressable (*this , cleanupPoint.inst ->getLoc (), *newState,
2380
+ cleanupPoint.state );
2381
+ cleanupPoint.inst ->eraseFromParent ();
2362
2382
}
2363
2383
2364
2384
return storeBorrow;
@@ -2400,8 +2420,8 @@ SILGenFunction::AddressableBuffer::~AddressableBuffer() {
2400
2420
if (insertPoint) {
2401
2421
insertPoint->eraseFromParent ();
2402
2422
}
2403
- for (auto cleanupPoint : cleanupPoints) {
2404
- cleanupPoint->eraseFromParent ();
2423
+ for (auto & cleanupPoint : cleanupPoints) {
2424
+ cleanupPoint. inst ->eraseFromParent ();
2405
2425
}
2406
2426
if (auto state = stateOrAlias.dyn_cast <State*>()) {
2407
2427
delete state;
0 commit comments