1010//
1111// ===----------------------------------------------------------------------===//
1212
13+ #include " Cleanup.h"
1314#include " Initialization.h"
1415#include " LValue.h"
1516#include " RValue.h"
@@ -682,10 +683,18 @@ namespace {
682683
683684static void deallocateAddressable (SILGenFunction &SGF,
684685 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+ }
687695 SGF.B .createDeallocStack (l, state.allocStack );
688- if (state.reabstraction
696+ if (active
697+ && state.reabstraction
689698 && !state.reabstraction ->getType ().isTrivial (SGF.F )) {
690699 SGF.B .createDestroyValue (l, state.reabstraction );
691700 }
@@ -695,28 +704,33 @@ static void deallocateAddressable(SILGenFunction &SGF,
695704// / binding.
696705class DeallocateLocalVariableAddressableBuffer : public Cleanup {
697706 ValueDecl *vd;
707+ CleanupHandle destroyVarHandle;
698708public:
699- DeallocateLocalVariableAddressableBuffer (ValueDecl *vd) : vd(vd) {}
709+ DeallocateLocalVariableAddressableBuffer (ValueDecl *vd,
710+ CleanupHandle destroyVarHandle)
711+ : vd(vd), destroyVarHandle(destroyVarHandle) {}
700712
701713 void emit (SILGenFunction &SGF, CleanupLocation l,
702714 ForUnwind_t forUnwind) override {
703715 auto addressableBuffer = SGF.getAddressableBufferInfo (vd);
704716 if (!addressableBuffer) {
705717 return ;
706718 }
707- auto found = SGF.VarLocs .find (vd);
708- if (found == SGF.VarLocs .end ()) {
709- return ;
710- }
711719
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+
712726 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 );
715729 } else {
716730 // Remember this insert location in case we need to force the addressable
717731 // buffer later.
718732 SILInstruction *marker = SGF.B .createTuple (l, {});
719- addressableBuffer->cleanupPoints .emplace_back ( marker);
733+ addressableBuffer->cleanupPoints .push_back ({ marker, cleanupState} );
720734 }
721735 }
722736
@@ -824,7 +838,7 @@ class LetValueInitialization : public Initialization {
824838
825839 // If the binding has an addressable buffer forced, it should be cleaned
826840 // up at this scope.
827- SGF.enterLocalVariableAddressableBufferScope (vd);
841+ SGF.enterLocalVariableAddressableBufferScope (vd, DestroyCleanup );
828842 }
829843
830844 ~LetValueInitialization () override {
@@ -2241,10 +2255,11 @@ void SILGenFunction::destroyLocalVariable(SILLocation silLoc, VarDecl *vd) {
22412255}
22422256
22432257void
2244- SILGenFunction::enterLocalVariableAddressableBufferScope (VarDecl *decl) {
2258+ SILGenFunction::enterLocalVariableAddressableBufferScope (VarDecl *decl,
2259+ CleanupHandle destroyCleanup) {
22452260 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 );
22482263}
22492264
22502265SILValue
@@ -2296,27 +2311,12 @@ SILGenFunction::getLocalVariableAddressableBuffer(VarDecl *decl,
22962311 SILValue reabstraction, allocStack, storeBorrow;
22972312 {
22982313 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);
23132315
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 );
23202320 auto allocStackTy = fullyAbstractedTy;
23212321 if (value->getType ().isMoveOnlyWrapped ()) {
23222322 allocStackTy = allocStackTy.addingMoveOnlyWrapper ();
@@ -2366,18 +2366,19 @@ SILGenFunction::getLocalVariableAddressableBuffer(VarDecl *decl,
23662366 // Record the addressable representation.
23672367 auto *addressableBuffer = getAddressableBufferInfo (decl);
23682368 auto *newState
2369- = new VarLoc:: AddressableBuffer::State (reabstraction, allocStack, storeBorrow);
2369+ = new AddressableBuffer::State (reabstraction, allocStack, storeBorrow);
23702370 addressableBuffer->stateOrAlias = newState;
23712371
23722372 // Emit cleanups on any paths where we previously would have cleaned up
23732373 // the addressable representation if it had been forced earlier.
23742374 decltype (addressableBuffer->cleanupPoints ) cleanupPoints;
23752375 cleanupPoints.swap (addressableBuffer->cleanupPoints );
23762376
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 ();
23812382 }
23822383
23832384 return storeBorrow;
@@ -2415,9 +2416,12 @@ void BlackHoleInitialization::copyOrInitValueInto(SILGenFunction &SGF, SILLocati
24152416 SGF.B .createIgnoredUse (loc, value.getValue ());
24162417}
24172418
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 ();
24212425 }
24222426 if (auto state = stateOrAlias.dyn_cast <State*>()) {
24232427 delete state;
0 commit comments