Skip to content

Commit 0870f81

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 1b32a8f commit 0870f81

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
@@ -7085,8 +7085,8 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
70857085
struct BBState {
70867086
std::vector<SILValue> Stack;
70877087

7088-
/// Contents: BeginAccessInst*, BeginApplyInst*.
7089-
std::set<SILInstruction*> ActiveOps;
7088+
/// Contents: Results of BeginAccessInst*, BeginApplyInst*.
7089+
std::set<SILValue> ActiveOps;
70907090

70917091
CFGState CFG = Normal;
70927092

@@ -7239,19 +7239,16 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
72397239
}
72407240
}
72417241

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

7249-
void handleScopeEndingInst(SILInstruction &i) {
7250-
if (auto beginOp = i.getOperand(0)->getDefiningInstruction()) {
7251-
if (!ActiveOps.erase(beginOp)) {
7252-
verificationFailure("operation has already been ended", &i,
7253-
nullptr);
7254-
}
7249+
void handleScopeEndingInst(const SILInstruction &i) {
7250+
if (!ActiveOps.erase(i.getOperand(0))) {
7251+
verificationFailure("operation has already been ended", &i, nullptr);
72557252
}
72567253
}
72577254
};
@@ -7265,31 +7262,40 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
72657262
};
72667263
};
72677264

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

72797282
default:
7280-
return false;
7283+
return SILValue();
72817284
}
72827285
}
72837286
}
7284-
return false;
7287+
7288+
return SILValue();
72857289
}
72867290

72877291
static bool isScopeEndingInst(SILInstruction *i) {
72887292
if (isa<EndAccessInst>(i) ||
72897293
isa<AbortApplyInst>(i) ||
72907294
isa<EndApplyInst>(i)) {
72917295
return true;
7292-
} else if (auto bi = dyn_cast<BuiltinInst>(i)) {
7296+
}
7297+
7298+
if (auto bi = dyn_cast<BuiltinInst>(i)) {
72937299
if (auto bk = bi->getBuiltinKind()) {
72947300
switch (*bk) {
72957301
case BuiltinValueKind::FinishAsyncLet:
@@ -7361,10 +7367,12 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
73617367
state.Stack.push_back(i.getStackAllocation());
73627368

73637369
// Also track begin_apply as a scope instruction.
7364-
if (isa<BeginApplyInst>(i))
7365-
state.handleScopeInst(i);
7370+
if (auto *bai = dyn_cast<BeginApplyInst>(&i)) {
7371+
state.handleScopeInst(bai->getStackAllocation());
7372+
state.handleScopeInst(bai->getTokenResult());
7373+
}
73667374
} else {
7367-
state.handleScopeInst(i);
7375+
state.handleScopeInst(i.getStackAllocation());
73687376
}
73697377
} else if (i.isDeallocatingStack()) {
73707378
SILValue op = i.getOperand(0);
@@ -7390,8 +7398,8 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
73907398
// failure.
73917399
});
73927400
}
7393-
} else if (isScopeInst(&i)) {
7394-
state.handleScopeInst(i);
7401+
} else if (auto scopeEndingValue = isScopeInst(&i)) {
7402+
state.handleScopeInst(scopeEndingValue);
73957403
} else if (isScopeEndingInst(&i)) {
73967404
state.handleScopeEndingInst(i);
73977405
} 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
@@ -81,3 +81,18 @@ entry:
8181
dealloc_stack %allocation : $*Builtin.SILToken
8282
return undef : $()
8383
}
84+
85+
sil [ossa] @yield_test : $@yield_once @convention(thin) (@inout Builtin.Int32) -> @yields @inout Builtin.Int32 {
86+
bb0(%0 : $*Builtin.Int32):
87+
(%2, %3) = begin_apply undef(%0) : $@yield_once @convention(method) (@inout Builtin.Int32) -> @yields @inout Builtin.Int32
88+
yield %2, resume bb1, unwind bb2
89+
90+
bb1:
91+
%5 = end_apply %3 as $()
92+
%6 = tuple ()
93+
return %6
94+
95+
bb2:
96+
abort_apply %3
97+
unwind
98+
}

0 commit comments

Comments
 (0)