Skip to content

Commit b8757a4

Browse files
Merge pull request #21980 from aschwaighofer/partial_apply_stack_tests
Add more comprehensive tests that closure lifetime fixup takes place
2 parents 9265f0a + 49d2f8a commit b8757a4

File tree

1 file changed

+347
-1
lines changed

1 file changed

+347
-1
lines changed

test/SILOptimizer/closure_lifetime_fixup.swift

Lines changed: 347 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
// RUN: %target-swift-frontend %s -sil-verify-all -enable-sil-ownership -emit-sil -o - | %FileCheck %s
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend %S/../Inputs/resilient_struct.swift -enable-resilience -emit-module -emit-module-path %t/resilient_struct.swiftmodule
3+
// RUN: %target-swift-frontend %S/../Inputs/resilient_enum.swift -I %t -enable-resilience -emit-module -emit-module-path %t/resilient_enum.swiftmodule
4+
// RUN: %target-swift-frontend %s -sil-verify-all -enable-sil-ownership -emit-sil -I %t -o - | %FileCheck %s --check-prefix=CHECK --check-prefix=%target-os
5+
6+
import resilient_struct
7+
import resilient_enum
28

39
func use_closure(_ c : () -> () ) {
410
c()
@@ -104,3 +110,343 @@ public func to_stack_of_convert_function(p: UnsafeMutableRawPointer?) {
104110
public func no_dealloc_stack_before_unreachable(_ message: String, fileName: StaticString = #file, lineNumber: Int = #line) -> Never {
105111
Swift.fatalError(message, file: fileName, line: UInt(lineNumber))
106112
}
113+
114+
// Make sure closures are allocated on the stack.
115+
func useClosure(_ c: () -> ()) {
116+
}
117+
func useClosureThrowing(_ c: () throws -> ()) throws {
118+
}
119+
func useGenericClosure<T, V>(_ c : (T) -> V) {
120+
}
121+
func useGenericClosureThrowing<T, V>(_ c: (T) throws -> V) throws {
122+
}
123+
124+
// CHECK-LABEL: sil @$s22closure_lifetime_fixup12captureClass1c1dyAA1CC_AFtKF
125+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
126+
// CHECK: function_ref @$s22closure_lifetime_fixup10useClosureyyyyXEF
127+
128+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
129+
// CHECK: function_ref @$s22closure_lifetime_fixup18useClosureThrowingyyyyKXEKF
130+
131+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
132+
// CHECK: function_ref @$sIg_ytytIegnr_TR
133+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
134+
// CHECK: function_ref @$s22closure_lifetime_fixup17useGenericClosureyyq_xXEr0_lF
135+
136+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
137+
// CHECK: function_ref @$ss5Error_pIgzo_ytytsAA_pIegnrzo_TR
138+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
139+
// CHECK: function_ref @$s22closure_lifetime_fixup25useGenericClosureThrowingyyq_xKXEKr0_l
140+
public func captureClass(c: C, d: C) throws {
141+
useClosure {
142+
c.doIt()
143+
d.doIt()
144+
}
145+
146+
try useClosureThrowing {
147+
c.doIt()
148+
d.doIt()
149+
}
150+
151+
useGenericClosure {
152+
c.doIt()
153+
d.doIt()
154+
}
155+
156+
try useGenericClosureThrowing {
157+
c.doIt()
158+
d.doIt()
159+
}
160+
}
161+
162+
public protocol DoIt {
163+
func doIt()
164+
}
165+
// CHECK-LABEL: sil @$s22closure_lifetime_fixup14captureGeneric1c1dyx_q_tKAA4DoItRzAaER_r0_lF
166+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
167+
// CHECK: function_ref @$s22closure_lifetime_fixup10useClosureyyyyXEF
168+
169+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
170+
// CHECK: function_ref @$s22closure_lifetime_fixup18useClosureThrowingyyyyKXEKF
171+
172+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
173+
// CHECK: function_ref @$sIg_ytytIegnr_TR
174+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
175+
// CHECK: function_ref @$s22closure_lifetime_fixup17useGenericClosureyyq_xXEr0_lF
176+
177+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
178+
// CHECK: function_ref @$ss5Error_pIgzo_ytytsAA_pIegnrzo_TR
179+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
180+
// CHECK: function_ref @$s22closure_lifetime_fixup25useGenericClosureThrowingyyq_xKXEKr0_lF
181+
public func captureGeneric<C :DoIt,D: DoIt>(c: C, d: D) throws {
182+
useClosure {
183+
c.doIt()
184+
d.doIt()
185+
}
186+
187+
try useClosureThrowing {
188+
c.doIt()
189+
d.doIt()
190+
}
191+
192+
useGenericClosure {
193+
c.doIt()
194+
d.doIt()
195+
}
196+
197+
try useGenericClosureThrowing {
198+
c.doIt()
199+
d.doIt()
200+
}
201+
}
202+
203+
// CHECK-LABEL: sil @$s22closure_lifetime_fixup14captureClosure1c1d1tyq_xXE_q_xXExtKr0_lF
204+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
205+
// CHECK: function_ref @$s22closure_lifetime_fixup10useClosureyyyyXEF
206+
207+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
208+
// CHECK: function_ref @$s22closure_lifetime_fixup18useClosureThrowingyyyyKXEKF
209+
210+
211+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
212+
// CHECK: function_ref @$sIg_ytytIegnr_TR
213+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
214+
// CHECK: function_ref @$s22closure_lifetime_fixup17useGenericClosureyyq_xXEr0_lF
215+
216+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
217+
// CHECK: function_ref @$ss5Error_pIgzo_ytytsAA_pIegnrzo_TR
218+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
219+
// CHECK: function_ref @$s22closure_lifetime_fixup25useGenericClosureThrowingyyq_xKXEKr0_lF
220+
public func captureClosure<T, V>(c : (T) ->V, d: (T) -> V, t: T) throws {
221+
useClosure {
222+
c(t)
223+
d(t)
224+
}
225+
226+
try useClosureThrowing {
227+
c(t)
228+
d(t)
229+
}
230+
231+
useGenericClosure {
232+
c(t)
233+
d(t)
234+
}
235+
236+
try useGenericClosureThrowing {
237+
c(t)
238+
d(t)
239+
}
240+
}
241+
242+
// CHECK-LABEL: sil @$s22closure_lifetime_fixup16captureResilient
243+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
244+
// CHECK: apply
245+
246+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
247+
// CHECK: try_apply
248+
249+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
250+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
251+
// CHECK: apply
252+
253+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
254+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
255+
// CHECK: try_apply
256+
257+
public func captureResilient(c: Size) throws {
258+
useClosure {
259+
c.method()
260+
}
261+
262+
try useClosureThrowing {
263+
c.method()
264+
}
265+
266+
useGenericClosure {
267+
c.method()
268+
}
269+
270+
try useGenericClosureThrowing {
271+
c.method()
272+
}
273+
}
274+
275+
// CHECK-LABEL: sil @$s22closure_lifetime_fixup10capturePOD1cy16resilient_struct5PointV_tKF
276+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
277+
// CHECK: apply
278+
279+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
280+
// CHECK: try_apply
281+
282+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
283+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
284+
// CHECK: apply
285+
286+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
287+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
288+
// CHECK: try_apply
289+
public func capturePOD(c: Point) throws {
290+
useClosure {
291+
c.method()
292+
}
293+
294+
try useClosureThrowing {
295+
c.method()
296+
}
297+
298+
useGenericClosure {
299+
c.method()
300+
}
301+
302+
try useGenericClosureThrowing {
303+
c.method()
304+
}
305+
}
306+
307+
// CHECK-LABEL: sil @$s22closure_lifetime_fixup11captureEnum
308+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
309+
// CHECK: apply
310+
311+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
312+
// CHECK: try_apply
313+
314+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
315+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
316+
// CHECK: apply
317+
318+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
319+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
320+
// CHECK: try_apply
321+
public func captureEnum(c: FullyFixedLayout, d: CustomColor) throws {
322+
useClosure {
323+
_ = c
324+
_ = d
325+
}
326+
327+
try useClosureThrowing {
328+
_ = c
329+
_ = d
330+
}
331+
332+
useGenericClosure {
333+
_ = c
334+
_ = d
335+
}
336+
337+
try useGenericClosureThrowing {
338+
_ = c
339+
_ = d
340+
}
341+
}
342+
343+
public protocol EmptyP {}
344+
345+
public struct AddressOnlyStruct : EmptyP {}
346+
347+
public enum AddressOnlyEnum {
348+
case nought
349+
case mere(EmptyP)
350+
case phantom(AddressOnlyStruct)
351+
}
352+
353+
// CHECK-LABEL: sil @$s22closure_lifetime_fixup22captureAddressOnlyEnum
354+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
355+
// CHECK: apply
356+
357+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
358+
// CHECK: try_apply
359+
360+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
361+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
362+
// CHECK: apply
363+
364+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
365+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
366+
// CHECK: try_apply
367+
public func captureAddressOnlyEnum(c: AddressOnlyEnum, d: AddressOnlyEnum) throws {
368+
useClosure {
369+
_ = c
370+
_ = d
371+
}
372+
373+
try useClosureThrowing {
374+
_ = c
375+
_ = d
376+
}
377+
378+
useGenericClosure {
379+
_ = c
380+
_ = d
381+
}
382+
383+
try useGenericClosureThrowing {
384+
_ = c
385+
_ = d
386+
}
387+
}
388+
389+
// CHECK-LABEL: sil @$s22closure_lifetime_fixup15captureProtocol
390+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
391+
// CHECK: apply
392+
393+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
394+
// CHECK: try_apply
395+
396+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
397+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
398+
// CHECK: apply
399+
400+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
401+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
402+
// CHECK: try_apply
403+
public func captureProtocol(c: EmptyP, d: EmptyP) throws {
404+
useClosure {
405+
_ = c
406+
_ = d
407+
}
408+
409+
try useClosureThrowing {
410+
_ = c
411+
_ = d
412+
}
413+
414+
useGenericClosure { () -> Int in
415+
_ = c
416+
_ = d
417+
return 0
418+
}
419+
420+
try useGenericClosureThrowing { () -> Int in
421+
_ = c
422+
_ = d
423+
return 0
424+
}
425+
}
426+
427+
public protocol Q {
428+
associatedtype Element
429+
func test<U>(_ c: (Element) -> U) throws
430+
}
431+
432+
// CHECK-LABEL: sil @$s22closure_lifetime_fixup0A18WithAssociatedType1c1eyx_7ElementQztKAA1QRzlF
433+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
434+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
435+
// CHECK: try_apply
436+
public func closureWithAssociatedType<C : Q> (c: C, e: C.Element) throws {
437+
try c.test( { _ in _ = e })
438+
}
439+
440+
441+
public class F<T> {
442+
func test<V>(_ c: (V) throws -> T) {}
443+
let t : T? = nil
444+
}
445+
446+
// CHECK-LABEL: s22closure_lifetime_fixup22testClosureMethodParam1fyAA1FCyxG_tKlF
447+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
448+
// CHECK: partial_apply [callee_guaranteed] [on_stack]
449+
// CHECK: apply
450+
public func testClosureMethodParam<T>(f: F<T>) throws {
451+
try f.test { return f.t! }
452+
}

0 commit comments

Comments
 (0)