Skip to content

Commit 94e9166

Browse files
committed
[sil-verifier] Use the scope result rather than the scope instruction when verifying that we end scope instructions.
We do this since we need to be able to handle instructions that may have two different results that independently need their scopes lifetime to be ended.
1 parent c876c1e commit 94e9166

File tree

2 files changed

+49
-26
lines changed

2 files changed

+49
-26
lines changed

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7083,8 +7083,8 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
70837083
struct BBState {
70847084
std::vector<SILValue> Stack;
70857085

7086-
/// Contents: BeginAccessInst*, BeginApplyInst*.
7087-
std::set<SILInstruction*> ActiveOps;
7086+
/// Contents: Results of BeginAccessInst*, BeginApplyInst*.
7087+
std::set<SILValue> ActiveOps;
70887088

70897089
CFGState CFG = Normal;
70907090

@@ -7237,19 +7237,16 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
72377237
}
72387238
}
72397239

7240-
void handleScopeInst(SILInstruction &i) {
7241-
if (!ActiveOps.insert(&i).second) {
7240+
void handleScopeInst(SILValue i) {
7241+
if (!ActiveOps.insert(i).second) {
72427242
verificationFailure("operation was not ended before re-beginning it",
7243-
&i, nullptr);
7243+
i, nullptr);
72447244
}
72457245
}
72467246

7247-
void handleScopeEndingInst(SILInstruction &i) {
7248-
if (auto beginOp = i.getOperand(0)->getDefiningInstruction()) {
7249-
if (!ActiveOps.erase(beginOp)) {
7250-
verificationFailure("operation has already been ended", &i,
7251-
nullptr);
7252-
}
7247+
void handleScopeEndingInst(const SILInstruction &i) {
7248+
if (!ActiveOps.erase(i.getOperand(0))) {
7249+
verificationFailure("operation has already been ended", &i, nullptr);
72537250
}
72547251
}
72557252
};
@@ -7263,31 +7260,40 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
72637260
};
72647261
};
72657262

7266-
static bool isScopeInst(SILInstruction *i) {
7267-
if (isa<BeginAccessInst>(i) ||
7268-
isa<BeginApplyInst>(i) ||
7269-
isa<StoreBorrowInst>(i)) {
7270-
return true;
7271-
} else if (auto bi = dyn_cast<BuiltinInst>(i)) {
7263+
/// If this is a scope ending inst, return the result from the instruction
7264+
/// that provides the scoped value whose lifetime must be ended by some other
7265+
/// scope ending instruction.
7266+
static SILValue isScopeInst(SILInstruction *i) {
7267+
if (auto *bai = dyn_cast<BeginAccessInst>(i))
7268+
return bai;
7269+
if (auto *bai = dyn_cast<BeginApplyInst>(i))
7270+
return bai->getTokenResult();
7271+
if (auto *sbi = dyn_cast<StoreBorrowInst>(i))
7272+
return sbi;
7273+
7274+
if (auto bi = dyn_cast<BuiltinInst>(i)) {
72727275
if (auto bk = bi->getBuiltinKind()) {
72737276
switch (*bk) {
72747277
case BuiltinValueKind::StartAsyncLetWithLocalBuffer:
7275-
return true;
7278+
return bi->getResult(0);
72767279

72777280
default:
7278-
return false;
7281+
return SILValue();
72797282
}
72807283
}
72817284
}
7282-
return false;
7285+
7286+
return SILValue();
72837287
}
72847288

72857289
static bool isScopeEndingInst(SILInstruction *i) {
72867290
if (isa<EndAccessInst>(i) ||
72877291
isa<AbortApplyInst>(i) ||
72887292
isa<EndApplyInst>(i)) {
72897293
return true;
7290-
} else if (auto bi = dyn_cast<BuiltinInst>(i)) {
7294+
}
7295+
7296+
if (auto bi = dyn_cast<BuiltinInst>(i)) {
72917297
if (auto bk = bi->getBuiltinKind()) {
72927298
switch (*bk) {
72937299
case BuiltinValueKind::FinishAsyncLet:
@@ -7359,10 +7365,12 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
73597365
state.Stack.push_back(i.getStackAllocation());
73607366

73617367
// Also track begin_apply as a scope instruction.
7362-
if (isa<BeginApplyInst>(i))
7363-
state.handleScopeInst(i);
7368+
if (auto *bai = dyn_cast<BeginApplyInst>(&i)) {
7369+
state.handleScopeInst(bai->getStackAllocation());
7370+
state.handleScopeInst(bai->getTokenResult());
7371+
}
73647372
} else {
7365-
state.handleScopeInst(i);
7373+
state.handleScopeInst(i.getStackAllocation());
73667374
}
73677375
} else if (i.isDeallocatingStack()) {
73687376
SILValue op = i.getOperand(0);
@@ -7388,8 +7396,8 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
73887396
// failure.
73897397
});
73907398
}
7391-
} else if (isScopeInst(&i)) {
7392-
state.handleScopeInst(i);
7399+
} else if (auto scopeEndingValue = isScopeInst(&i)) {
7400+
state.handleScopeInst(scopeEndingValue);
73937401
} else if (isScopeEndingInst(&i)) {
73947402
state.handleScopeEndingInst(i);
73957403
} else if (auto *endBorrow = dyn_cast<EndBorrowInst>(&i)) {

test/SIL/verifier_failures.sil

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,18 @@ failure(%error : @owned $any Error):
8989
dealloc_stack %allocation : $*Builtin.SILToken
9090
throw %error : $any Error
9191
}
92+
93+
sil [ossa] @yield_test : $@yield_once @convention(thin) (@inout Builtin.Int32) -> @yields @inout Builtin.Int32 {
94+
bb0(%0 : $*Builtin.Int32):
95+
(%2, %3) = begin_apply undef(%0) : $@yield_once @convention(method) (@inout Builtin.Int32) -> @yields @inout Builtin.Int32
96+
yield %2, resume bb1, unwind bb2
97+
98+
bb1:
99+
%5 = end_apply %3 as $()
100+
%6 = tuple ()
101+
return %6
102+
103+
bb2:
104+
abort_apply %3
105+
unwind
106+
}

0 commit comments

Comments
 (0)