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::VarLoc::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,28 +704,33 @@ 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 {
703
715
auto addressableBuffer = SGF.getAddressableBufferInfo (vd);
704
716
if (!addressableBuffer) {
705
717
return ;
706
718
}
707
- auto found = SGF.VarLocs .find (vd);
708
- if (found == SGF.VarLocs .end ()) {
709
- return ;
710
- }
711
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
+
712
726
if (auto *state = addressableBuffer->getState ()) {
713
- // The addressable buffer was forced, so clean it up now.
714
- deallocateAddressable (SGF, l, *state);
727
+ // The addressable buffer was already forced, so clean up now.
728
+ deallocateAddressable (SGF, l, *state, cleanupState );
715
729
} else {
716
730
// Remember this insert location in case we need to force the addressable
717
731
// buffer later.
718
732
SILInstruction *marker = SGF.B .createTuple (l, {});
719
- addressableBuffer->cleanupPoints .emplace_back ( marker);
733
+ addressableBuffer->cleanupPoints .push_back ({ marker, cleanupState} );
720
734
}
721
735
}
722
736
@@ -824,7 +838,7 @@ class LetValueInitialization : public Initialization {
824
838
825
839
// If the binding has an addressable buffer forced, it should be cleaned
826
840
// up at this scope.
827
- SGF.enterLocalVariableAddressableBufferScope (vd);
841
+ SGF.enterLocalVariableAddressableBufferScope (vd, DestroyCleanup );
828
842
}
829
843
830
844
~LetValueInitialization () override {
@@ -2241,10 +2255,11 @@ void SILGenFunction::destroyLocalVariable(SILLocation silLoc, VarDecl *vd) {
2241
2255
}
2242
2256
2243
2257
void
2244
- SILGenFunction::enterLocalVariableAddressableBufferScope (VarDecl *decl) {
2258
+ SILGenFunction::enterLocalVariableAddressableBufferScope (VarDecl *decl,
2259
+ CleanupHandle destroyCleanup) {
2245
2260
auto marker = B.createTuple (decl, {});
2246
- AddressableBuffers[decl] = marker;
2247
- Cleanups.pushCleanup <DeallocateLocalVariableAddressableBuffer>(decl);
2261
+ AddressableBuffers[decl]. insertPoint = marker;
2262
+ Cleanups.pushCleanup <DeallocateLocalVariableAddressableBuffer>(decl, destroyCleanup );
2248
2263
}
2249
2264
2250
2265
SILValue
@@ -2296,27 +2311,12 @@ SILGenFunction::getLocalVariableAddressableBuffer(VarDecl *decl,
2296
2311
SILValue reabstraction, allocStack, storeBorrow;
2297
2312
{
2298
2313
SavedInsertionPointRAII save (B);
2299
- SILInstruction *insertPoint = nullptr ;
2300
- // Look through bindings that might alias the original addressable buffer
2301
- // (such as case block variables, which use an alias variable to represent the
2302
- // incoming value from all of the case label patterns).
2303
- VarDecl *origDecl = decl;
2304
- do {
2305
- auto bufferIter = AddressableBuffers.find (origDecl);
2306
- ASSERT (bufferIter != AddressableBuffers.end ()
2307
- && " local variable didn't have an addressability scope set" );
2308
-
2309
- insertPoint = bufferIter->second .getInsertPoint ();
2310
- if (insertPoint) {
2311
- break ;
2312
- }
2314
+ auto *addressableBuffer = getAddressableBufferInfo (decl);
2313
2315
2314
- origDecl = bufferIter->second .getOriginalForAlias ();
2315
- ASSERT (origDecl && " no insert point or alias for addressable declaration!" );
2316
- } while (true );
2317
-
2318
- assert (insertPoint && " didn't find an insertion point for the addressable buffer" );
2319
- B.setInsertionPoint (insertPoint);
2316
+ assert (addressableBuffer
2317
+ && addressableBuffer->insertPoint
2318
+ && " didn't find an insertion point for the addressable buffer" );
2319
+ B.setInsertionPoint (addressableBuffer->insertPoint );
2320
2320
auto allocStackTy = fullyAbstractedTy;
2321
2321
if (value->getType ().isMoveOnlyWrapped ()) {
2322
2322
allocStackTy = allocStackTy.addingMoveOnlyWrapper ();
@@ -2366,18 +2366,19 @@ SILGenFunction::getLocalVariableAddressableBuffer(VarDecl *decl,
2366
2366
// Record the addressable representation.
2367
2367
auto *addressableBuffer = getAddressableBufferInfo (decl);
2368
2368
auto *newState
2369
- = new VarLoc:: AddressableBuffer::State (reabstraction, allocStack, storeBorrow);
2369
+ = new AddressableBuffer::State (reabstraction, allocStack, storeBorrow);
2370
2370
addressableBuffer->stateOrAlias = newState;
2371
2371
2372
2372
// Emit cleanups on any paths where we previously would have cleaned up
2373
2373
// the addressable representation if it had been forced earlier.
2374
2374
decltype (addressableBuffer->cleanupPoints ) cleanupPoints;
2375
2375
cleanupPoints.swap (addressableBuffer->cleanupPoints );
2376
2376
2377
- for (SILInstruction *cleanupPoint : cleanupPoints) {
2378
- SavedInsertionPointRAII insertCleanup (B, cleanupPoint);
2379
- deallocateAddressable (*this , cleanupPoint->getLoc (), *newState);
2380
- 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 ();
2381
2382
}
2382
2383
2383
2384
return storeBorrow;
@@ -2415,9 +2416,12 @@ void BlackHoleInitialization::copyOrInitValueInto(SILGenFunction &SGF, SILLocati
2415
2416
SGF.B .createIgnoredUse (loc, value.getValue ());
2416
2417
}
2417
2418
2418
- SILGenFunction::VarLoc::AddressableBuffer::~AddressableBuffer () {
2419
- for (auto cleanupPoint : cleanupPoints) {
2420
- cleanupPoint->eraseFromParent ();
2419
+ SILGenFunction::AddressableBuffer::~AddressableBuffer () {
2420
+ if (insertPoint) {
2421
+ insertPoint->eraseFromParent ();
2422
+ }
2423
+ for (auto &cleanupPoint : cleanupPoints) {
2424
+ cleanupPoint.inst ->eraseFromParent ();
2421
2425
}
2422
2426
if (auto state = stateOrAlias.dyn_cast <State*>()) {
2423
2427
delete state;
0 commit comments