Skip to content

Commit d94a4dc

Browse files
committed
test LifetimeDepInsertion for @_addressableForDependencies
1 parent 331c315 commit d94a4dc

File tree

1 file changed

+220
-0
lines changed

1 file changed

+220
-0
lines changed
Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
// RUN: %target-swift-frontend %s -emit-sil \
2+
// RUN: -Xllvm -sil-print-after=lifetime-dependence-insertion \
3+
// RUN: -enable-builtin-module \
4+
// RUN: -sil-verify-all \
5+
// RUN: -module-name test \
6+
// RUN: -define-availability "Span 0.1:macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, visionOS 9999" \
7+
// RUN: -enable-address-dependencies \
8+
// RUN: -enable-experimental-feature LifetimeDependence \
9+
// RUN: -enable-experimental-feature AddressableParameters \
10+
// RUN: -enable-experimental-feature AddressableTypes \
11+
// RUN: -o /dev/null 2>&1 | %FileCheck %s
12+
13+
// REQUIRES: swift_in_compiler
14+
// REQUIRES: swift_feature_LifetimeDependence
15+
// REQUIRES: swift_feature_AddressableParameters
16+
// REQUIRES: swift_feature_AddressableTypes
17+
18+
import Builtin
19+
20+
@unsafe
21+
@_unsafeNonescapableResult
22+
@_alwaysEmitIntoClient
23+
@_transparent
24+
@lifetime(borrow source)
25+
internal func _overrideLifetime<
26+
T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable
27+
>(
28+
_ dependent: consuming T, borrowing source: borrowing U
29+
) -> T {
30+
dependent
31+
}
32+
33+
struct BV : ~Escapable {
34+
let p: UnsafeRawPointer
35+
let i: Int
36+
37+
@lifetime(borrow p)
38+
init(_ p: UnsafeRawPointer, _ i: Int) {
39+
self.p = p
40+
self.i = i
41+
}
42+
}
43+
44+
struct NC : ~Copyable {
45+
let p: UnsafeRawPointer
46+
let i: Int
47+
48+
// Requires a borrow.
49+
@lifetime(borrow self)
50+
borrowing func getBV() -> BV {
51+
BV(p, i)
52+
}
53+
}
54+
55+
public class C {
56+
var i: Int = 42
57+
}
58+
59+
@_silgen_name("use")
60+
func use(_ o : borrowing BV)
61+
62+
// =============================================================================
63+
// Basic pointer dependencies
64+
// =============================================================================
65+
66+
// CHECK-LABEL: sil hidden [ossa] @$s4test13bv_borrow_var1p1iySV_SitF : $@convention(thin) (UnsafeRawPointer, Int) -> () {
67+
// CHECK: [[A:%.*]] = begin_access [read] [unknown] %{{.*}}
68+
// CHECK: [[U:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[A]]
69+
// CHECK: [[L:%.*]] = load [copy] [[U]]
70+
// CHECK: [[R:%.*]] = apply %{{.*}}([[L]]) : $@convention(method) (@guaranteed NC) -> @lifetime(borrow 0) @owned BV
71+
// CHECK: [[M:%.*]] = mark_dependence [unresolved] [[R]] on [[A]]
72+
// CHECK: end_access [[A]]
73+
// CHECK: [[MV:%.*]] = move_value [var_decl] [[M]]
74+
// CHECK: %{{.*}} = apply %{{.*}}([[MV]]) : $@convention(thin) (@guaranteed BV) -> ()
75+
// CHECK-LABEL: } // end sil function '$s4test13bv_borrow_var1p1iySV_SitF'
76+
func bv_borrow_var(p: UnsafeRawPointer, i: Int) {
77+
var nc = NC(p: p, i: i)
78+
let bv = nc.getBV()
79+
use(bv)
80+
}
81+
82+
// LifetimeDependence.Scope needs to see through typed-to-raw pointer conversion.
83+
//
84+
// CHECK-LABEL: sil hidden [ossa] @$s4test18bv_pointer_convert1pAA2BVVSPySiG_tF : $@convention(thin) (UnsafePointer<Int>) -> @lifetime(borrow 0) @owned BV {
85+
// CHECK: bb0(%0 : $UnsafePointer<Int>):
86+
// CHECK: apply %{{.*}}<UnsafePointer<Int>, UnsafeRawPointer>([[RAW:%.*]], %{{.*}}) : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 : _Pointer, τ_0_1 : _Pointer> (@in_guaranteed τ_0_0) -> @out τ_0_1
87+
// CHECK: [[RAW:%.*]] = load [trivial] %6
88+
// CHECK: [[BV:%.*]] = apply %13([[RAW]], {{.*}}) : $@convention(method) (UnsafeRawPointer, Int, @thin BV.Type) -> @lifetime(borrow 0) @owned BV
89+
// CHECK: [[MD:%.*]] = mark_dependence [unresolved] [[BV]] on %0
90+
// CHECK: return [[MD]]
91+
// CHECK-LABEL: } // end sil function '$s4test18bv_pointer_convert1pAA2BVVSPySiG_tF'
92+
@lifetime(borrow p)
93+
func bv_pointer_convert(p: UnsafePointer<Int>) -> BV {
94+
BV(p, 0)
95+
}
96+
97+
// =============================================================================
98+
// @_addressableForDependencies
99+
// =============================================================================
100+
101+
@available(Span 0.1, *)
102+
public typealias IntSpan = Span<Int>
103+
104+
@available(Span 0.1, *)
105+
protocol IntSpanable {
106+
@lifetime(borrow self)
107+
func getIntSpan() -> IntSpan
108+
}
109+
110+
@available(Span 0.1, *)
111+
public struct Holder: IntSpanable {
112+
let c: C
113+
var p: UnsafePointer<Int>
114+
115+
init(_ c: C) {
116+
self.c = c
117+
self.p = UnsafePointer<Int>(bitPattern: 0)!
118+
withUnsafePointer(to: c.i) {
119+
self.p = $0
120+
}
121+
}
122+
123+
@lifetime(borrow self)
124+
func getIntSpan() -> IntSpan {
125+
let span = unsafe Span(_unsafeStart: p, count: 1)
126+
return unsafe _overrideLifetime(span, borrowing: self)
127+
}
128+
}
129+
130+
@available(Span 0.1, *)
131+
@_addressableForDependencies
132+
public struct InlineHolder: IntSpanable {
133+
var i: Int
134+
var c: C
135+
136+
init(_ c: C) {
137+
self.c = c
138+
self.i = c.i
139+
}
140+
141+
@lifetime(borrow self)
142+
func getIntSpan() -> IntSpan {
143+
let a = Builtin.addressOfBorrow(self)
144+
let address = unsafe UnsafePointer<Int>(a)
145+
let span = unsafe Span(_unsafeStart: address, count: 1)
146+
return unsafe _overrideLifetime(span, borrowing: self)
147+
}
148+
}
149+
150+
// 'some Spanable' is AddressableForDependencies.
151+
@available(Span 0.1, *)
152+
@lifetime(borrow spanable)
153+
func getIntSpan(_ spanable: some IntSpanable) -> IntSpan {
154+
spanable.getIntSpan()
155+
}
156+
157+
// 'Holder' is not AddressableForDependencies.
158+
// 'span' depends on the value of the borrowed argument.
159+
//
160+
// CHECK-LABEL: sil {{.*}} [ossa] @$s4test13getHolderSpanys0D0VySiGAA0C0VF : $@convention(thin) (@guaranteed Holder) -> @lifetime(borrow 0) @owned Span<Int> {
161+
// CHECK: bb0(%0 : @noImplicitCopy @guaranteed $Holder):
162+
// CHECK: [[C:%.*]] = apply %{{.*}}<Holder>(%{{.*}}) : $@convention(thin) <τ_0_0 where τ_0_0 : IntSpanable>
163+
// CHECK-SAME: (@in_guaranteed τ_0_0) -> @lifetime(borrow address_for_deps 0) @owned Span<Int>
164+
// CHECK: mark_dependence [unresolved] [[C]] on %0
165+
// CHECK-LABEL: } // end sil function '$s4test13getHolderSpanys0D0VySiGAA0C0VF'
166+
@available(Span 0.1, *)
167+
public func getHolderSpan(_ holder: borrowing Holder) -> IntSpan {
168+
let span = getIntSpan(holder)
169+
return span
170+
}
171+
172+
// CHECK-LABEL: sil [available 9999] [ossa] @$s4test0A10HolderSpanSiyF : $@convention(thin) () -> Int {
173+
// CHECK: [[C1:%.*]] = apply %{{.*}}(%{{.*}}) : $@convention(method) (@owned C, @thin Holder.Type) -> @owned Holder
174+
// CHECK: [[MV:%.*]] = move_value [lexical] [var_decl] [[C1]]
175+
// CHECK: [[C2:%.*]] = apply %{{.*}}([[MV]]) : $@convention(thin) (@guaranteed Holder) -> @lifetime(borrow 0) @owned Span<Int>
176+
// CHECK: [[MD:%.*]] = mark_dependence [unresolved] [[C2]] on %10
177+
// CHECK-LABEL: } // end sil function '$s4test0A10HolderSpanSiyF'
178+
@available(Span 0.1, *)
179+
public func testHolderSpan() -> Int {
180+
let c = C()
181+
let holder = Holder(consume c)
182+
let span = getHolderSpan(holder)
183+
return span[0]
184+
}
185+
186+
// 'InlineHolder' is AddressableForDependencies.
187+
// 'span' depends on the address of the borrowed argument.
188+
//
189+
// CHECK-LABEL: sil [available 9999] [ossa] @$s4test19getInlineHolderSpanys0E0VySiGAA0cD0VF : $@convention(thin)
190+
// CHECK-SAME: (@in_guaranteed InlineHolder) -> @lifetime(borrow address_for_deps 0) @owned Span<Int> {
191+
// CHECK: [[VAR:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign]
192+
// CHECK: [[A:%.*]] = moveonlywrapper_to_copyable_addr [[VAR]]
193+
// CHECK: [[C:%.*]] = apply %{{.*}}<InlineHolder>([[A]]) : $@convention(thin) <τ_0_0 where τ_0_0 : IntSpanable>
194+
// CHECK-SAME: (@in_guaranteed τ_0_0) -> @lifetime(borrow address_for_deps 0) @owned Span<Int>
195+
// CHECK: [[MD:%.*]] = mark_dependence [unresolved] [[C]] on [[A]]
196+
// CHECK-LABEL: } // end sil function '$s4test19getInlineHolderSpanys0E0VySiGAA0cD0VF'
197+
@available(Span 0.1, *)
198+
public func getInlineHolderSpan(_ holder: borrowing InlineHolder) -> IntSpan {
199+
let span = getIntSpan(holder)
200+
return span
201+
}
202+
203+
// CHECK-LABEL: sil [available 9999] [ossa] @$s4test0A16InlineHolderSpanSiyF : $@convention(thin) () -> Int {
204+
// CHECK: [[STK:%.*]] = alloc_stack $InlineHolder
205+
// CHECK: [[SB:%.*]] = store_borrow %{{.*}} to [[STK]]
206+
// CHECK: [[C:%.*]] = apply %{{.*}}([[SB]]) : $@convention(thin)
207+
// CHECK-SAME: (@in_guaranteed InlineHolder) -> @lifetime(borrow address_for_deps 0) @owned Span<Int>
208+
// CHECK: [[MD:%.*]] = mark_dependence [unresolved] [[C]] on [[SB]]
209+
// CHECK: [[MV:%.*]] = move_value [var_decl] [[MD]]
210+
// CHECK: destroy_value [[MV]]
211+
// CHECK: end_borrow [[SB]]
212+
// CHECK: dealloc_stack [[STK]]
213+
// CHECK-LABEL: } // end sil function '$s4test0A16InlineHolderSpanSiyF'
214+
@available(Span 0.1, *)
215+
public func testInlineHolderSpan() -> Int {
216+
let c = C()
217+
let holder = InlineHolder(consume c)
218+
let span = getInlineHolderSpan(holder)
219+
return span[0]
220+
}

0 commit comments

Comments
 (0)