@@ -255,21 +255,23 @@ private func rewriteApplyInstruction(using specializedCallee: Function, callSite
255
255
let closureArgDesc = callSite. closureArgDesc ( at: parentClosureArgIndex) !
256
256
var builder = Builder ( before: closureArgDesc. closure, context)
257
257
258
+ // TODO: Support only OSSA instructions once the OSSA elimination pass is moved after all function optimization
259
+ // passes.
258
260
if callSite. applySite. parentBlock != closureArgDesc. closure. parentBlock {
259
261
// Emit the retain and release that keeps the argument live across the callee using the closure.
260
- builder. createCopyValue ( operand: capturedArg)
262
+ builder. createRetainValue ( operand: capturedArg)
261
263
262
264
for instr in closureArgDesc. lifetimeFrontier {
263
265
builder = Builder ( before: instr, context)
264
- builder. createDestroyValue ( operand: capturedArg)
266
+ builder. createReleaseValue ( operand: capturedArg)
265
267
}
266
268
267
269
// Emit the retain that matches the captured argument by the partial_apply in the callee that is consumed by
268
270
// the partial_apply.
269
271
builder = Builder ( before: callSite. applySite, context)
270
- builder. createCopyValue ( operand: capturedArg)
272
+ builder. createRetainValue ( operand: capturedArg)
271
273
} else {
272
- builder. createCopyValue ( operand: capturedArg)
274
+ builder. createRetainValue ( operand: capturedArg)
273
275
}
274
276
}
275
277
}
@@ -286,12 +288,14 @@ private func rewriteApplyInstruction(using specializedCallee: Function, callSite
286
288
isOnStack: oldApply. isOnStack)
287
289
288
290
builder = Builder ( before: callSite. applySite. next!, context)
291
+ // TODO: Support only OSSA instructions once the OSSA elimination pass is moved after all function optimization
292
+ // passes.
289
293
for closureArgDesc in callSite. closureArgDescriptors {
290
294
if closureArgDesc. isClosureConsumed,
291
295
!closureArgDesc. isPartialApplyOnStack,
292
296
!closureArgDesc. parameterInfo. isTrivialNoescapeClosure
293
297
{
294
- builder. createDestroyValue ( operand: closureArgDesc. closure)
298
+ builder. createReleaseValue ( operand: closureArgDesc. closure)
295
299
}
296
300
}
297
301
@@ -825,7 +829,7 @@ private extension SpecializationCloner {
825
829
{
826
830
builder. destroyPartialApplyOnStack ( paiOnStack: pai, self . context)
827
831
} else {
828
- builder. createDestroyValue ( operand: closure)
832
+ builder. createReleaseValue ( operand: closure)
829
833
}
830
834
}
831
835
}
@@ -992,11 +996,25 @@ private extension Builder {
992
996
func destroyPartialApplyOnStack( paiOnStack: PartialApplyInst , _ context: FunctionPassContext ) {
993
997
precondition ( paiOnStack. isOnStack, " Function must only be called for `partial_apply`s on stack! " )
994
998
995
- for arg in paiOnStack. arguments {
996
- self . createDestroyValue ( operand: arg)
997
- }
999
+ // TODO: Support only OSSA instructions once the OSSA elimination pass is moved after all function optimization
1000
+ // passes.
1001
+ //
1002
+ // for arg in paiOnStack.arguments {
1003
+ // self.createDestroyValue(operand: arg)
1004
+ // }
998
1005
999
- self . createDestroyValue ( operand: paiOnStack)
1006
+ // self.createDestroyValue(operand: paiOnStack)
1007
+
1008
+ if paiOnStack. parentFunction. hasOwnership {
1009
+ // Under OSSA, the closure acts as an owned value whose lifetime is a borrow scope for the captures, so we need to
1010
+ // end the borrow scope before ending the lifetimes of the captures themselves.
1011
+ self . createDestroyValue ( operand: paiOnStack)
1012
+ self . destroyCapturedArgs ( for: paiOnStack)
1013
+ } else {
1014
+ self . destroyCapturedArgs ( for: paiOnStack)
1015
+ self . createDeallocStack ( paiOnStack)
1016
+ context. notifyInvalidatedStackNesting ( )
1017
+ }
1000
1018
}
1001
1019
}
1002
1020
0 commit comments