Skip to content

Commit a3bdc89

Browse files
committed
Tell cleanups whether they're being emitted for the normal or unwind path.
NFC, but this may become semantically important for coroutines, because an active coroutine must be aborted instead of ended on the unwind path.
1 parent 81abcb8 commit a3bdc89

File tree

9 files changed

+70
-33
lines changed

9 files changed

+70
-33
lines changed

lib/SILGen/Cleanup.cpp

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ void CleanupManager::popTopDeadCleanups(CleanupsDepth end) {
5656
}
5757

5858
void CleanupManager::emitCleanups(CleanupsDepth depth, CleanupLocation loc,
59-
bool popCleanups) {
59+
ForUnwind_t forUnwind, bool popCleanups) {
6060
auto begin = stack.stable_begin();
6161
while (begin != depth) {
6262
auto iter = stack.find(begin);
@@ -76,7 +76,7 @@ void CleanupManager::emitCleanups(CleanupsDepth depth, CleanupLocation loc,
7676
stack.pop();
7777

7878
if (cleanup.isActive() && SGF.B.hasValidInsertionPoint())
79-
cleanup.emit(SGF, loc);
79+
cleanup.emit(SGF, loc, forUnwind);
8080

8181
stack.checkIterator(begin);
8282
}
@@ -95,7 +95,7 @@ void CleanupManager::endScope(CleanupsDepth depth, CleanupLocation loc) {
9595

9696
// Iteratively mark cleanups dead and pop them.
9797
// Maybe we'd get better results if we marked them all dead in one shot?
98-
emitCleanups(depth, loc);
98+
emitCleanups(depth, loc, NotForUnwind);
9999
}
100100

101101
bool CleanupManager::hasAnyActiveCleanups(CleanupsDepth from,
@@ -111,35 +111,37 @@ bool CleanupManager::hasAnyActiveCleanups(CleanupsDepth from) {
111111
/// threading out through any cleanups we might need to run. This does not
112112
/// pop the cleanup stack.
113113
void CleanupManager::emitBranchAndCleanups(JumpDest dest, SILLocation branchLoc,
114-
ArrayRef<SILValue> args) {
114+
ArrayRef<SILValue> args,
115+
ForUnwind_t forUnwind) {
115116
SILGenBuilder &builder = SGF.getBuilder();
116117
assert(builder.hasValidInsertionPoint() && "Emitting branch in invalid spot");
117118
emitCleanups(dest.getDepth(), dest.getCleanupLocation(),
118-
/*popCleanups=*/false);
119+
forUnwind, /*popCleanups=*/false);
119120
builder.createBranch(branchLoc, dest.getBlock(), args);
120121
}
121122

122123
void CleanupManager::emitCleanupsForReturn(CleanupLocation loc) {
123124
SILGenBuilder &builder = SGF.getBuilder();
124125
assert(builder.hasValidInsertionPoint() && "Emitting return in invalid spot");
125126
(void)builder;
126-
emitCleanups(stack.stable_end(), loc, /*popCleanups=*/false);
127+
emitCleanups(stack.stable_end(), loc, NotForUnwind, /*popCleanups=*/false);
127128
}
128129

129130
/// Emit a new block that jumps to the specified location and runs necessary
130131
/// cleanups based on its level. If there are no cleanups to run, this just
131132
/// returns the dest block.
132133
SILBasicBlock *CleanupManager::emitBlockForCleanups(JumpDest dest,
133134
SILLocation branchLoc,
134-
ArrayRef<SILValue> args) {
135+
ArrayRef<SILValue> args,
136+
ForUnwind_t forUnwind) {
135137
// If there are no cleanups to run, just return the Dest block directly.
136138
if (!hasAnyActiveCleanups(dest.getDepth()))
137139
return dest.getBlock();
138140

139141
// Otherwise, create and emit a new block.
140142
auto *newBlock = SGF.createBasicBlock();
141143
SILGenSavedInsertionPoint IPRAII(SGF, newBlock);
142-
emitBranchAndCleanups(dest, branchLoc, args);
144+
emitBranchAndCleanups(dest, branchLoc, args, forUnwind);
143145
return newBlock;
144146
}
145147

lib/SILGen/Cleanup.h

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,21 @@ class ManagedValue;
3737
class SharedBorrowFormalAccess;
3838
class FormalEvaluationScope;
3939

40+
/// Is a cleanup being executed as a result of some sort of forced
41+
/// unwinding, such as an error being thrown, or are we just cleaning up
42+
/// after some operation?
43+
///
44+
/// Most cleanups don't care, but the cleanups tied to l-value accesses do:
45+
/// the access will be aborted rather than ended normally, which may cause
46+
/// e.g. writebacks to be skipped. It is also important that no actions
47+
/// be undertaken by an unwind cleanup that might change control flow,
48+
/// such as throwing an error. In contrast, non-unwinding cleanups are
49+
/// permitted to change control flow.
50+
enum ForUnwind_t : bool {
51+
NotForUnwind,
52+
IsForUnwind
53+
};
54+
4055
/// The valid states that a cleanup can be in.
4156
enum class CleanupState {
4257
/// The cleanup is inactive but may be activated later.
@@ -80,7 +95,8 @@ class LLVM_LIBRARY_VISIBILITY Cleanup {
8095
bool isActive() const { return state >= CleanupState::Active; }
8196
bool isDead() const { return state == CleanupState::Dead; }
8297

83-
virtual void emit(SILGenFunction &SGF, CleanupLocation loc) = 0;
98+
virtual void emit(SILGenFunction &SGF, CleanupLocation loc,
99+
ForUnwind_t forUnwind) = 0;
84100
virtual void dump(SILGenFunction &SGF) const = 0;
85101
};
86102

@@ -120,6 +136,7 @@ class LLVM_LIBRARY_VISIBILITY CleanupManager {
120136

121137
void popTopDeadCleanups(CleanupsDepth end);
122138
void emitCleanups(CleanupsDepth depth, CleanupLocation l,
139+
ForUnwind_t forUnwind,
123140
bool popCleanups=true);
124141
void endScope(CleanupsDepth depth, CleanupLocation l);
125142

@@ -151,7 +168,8 @@ class LLVM_LIBRARY_VISIBILITY CleanupManager {
151168
/// \param branchLoc The location of the branch instruction.
152169
/// \param args Arguments to pass to the destination block.
153170
void emitBranchAndCleanups(JumpDest dest, SILLocation branchLoc,
154-
ArrayRef<SILValue> args = {});
171+
ArrayRef<SILValue> args = {},
172+
ForUnwind_t forUnwind = NotForUnwind);
155173

156174
/// emitCleanupsForReturn - Emit the top-level cleanups needed prior to a
157175
/// return from the function.
@@ -161,7 +179,8 @@ class LLVM_LIBRARY_VISIBILITY CleanupManager {
161179
/// cleanups based on its level. If there are no cleanups to run, this just
162180
/// returns the dest block.
163181
SILBasicBlock *emitBlockForCleanups(JumpDest dest, SILLocation branchLoc,
164-
ArrayRef<SILValue> args = {});
182+
ArrayRef<SILValue> args = {},
183+
ForUnwind_t forUnwind = NotForUnwind);
165184

166185
/// pushCleanup - Push a new cleanup.
167186
template<class T, class... A>

lib/SILGen/SILGenApply.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3338,7 +3338,7 @@ class DeallocateUninitializedBox : public Cleanup {
33383338
public:
33393339
DeallocateUninitializedBox(SILValue box) : box(box) {}
33403340

3341-
void emit(SILGenFunction &SGF, CleanupLocation l) override {
3341+
void emit(SILGenFunction &SGF, CleanupLocation l, ForUnwind_t forUnwind) override {
33423342
SGF.B.createDeallocBox(l, box);
33433343
}
33443344

@@ -4830,7 +4830,7 @@ namespace {
48304830
DeallocateUninitializedArray(SILValue array)
48314831
: Array(array) {}
48324832

4833-
void emit(SILGenFunction &SGF, CleanupLocation l) override {
4833+
void emit(SILGenFunction &SGF, CleanupLocation l, ForUnwind_t forUnwind) override {
48344834
SGF.emitUninitializedArrayDeallocation(l, Array);
48354835
}
48364836

lib/SILGen/SILGenDecl.cpp

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,8 @@ namespace {
131131
SILValue closure;
132132
public:
133133
CleanupClosureConstant(SILValue closure) : closure(closure) {}
134-
void emit(SILGenFunction &SGF, CleanupLocation l) override {
134+
void emit(SILGenFunction &SGF, CleanupLocation l,
135+
ForUnwind_t forUnwind) override {
135136
SGF.B.emitDestroyValueOperation(l, closure);
136137
}
137138
void dump(SILGenFunction &) const override {
@@ -250,7 +251,8 @@ class EndBorrowCleanup : public Cleanup {
250251
EndBorrowCleanup(SILValue original, SILValue borrowed)
251252
: original(original), borrowed(borrowed) {}
252253

253-
void emit(SILGenFunction &SGF, CleanupLocation l) override {
254+
void emit(SILGenFunction &SGF, CleanupLocation l,
255+
ForUnwind_t forUnwind) override {
254256
SGF.B.createEndBorrow(l, borrowed, original);
255257
}
256258

@@ -271,7 +273,8 @@ class ReleaseValueCleanup : public Cleanup {
271273
public:
272274
ReleaseValueCleanup(SILValue v) : v(v) {}
273275

274-
void emit(SILGenFunction &SGF, CleanupLocation l) override {
276+
void emit(SILGenFunction &SGF, CleanupLocation l,
277+
ForUnwind_t forUnwind) override {
275278
if (v->getType().isAddress())
276279
SGF.B.createDestroyAddr(l, v);
277280
else
@@ -295,7 +298,8 @@ class DeallocStackCleanup : public Cleanup {
295298
public:
296299
DeallocStackCleanup(SILValue addr) : Addr(addr) {}
297300

298-
void emit(SILGenFunction &SGF, CleanupLocation l) override {
301+
void emit(SILGenFunction &SGF, CleanupLocation l,
302+
ForUnwind_t forUnwind) override {
299303
SGF.B.createDeallocStack(l, Addr);
300304
}
301305

@@ -316,7 +320,8 @@ class DestroyLocalVariable : public Cleanup {
316320
public:
317321
DestroyLocalVariable(VarDecl *var) : Var(var) {}
318322

319-
void emit(SILGenFunction &SGF, CleanupLocation l) override {
323+
void emit(SILGenFunction &SGF, CleanupLocation l,
324+
ForUnwind_t forUnwind) override {
320325
SGF.destroyLocalVariable(l, Var);
321326
}
322327

@@ -349,7 +354,8 @@ class DeallocateUninitializedLocalVariable : public Cleanup {
349354
public:
350355
DeallocateUninitializedLocalVariable(VarDecl *var) : Var(var) {}
351356

352-
void emit(SILGenFunction &SGF, CleanupLocation l) override {
357+
void emit(SILGenFunction &SGF, CleanupLocation l,
358+
ForUnwind_t forUnwind) override {
353359
SGF.deallocateUninitializedLocalVariable(l, Var);
354360
}
355361

@@ -1304,7 +1310,8 @@ namespace {
13041310
concreteFormalType(concreteFormalType),
13051311
repr(repr) {}
13061312

1307-
void emit(SILGenFunction &SGF, CleanupLocation l) override {
1313+
void emit(SILGenFunction &SGF, CleanupLocation l,
1314+
ForUnwind_t forUnwind) override {
13081315
switch (repr) {
13091316
case ExistentialRepresentation::None:
13101317
case ExistentialRepresentation::Class:
@@ -1481,7 +1488,8 @@ struct FormalAccessReleaseValueCleanup : Cleanup {
14811488
state = newState;
14821489
}
14831490

1484-
void emit(SILGenFunction &SGF, CleanupLocation l) override {
1491+
void emit(SILGenFunction &SGF, CleanupLocation l,
1492+
ForUnwind_t forUnwind) override {
14851493
getEvaluation(SGF).finish(SGF);
14861494
}
14871495

lib/SILGen/SILGenExpr.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,8 @@ struct EndBorrowCleanup : Cleanup {
168168
EndBorrowCleanup(SILValue originalValue, SILValue borrowedValue)
169169
: originalValue(originalValue), borrowedValue(borrowedValue) {}
170170

171-
void emit(SILGenFunction &SGF, CleanupLocation l) override {
171+
void emit(SILGenFunction &SGF, CleanupLocation l,
172+
ForUnwind_t forUnwind) override {
172173
SGF.B.createEndBorrow(l, borrowedValue, originalValue);
173174
}
174175

@@ -187,7 +188,7 @@ struct FormalEvaluationEndBorrowCleanup : Cleanup {
187188

188189
FormalEvaluationEndBorrowCleanup() : Depth() {}
189190

190-
void emit(SILGenFunction &SGF, CleanupLocation l) override {
191+
void emit(SILGenFunction &SGF, CleanupLocation l, ForUnwind_t forUnwind) override {
191192
getEvaluation(SGF).finish(SGF);
192193
}
193194

@@ -276,7 +277,8 @@ struct EndBorrowArgumentCleanup : Cleanup {
276277

277278
EndBorrowArgumentCleanup(SILPHIArgument *arg) : arg(arg) {}
278279

279-
void emit(SILGenFunction &SGF, CleanupLocation l) override {
280+
void emit(SILGenFunction &SGF, CleanupLocation l,
281+
ForUnwind_t forUnwind) override {
280282
SGF.B.createEndBorrowArgument(l, arg);
281283
}
282284

@@ -708,7 +710,7 @@ struct DelegateInitSelfWritebackCleanup : Cleanup {
708710
SILValue value)
709711
: loc(loc), lvalueAddress(lvalueAddress), value(value) {}
710712

711-
void emit(SILGenFunction &SGF, CleanupLocation) override {
713+
void emit(SILGenFunction &SGF, CleanupLocation l, ForUnwind_t forUnwind) override {
712714
SILValue valueToStore = value;
713715
SILType lvalueObjTy = lvalueAddress->getType().getObjectType();
714716

lib/SILGen/SILGenLValue.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,9 @@ struct LValueWritebackCleanup : Cleanup {
4444

4545
LValueWritebackCleanup() : Depth() {}
4646

47-
void emit(SILGenFunction &SGF, CleanupLocation loc) override {
47+
void emit(SILGenFunction &SGF, CleanupLocation loc,
48+
ForUnwind_t forUnwind) override {
49+
// TODO: honor forUnwind!
4850
auto &evaluation = *SGF.FormalEvalContext.find(Depth);
4951
assert(evaluation.getKind() == FormalAccess::Exclusive);
5052
auto &lvalue = static_cast<ExclusiveBorrowFormalAccess &>(evaluation);
@@ -554,7 +556,8 @@ struct UnenforcedAccessCleanup : Cleanup {
554556

555557
UnenforcedAccessCleanup() : Depth() {}
556558

557-
void emit(SILGenFunction &SGF, CleanupLocation loc) override {
559+
void emit(SILGenFunction &SGF, CleanupLocation loc,
560+
ForUnwind_t forUnwind) override {
558561
auto &evaluation = *SGF.FormalEvalContext.find(Depth);
559562
assert(evaluation.getKind() == FormalAccess::Unenforced);
560563
auto &formalAccess = static_cast<UnenforcedFormalAccess &>(evaluation);

lib/SILGen/SILGenMaterializeForSet.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -952,7 +952,8 @@ namespace {
952952
public:
953953
DeallocateValueBuffer(SILType valueType, SILValue buffer)
954954
: Buffer(buffer), ValueType(valueType) {}
955-
void emit(SILGenFunction &SGF, CleanupLocation loc) override {
955+
void emit(SILGenFunction &SGF, CleanupLocation loc,
956+
ForUnwind_t forUnwind) override {
956957
SGF.B.createDeallocValueBuffer(loc, ValueType, Buffer);
957958
}
958959
void dump(SILGenFunction &) const override {

lib/SILGen/SILGenProlog.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ class CleanupWriteBackToInOut : public Cleanup {
4545
CleanupWriteBackToInOut(VarDecl *var, SILValue inoutAddr)
4646
: var(var), inoutAddr(inoutAddr) {}
4747

48-
void emit(SILGenFunction &SGF, CleanupLocation l) override {
48+
void emit(SILGenFunction &SGF, CleanupLocation l,
49+
ForUnwind_t forUnwind) override {
4950
// Assign from the local variable to the inout address with an
5051
// 'autogenerated' copyaddr.
5152
l.markAutoGenerated();
@@ -61,7 +62,8 @@ class StrongReleaseCleanup : public Cleanup {
6162
SILValue box;
6263
public:
6364
StrongReleaseCleanup(SILValue box) : box(box) {}
64-
void emit(SILGenFunction &SGF, CleanupLocation l) override {
65+
void emit(SILGenFunction &SGF, CleanupLocation l,
66+
ForUnwind_t forUnwind) override {
6567
SGF.B.emitDestroyValueOperation(l, box);
6668
}
6769

lib/SILGen/SILGenStmt.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,7 @@ namespace {
426426
SourceLoc deferLoc;
427427
public:
428428
DeferEscapeCheckerCleanup(SourceLoc deferLoc) : deferLoc(deferLoc) {}
429-
void emit(SILGenFunction &SGF, CleanupLocation l) override {
429+
void emit(SILGenFunction &SGF, CleanupLocation l, ForUnwind_t forUnwind) override {
430430
assert(false && "Sema didn't catch exit out of a defer?");
431431
}
432432
void dump(SILGenFunction &) const override {
@@ -446,7 +446,7 @@ namespace {
446446
public:
447447
DeferCleanup(SourceLoc deferLoc, Expr *call)
448448
: deferLoc(deferLoc), call(call) {}
449-
void emit(SILGenFunction &SGF, CleanupLocation l) override {
449+
void emit(SILGenFunction &SGF, CleanupLocation l, ForUnwind_t forUnwind) override {
450450
SGF.Cleanups.pushCleanup<DeferEscapeCheckerCleanup>(deferLoc);
451451
auto TheCleanup = SGF.Cleanups.getTopCleanup();
452452

@@ -1010,5 +1010,5 @@ void SILGenFunction::emitThrow(SILLocation loc, ManagedValue exnMV,
10101010
}
10111011

10121012
// Branch to the cleanup destination.
1013-
Cleanups.emitBranchAndCleanups(ThrowDest, loc, exn);
1013+
Cleanups.emitBranchAndCleanups(ThrowDest, loc, exn, IsForUnwind);
10141014
}

0 commit comments

Comments
 (0)