Skip to content

Commit 86de35b

Browse files
authored
Merge pull request swiftlang#22180 from gottesmm/pr-80686c0faa81a91a0e6027f58f6598ca7c3fa885
2 parents 575baf9 + 224c8a5 commit 86de35b

File tree

5 files changed

+82
-49
lines changed

5 files changed

+82
-49
lines changed

include/swift/SIL/OwnershipUtils.h

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,44 @@ struct ErrorBehaviorKind {
6767

6868
} // end namespace ownership
6969

70+
class LinearLifetimeError {
71+
ownership::ErrorBehaviorKind errorBehavior;
72+
bool foundError = false;
73+
74+
public:
75+
LinearLifetimeError(ownership::ErrorBehaviorKind errorBehavior)
76+
: errorBehavior(errorBehavior) {}
77+
78+
bool getFoundError() const { return foundError; }
79+
80+
void handleLeakError(llvm::function_ref<void()> &&messagePrinterFunc) {
81+
foundError = true;
82+
83+
if (errorBehavior.shouldPrintMessage())
84+
messagePrinterFunc();
85+
86+
if (errorBehavior.shouldReturnFalseOnLeak())
87+
return;
88+
89+
// We already printed out our error if we needed to, so don't pass it along.
90+
handleError([]() {});
91+
}
92+
93+
void handleError(llvm::function_ref<void()> &&messagePrinterFunc) {
94+
foundError = true;
95+
96+
if (errorBehavior.shouldPrintMessage())
97+
messagePrinterFunc();
98+
99+
if (errorBehavior.shouldReturnFalse()) {
100+
return;
101+
}
102+
103+
assert(errorBehavior.shouldAssert() && "At this point, we should assert");
104+
llvm_unreachable("triggering standard assertion failure routine");
105+
}
106+
};
107+
70108
/// Returns true if:
71109
///
72110
/// 1. No consuming uses are reachable from any other consuming use, from any
@@ -82,7 +120,7 @@ struct ErrorBehaviorKind {
82120
/// error.
83121
/// \p leakingBlocks If non-null a list of blocks where the value was detected
84122
/// to leak. Can be used to insert missing destroys.
85-
bool valueHasLinearLifetime(
123+
LinearLifetimeError valueHasLinearLifetime(
86124
SILValue value, ArrayRef<BranchPropagatedUser> consumingUses,
87125
ArrayRef<BranchPropagatedUser> nonConsumingUses,
88126
SmallPtrSetImpl<SILBasicBlock *> &visitedBlocks,

lib/SIL/LinearLifetimeChecker.cpp

Lines changed: 25 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,9 @@ struct State {
4545
/// The value that we are checking.
4646
SILValue value;
4747

48-
/// The behavior of the checker when we detect an error. Can either be
49-
/// returning false, returning false with a message emitted to stderr, or an
50-
/// assert.
51-
ErrorBehaviorKind errorBehavior;
48+
/// The result error object that use to signal either that no errors were
49+
/// found or if errors are found the specific type of error that was found.
50+
LinearLifetimeError error;
5251

5352
/// The blocks that we have already visited.
5453
SmallPtrSetImpl<SILBasicBlock *> &visitedBlocks;
@@ -76,8 +75,8 @@ struct State {
7675
State(SILValue value, SmallPtrSetImpl<SILBasicBlock *> &visitedBlocks,
7776
ErrorBehaviorKind errorBehavior,
7877
SmallVectorImpl<SILBasicBlock *> *leakingBlocks)
79-
: value(value), errorBehavior(errorBehavior),
80-
visitedBlocks(visitedBlocks), leakingBlocks(leakingBlocks) {}
78+
: value(value), error(errorBehavior), visitedBlocks(visitedBlocks),
79+
leakingBlocks(leakingBlocks) {}
8180

8281
void initializeAllNonConsumingUses(
8382
ArrayRef<BranchPropagatedUser> nonConsumingUsers);
@@ -115,17 +114,9 @@ struct State {
115114

116115
/// Depending on our initialization, either return false or call Func and
117116
/// throw an error.
118-
bool handleError(llvm::function_ref<void()> &&messagePrinterFunc) const {
119-
if (errorBehavior.shouldPrintMessage()) {
120-
messagePrinterFunc();
121-
}
122-
123-
if (errorBehavior.shouldReturnFalse()) {
124-
return false;
125-
}
126-
127-
assert(errorBehavior.shouldAssert() && "At this point, we should assert");
128-
llvm_unreachable("triggering standard assertion failure routine");
117+
bool handleError(llvm::function_ref<void()> &&messagePrinterFunc) {
118+
error.handleError(std::move(messagePrinterFunc));
119+
return false;
129120
}
130121
};
131122

@@ -406,20 +397,17 @@ bool State::checkDataflowEndState(DeadEndBlocks &deBlocks) {
406397
}
407398

408399
// If we are supposed to error on leaks, do so now.
409-
if (!errorBehavior.shouldReturnFalseOnLeak()) {
410-
return handleError([&] {
411-
llvm::errs() << "Function: '" << value->getFunction()->getName()
412-
<< "'\n"
413-
<< "Error! Found a leak due to a consuming post-dominance "
414-
"failure!\n"
415-
<< " Value: " << *value
416-
<< " Post Dominating Failure Blocks:\n";
417-
for (auto *succBlock : successorBlocksThatMustBeVisited) {
418-
llvm::errs() << " bb" << succBlock->getDebugID();
419-
}
420-
llvm::errs() << '\n';
421-
});
422-
}
400+
error.handleLeakError([&] {
401+
llvm::errs() << "Function: '" << value->getFunction()->getName() << "'\n"
402+
<< "Error! Found a leak due to a consuming post-dominance "
403+
"failure!\n"
404+
<< " Value: " << *value
405+
<< " Post Dominating Failure Blocks:\n";
406+
for (auto *succBlock : successorBlocksThatMustBeVisited) {
407+
llvm::errs() << " bb" << succBlock->getDebugID();
408+
}
409+
llvm::errs() << '\n';
410+
});
423411

424412
// Otherwise... see if we have any other failures. This signals the user
425413
// wants us to tell it where to insert compensating destroys.
@@ -461,7 +449,7 @@ bool State::checkDataflowEndState(DeadEndBlocks &deBlocks) {
461449
// Top Level Entrypoints
462450
//===----------------------------------------------------------------------===//
463451

464-
bool swift::valueHasLinearLifetime(
452+
LinearLifetimeError swift::valueHasLinearLifetime(
465453
SILValue value, ArrayRef<BranchPropagatedUser> consumingUses,
466454
ArrayRef<BranchPropagatedUser> nonConsumingUses,
467455
SmallPtrSetImpl<SILBasicBlock *> &visitedBlocks, DeadEndBlocks &deBlocks,
@@ -496,7 +484,7 @@ bool swift::valueHasLinearLifetime(
496484
// have been detected by initializing our consuming uses. So we are done.
497485
if (consumingUses.size() == 1 &&
498486
consumingUses[0].getParent() == value->getParentBlock()) {
499-
return true;
487+
return state.error;
500488
}
501489

502490
// Ok, we may have multiple consuming uses. Add the user block of each of our
@@ -517,7 +505,7 @@ bool swift::valueHasLinearLifetime(
517505
// Make sure that the predecessor is not in our blocksWithConsumingUses
518506
// list.
519507
if (state.checkPredsForDoubleConsume(user, predBlock)) {
520-
return state.handleError([] {});
508+
return state.error;
521509
}
522510

523511
if (!state.visitedBlocks.insert(predBlock).second)
@@ -528,9 +516,10 @@ bool swift::valueHasLinearLifetime(
528516
// Now that our algorithm is completely prepared, run the
529517
// dataflow... If we find a failure, return false.
530518
if (!state.performDataflow(deBlocks))
531-
return false;
519+
return state.error;
532520

533521
// ...and then check that the end state shows that we have a valid linear
534522
// typed value.
535-
return state.checkDataflowEndState(deBlocks);
523+
state.checkDataflowEndState(deBlocks);
524+
return state.error;
536525
}

lib/SIL/SILOwnershipVerifier.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,9 +139,10 @@ class SILValueOwnershipChecker {
139139
SmallVector<BranchPropagatedUser, 32> allRegularUsers;
140140
copy(regularUsers, std::back_inserter(allRegularUsers));
141141
copy(implicitRegularUsers, std::back_inserter(allRegularUsers));
142-
result =
142+
auto linearLifetimeResult =
143143
valueHasLinearLifetime(value, lifetimeEndingUsers, allRegularUsers,
144144
visitedBlocks, deadEndBlocks, errorBehavior);
145+
result = !linearLifetimeResult.getFoundError();
145146

146147
return result.getValue();
147148
}

lib/SILOptimizer/Mandatory/MandatoryInlining.cpp

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,10 @@ static void fixupReferenceCounts(
136136

137137
visitedBlocks.clear();
138138
// If we need to insert compensating destroys, do so.
139-
if (!valueHasLinearLifetime(copy, {applySite}, {}, visitedBlocks,
140-
deadEndBlocks, errorBehavior,
141-
&leakingBlocks)) {
139+
auto error =
140+
valueHasLinearLifetime(copy, {applySite}, {}, visitedBlocks,
141+
deadEndBlocks, errorBehavior, &leakingBlocks);
142+
if (error.getFoundError()) {
142143
while (!leakingBlocks.empty()) {
143144
auto *leakingBlock = leakingBlocks.pop_back_val();
144145
auto loc = RegularLocation::getAutoGeneratedLocation();
@@ -163,9 +164,10 @@ static void fixupReferenceCounts(
163164

164165
visitedBlocks.clear();
165166
// If we need to insert compensating destroys, do so.
166-
if (!valueHasLinearLifetime(v, {applySite}, {}, visitedBlocks,
167-
deadEndBlocks, errorBehavior,
168-
&leakingBlocks)) {
167+
auto error =
168+
valueHasLinearLifetime(v, {applySite}, {}, visitedBlocks,
169+
deadEndBlocks, errorBehavior, &leakingBlocks);
170+
if (error.getFoundError()) {
169171
while (!leakingBlocks.empty()) {
170172
auto *leakingBlock = leakingBlocks.pop_back_val();
171173
auto loc = RegularLocation::getAutoGeneratedLocation();
@@ -190,9 +192,10 @@ static void fixupReferenceCounts(
190192

191193
visitedBlocks.clear();
192194
// If we need to insert compensating destroys, do so.
193-
if (!valueHasLinearLifetime(v, {applySite}, {}, visitedBlocks,
194-
deadEndBlocks, errorBehavior,
195-
&leakingBlocks)) {
195+
auto error =
196+
valueHasLinearLifetime(v, {applySite}, {}, visitedBlocks,
197+
deadEndBlocks, errorBehavior, &leakingBlocks);
198+
if (error.getFoundError()) {
196199
while (!leakingBlocks.empty()) {
197200
auto *leakingBlock = leakingBlocks.pop_back_val();
198201
auto loc = RegularLocation::getAutoGeneratedLocation();

lib/SILOptimizer/Mandatory/PredictableMemOpt.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -777,8 +777,10 @@ void AvailableValueAggregator::addMissingDestroysForCopiedValues(LoadInst *li) {
777777
// no further work to do.
778778
auto errorKind =
779779
ownership::ErrorBehaviorKind::ReturnFalseOnLeakAssertOtherwise;
780-
if (valueHasLinearLifetime(cvi, consumingUses, {}, visitedBlocks,
781-
deadEndBlocks, errorKind, &leakingBlocks))
780+
auto error =
781+
valueHasLinearLifetime(cvi, consumingUses, {}, visitedBlocks,
782+
deadEndBlocks, errorKind, &leakingBlocks);
783+
if (!error.getFoundError())
782784
continue;
783785

784786
// Ok, we found some leaking blocks. Insert destroys at the

0 commit comments

Comments
 (0)