@@ -66,6 +66,27 @@ static SILBasicBlock *getOptionalDiamondSuccessor(SwitchEnumInst *SEI) {
66
66
return nullptr ;
67
67
}
68
68
69
+ // / Find a safe insertion point for closure destruction. We might create a
70
+ // / closure that captures self in deinit of self. In this situation it is not
71
+ // / safe to destroy the closure after we called super deinit. We have to place
72
+ // / the closure destruction before that call.
73
+ // /
74
+ // / %deinit = objc_super_method %0 : $C, #A.deinit!deallocator.foreign
75
+ // / %super = upcast %0 : $C to $A
76
+ // / apply %deinit(%super) : $@convention(objc_method) (A) -> ()
77
+ // / end_lifetime %super : $A
78
+ static SILInstruction *getDeinitSafeClosureDestructionPoint (TermInst *Term) {
79
+ for (auto It = Term->getParent ()->rbegin (), E = Term->getParent ()->rend ();
80
+ It != E; ++It) {
81
+ if (auto *EndLifetime = dyn_cast<EndLifetimeInst>(&*It)) {
82
+ auto *SuperInstance = EndLifetime->getOperand ()->getDefiningInstruction ();
83
+ assert (SuperInstance && " Expected an instruction" );
84
+ return SuperInstance;
85
+ }
86
+ }
87
+ return Term;
88
+ }
89
+
69
90
// / Extend the lifetime of the convert_escape_to_noescape's operand to the end
70
91
// / of the function.
71
92
static void extendLifetimeToEndOfFunction (SILFunction &Fn,
@@ -111,10 +132,11 @@ static void extendLifetimeToEndOfFunction(SILFunction &Fn,
111
132
Fn.findExitingBlocks (ExitingBlocks);
112
133
for (auto *Exit : ExitingBlocks) {
113
134
auto *Term = Exit->getTerminator ();
114
- SILBuilderWithScope B (Term);
115
- B. setInsertionPoint (Term );
135
+ auto *SafeClosureDestructionPt = getDeinitSafeClosureDestructionPoint (Term);
136
+ SILBuilderWithScope B (SafeClosureDestructionPt );
116
137
B.createDestroyAddr (loc, Slot);
117
- B.createDeallocStack (loc, Slot);
138
+ SILBuilderWithScope B2 (Term);
139
+ B2.createDeallocStack (loc, Slot);
118
140
}
119
141
}
120
142
0 commit comments