@@ -7052,6 +7052,22 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
70527052 }
70537053 }
70547054 }
7055+
7056+ void handleScopeInst (SILInstruction &i) {
7057+ if (!ActiveOps.insert (&i).second ) {
7058+ verificationFailure (" operation was not ended before re-beginning it" ,
7059+ &i, nullptr , nullptr );
7060+ }
7061+ }
7062+
7063+ void handleScopeEndingInst (SILInstruction &i) {
7064+ if (auto beginOp = i.getOperand (0 )->getDefiningInstruction ()) {
7065+ if (!ActiveOps.erase (beginOp)) {
7066+ verificationFailure (" operation has already been ended" , &i, nullptr ,
7067+ nullptr );
7068+ }
7069+ }
7070+ }
70557071 };
70567072
70577073 struct DeadEndRegionState {
@@ -7152,22 +7168,31 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
71527168 }
71537169
71547170 if (i.isAllocatingStack ()) {
7155- if (auto *BAI = dyn_cast<BeginApplyInst>(&i)) {
7156- state.Stack .push_back (BAI->getCalleeAllocationResult ());
7171+ // Nested stack allocations are pushed on the stack. Non-nested stack
7172+ // allocations are treated as active ops so that we can at least
7173+ // verify their joint post-dominance.
7174+ if (i.isStackAllocationNested ()) {
7175+ state.Stack .push_back (i.getStackAllocation ());
7176+
7177+ // Also track begin_apply as a scope instruction.
7178+ if (isa<BeginApplyInst>(i))
7179+ state.handleScopeInst (i);
71577180 } else {
7158- state.Stack . push_back (cast<SingleValueInstruction>(&i) );
7181+ state.handleScopeInst (i );
71597182 }
7160- // Not "else if": begin_apply both allocates stack and begins an
7161- // operation.
7162- }
7163- if (i.isDeallocatingStack ()) {
7183+ } else if (i.isDeallocatingStack ()) {
71647184 SILValue op = i.getOperand (0 );
71657185 while (auto *mvi = dyn_cast<MoveValueInst>(op)) {
71667186 op = mvi->getOperand ();
71677187 }
71687188
7169- if (!state.Stack .empty () && op == state.Stack .back ()) {
7189+ auto beginInst = op->getDefiningInstruction ();
7190+ if (beginInst && !beginInst->isStackAllocationNested ()) {
7191+ state.handleScopeEndingInst (i);
7192+ } else if (!state.Stack .empty () && op == state.Stack .back ()) {
71707193 state.Stack .pop_back ();
7194+ if (beginInst && isa<BeginApplyInst>(beginInst))
7195+ state.handleScopeEndingInst (i);
71717196 } else {
71727197 verificationFailure (" deallocating allocation that is not the top of the stack" ,
71737198 &i, nullptr ,
@@ -7178,20 +7203,12 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
71787203 });
71797204 }
71807205 } else if (isScopeInst (&i)) {
7181- bool notAlreadyPresent = state.ActiveOps .insert (&i).second ;
7182- require (notAlreadyPresent,
7183- " operation was not ended before re-beginning it" );
7206+ state.handleScopeInst (i);
71847207 } else if (isScopeEndingInst (&i)) {
7185- if (auto beginOp = i.getOperand (0 )->getDefiningInstruction ()) {
7186- bool present = state.ActiveOps .erase (beginOp);
7187- require (present, " operation has already been ended" );
7188- }
7208+ state.handleScopeEndingInst (i);
71897209 } else if (auto *endBorrow = dyn_cast<EndBorrowInst>(&i)) {
71907210 if (isa<StoreBorrowInst>(endBorrow->getOperand ())) {
7191- if (auto beginOp = i.getOperand (0 )->getDefiningInstruction ()) {
7192- bool present = state.ActiveOps .erase (beginOp);
7193- require (present, " operation has already been ended" );
7194- }
7211+ state.handleScopeEndingInst (i);
71957212 }
71967213 } else if (auto gaci = dyn_cast<GetAsyncContinuationInstBase>(&i)) {
71977214 require (!state.GotAsyncContinuation ,
0 commit comments