@@ -210,6 +210,13 @@ struct BBState {
210210 verificationFailure (" operation has already been ended" , &i, nullptr );
211211 }
212212 }
213+
214+ void handleScopeEndingUse (SILValue value, SILInstruction *origUser) {
215+ if (!ActiveOps.erase (value)) {
216+ verificationFailure (" operation has already been ended" , origUser,
217+ nullptr );
218+ }
219+ }
213220};
214221
215222struct DeadEndRegionState {
@@ -224,7 +231,7 @@ struct DeadEndRegionState {
224231// / If this is a scope ending inst, return the result from the instruction
225232// / that provides the scoped value whose lifetime must be ended by some other
226233// / scope ending instruction.
227- static SILValue isScopeInst (SILInstruction *i) {
234+ static SILValue getScopeEndingValueOfScopeInst (SILInstruction *i) {
228235 if (auto *bai = dyn_cast<BeginAccessInst>(i))
229236 return bai;
230237 if (auto *bai = dyn_cast<BeginApplyInst>(i))
@@ -325,15 +332,15 @@ void swift::silverifier::verifyFlowSensitiveRules(SILFunction *F) {
325332 // verify their joint post-dominance.
326333 if (i.isStackAllocationNested ()) {
327334 state.Stack .push_back (i.getStackAllocation ());
328-
329- // Also track begin_apply as a scope instruction.
330- if (auto *bai = dyn_cast<BeginApplyInst>(&i)) {
331- state.handleScopeInst (bai->getStackAllocation ());
332- state.handleScopeInst (bai->getTokenResult ());
333- }
334335 } else {
335336 state.handleScopeInst (i.getStackAllocation ());
336337 }
338+
339+ // Also track begin_apply's token as an ActiveOp so we can also verify
340+ // its joint dominance.
341+ if (auto *bai = dyn_cast<BeginApplyInst>(&i)) {
342+ state.handleScopeInst (bai->getTokenResult ());
343+ }
337344 continue ;
338345 }
339346
@@ -343,28 +350,48 @@ void swift::silverifier::verifyFlowSensitiveRules(SILFunction *F) {
343350 op = mvi->getOperand ();
344351 }
345352
346- auto beginInst = op->getDefiningInstruction ();
347- if (beginInst && (!beginInst->isAllocatingStack () ||
348- !beginInst->isStackAllocationNested ())) {
349- state.handleScopeEndingInst (i);
350- } else if (!state.Stack .empty () && op == state.Stack .back ()) {
353+ auto *definingInst = op->getDefiningInstruction ();
354+
355+ // First see if we have a begin_inst. In such a case, we need to handle
356+ // the token result first.
357+ if (auto *beginInst =
358+ llvm::dyn_cast_if_present<BeginApplyInst>(definingInst)) {
359+ // Check if our value is the token result... in such a case, we need
360+ // to handle scope ending inst and continue.
361+ if (op == beginInst->getTokenResult ()) {
362+ state.handleScopeEndingUse (op, &i);
363+ continue ;
364+ }
365+ }
366+
367+ // Ok, we have some sort of memory. Lets check if our definingInst is
368+ // unnested stack memory. In such a case, we want to just verify post
369+ // dominance and not validate that we are in stack order.
370+ if (definingInst && definingInst->isAllocatingStack () &&
371+ !definingInst->isStackAllocationNested ()) {
372+ state.handleScopeEndingUse (op, &i);
373+ continue ;
374+ }
375+
376+ // Ok, we have nested stack memory. Lets try to pop the stack. If we
377+ // fail due to an empty stack or a lack of a match, emit an error.
378+ if (!state.Stack .empty () && op == state.Stack .back ()) {
351379 state.Stack .pop_back ();
352- if (llvm::isa_and_present<BeginApplyInst>(beginInst))
353- state.handleScopeEndingInst (i);
354- } else {
355- verificationFailure (
356- " deallocating allocation that is not the top of the stack" , &i,
357- [&](SILPrintContext &ctx) {
358- state.printStack (ctx, " Current stack state" );
359- ctx.OS () << " Stack allocation:\n " << *op;
360- // The deallocation is printed out as the focus of the
361- // failure.
362- });
380+ continue ;
363381 }
382+
383+ verificationFailure (
384+ " deallocating allocation that is not the top of the stack" , &i,
385+ [&](SILPrintContext &ctx) {
386+ state.printStack (ctx, " Current stack state" );
387+ ctx.OS () << " Stack allocation:\n " << *op;
388+ // The deallocation is printed out as the focus of the
389+ // failure.
390+ });
364391 continue ;
365392 }
366393
367- if (auto scopeEndingValue = isScopeInst (&i)) {
394+ if (auto scopeEndingValue = getScopeEndingValueOfScopeInst (&i)) {
368395 state.handleScopeInst (scopeEndingValue);
369396 continue ;
370397 }
0 commit comments