Skip to content

Commit 57e56a0

Browse files
Merge pull request #68342 from nate-chandler/gh68328
[MoveChecker] Complete lifetimes before checking.
2 parents f8f8d24 + 7713eef commit 57e56a0

File tree

3 files changed

+84
-0
lines changed

3 files changed

+84
-0
lines changed

lib/SILOptimizer/Mandatory/MoveOnlyChecker.cpp

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "swift/SIL/FieldSensitivePrunedLiveness.h"
3131
#include "swift/SIL/InstructionUtils.h"
3232
#include "swift/SIL/MemAccessUtils.h"
33+
#include "swift/SIL/OSSALifetimeCompletion.h"
3334
#include "swift/SIL/OwnershipUtils.h"
3435
#include "swift/SIL/PrunedLiveness.h"
3536
#include "swift/SIL/SILArgument.h"
@@ -86,6 +87,7 @@ struct MoveOnlyChecker {
8687
}
8788

8889
void checkObjects();
90+
void completeObjectLifetimes(ArrayRef<MarkUnresolvedNonCopyableValueInst *>);
8991
void checkAddresses();
9092
};
9193

@@ -110,10 +112,75 @@ void MoveOnlyChecker::checkObjects() {
110112
return;
111113
}
112114

115+
completeObjectLifetimes(moveIntroducersToProcess.getArrayRef());
116+
113117
MoveOnlyObjectChecker checker{diagnosticEmitter, domTree, poa, allocator};
114118
madeChange |= checker.check(moveIntroducersToProcess);
115119
}
116120

121+
void MoveOnlyChecker::completeObjectLifetimes(
122+
ArrayRef<MarkUnresolvedNonCopyableValueInst *> insts) {
123+
// TODO: Delete once OSSALifetimeCompletion is run as part of SILGenCleanup.
124+
OSSALifetimeCompletion completion(fn, domTree);
125+
126+
// Collect all values derived from each mark_unresolved_non_copyable_value
127+
// instruction via ownership instructions and phis.
128+
ValueWorklist transitiveValues(fn);
129+
for (auto *inst : insts) {
130+
transitiveValues.push(inst);
131+
}
132+
while (auto value = transitiveValues.pop()) {
133+
for (auto *use : value->getUses()) {
134+
auto *user = use->getUser();
135+
switch (user->getKind()) {
136+
case SILInstructionKind::BeginBorrowInst:
137+
case SILInstructionKind::CopyValueInst:
138+
case SILInstructionKind::MoveValueInst:
139+
transitiveValues.pushIfNotVisited(cast<SingleValueInstruction>(user));
140+
break;
141+
case SILInstructionKind::BranchInst: {
142+
PhiOperand po(use);
143+
transitiveValues.pushIfNotVisited(po.getValue());
144+
break;
145+
}
146+
default: {
147+
auto forward = ForwardingOperation(user);
148+
if (!forward)
149+
continue;
150+
forward.visitForwardedValues([&transitiveValues](auto forwarded) {
151+
transitiveValues.pushIfNotVisited(forwarded);
152+
return true;
153+
});
154+
break;
155+
}
156+
}
157+
}
158+
}
159+
// Complete the lifetime of each collected value. This is a subset of the
160+
// work that SILGenCleanup will do.
161+
for (auto *block : poa->get(fn)->getPostOrder()) {
162+
for (SILInstruction &inst : reverse(*block)) {
163+
for (auto result : inst.getResults()) {
164+
if (!transitiveValues.isVisited(result))
165+
continue;
166+
if (completion.completeOSSALifetime(result) ==
167+
LifetimeCompletion::WasCompleted) {
168+
madeChange = true;
169+
}
170+
}
171+
}
172+
for (SILArgument *arg : block->getArguments()) {
173+
assert(!arg->isReborrow() && "reborrows not legal at this SIL stage");
174+
if (!transitiveValues.isVisited(arg))
175+
continue;
176+
if (completion.completeOSSALifetime(arg) ==
177+
LifetimeCompletion::WasCompleted) {
178+
madeChange = true;
179+
}
180+
}
181+
}
182+
}
183+
117184
void MoveOnlyChecker::checkAddresses() {
118185
unsigned diagCount = diagnosticEmitter.getDiagnosticCount();
119186
SmallSetVector<MarkUnresolvedNonCopyableValueInst *, 32>

lib/SILOptimizer/Mandatory/SILGenCleanup.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ bool SILGenCleanup::completeOSSALifetimes(SILFunction *function) {
124124
}
125125
}
126126
for (SILArgument *arg : block->getArguments()) {
127+
assert(!arg->isReborrow() && "reborrows not legal at this SIL stage");
127128
if (completion.completeOSSALifetime(arg) ==
128129
LifetimeCompletion::WasCompleted) {
129130
changed = true;
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-build-swift %s -o %t/bin
3+
// RUN: %target-run %t/bin 2> %t/out.txt || true
4+
// RUN: %FileCheck %s < %t/out.txt
5+
6+
struct Example: ~Copyable {
7+
private var failureString: String { "Goodbye." }
8+
deinit { fatalError("FATAL ERROR: \(failureString)") }
9+
}
10+
11+
func doit() {
12+
let e = Example()
13+
// CHECK: FATAL ERROR: Goodbye.
14+
}
15+
16+
doit()

0 commit comments

Comments
 (0)