Skip to content

Commit d44490e

Browse files
committed
Add tests for SILGen support of @_addressable annotations.
1 parent a4bfa3f commit d44490e

File tree

1 file changed

+194
-0
lines changed

1 file changed

+194
-0
lines changed
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
// RUN: %target-swift-frontend %s -emit-sil \
2+
// RUN: -o /dev/null \
3+
// RUN: -verify \
4+
// RUN: -sil-verify-all \
5+
// RUN: -enable-builtin-module \
6+
// RUN: -module-name test \
7+
// RUN: -enable-experimental-feature Lifetimes \
8+
// RUN: -enable-experimental-feature AddressableTypes \
9+
// RUN: -enable-experimental-feature AddressableParameters
10+
11+
// RUN: %target-swift-frontend %s -emit-silgen \
12+
// RUN: -sil-verify-all \
13+
// RUN: -enable-builtin-module \
14+
// RUN: -module-name test \
15+
// RUN: -enable-experimental-feature Lifetimes \
16+
// RUN: -enable-experimental-feature AddressableTypes \
17+
// RUN: -enable-experimental-feature AddressableParameters \
18+
// RUN: 2>&1 | %FileCheck %s
19+
20+
// REQUIRES: swift_in_compiler
21+
// REQUIRES: swift_feature_Lifetimes
22+
// REQUIRES: swift_feature_AddressableTypes
23+
// REQUIRES: swift_feature_AddressableParameters
24+
25+
import Builtin
26+
27+
class C {
28+
var p: Builtin.RawPointer
29+
init(p: Builtin.RawPointer) { self.p = p }
30+
31+
// unsupported annotation
32+
@_addressableSelf
33+
func method() {}
34+
}
35+
36+
struct NE: ~Escapable {
37+
var p: Builtin.RawPointer
38+
}
39+
40+
struct PtrHolder {
41+
var field: Builtin.RawPointer
42+
}
43+
44+
struct CHolder {
45+
var field: C
46+
}
47+
48+
struct IHolder {
49+
var field: Int
50+
}
51+
52+
@_lifetime(borrow ptr)
53+
func depends(onPtr ptr: Builtin.RawPointer) -> NE {
54+
NE(p: ptr)
55+
}
56+
57+
// FIXME: Allowed now, but should be prohibited if projection dependence carries exclusivity.
58+
// rdar://153670930 ([nonescapable] extend access scopes for trivial value (UnsafePointer) dependencies)
59+
@_lifetime(&holder)
60+
func testTrivialField(holder: inout PtrHolder, other: Builtin.RawPointer) -> NE {
61+
// copy holder.field
62+
// end_access holder.field
63+
let ne = depends(onPtr: holder.field)
64+
// mark_dependence ne on holder
65+
holder.field = other
66+
return ne
67+
}
68+
69+
@_lifetime(borrow c)
70+
func depends(onC c: C) -> NE {
71+
let ne = NE(p: c.p)
72+
return _overrideLifetime(ne, borrowing: c)
73+
}
74+
75+
// OK: Correctly diagnoses the exclusivity violation.
76+
@_lifetime(&holder)
77+
func testObjectField(holder: inout CHolder, other: C) -> NE {
78+
// copy holder.field
79+
// end_access holder.field
80+
let ne = depends(onC: holder.field) // expected-note{{conflicting access is here}}
81+
// mark_dependence ne on holder
82+
holder.field = other // expected-error{{overlapping accesses to 'holder.field', but modification requires exclusive access; consider copying to a local variable}}
83+
return ne
84+
}
85+
86+
// OK
87+
@_lifetime(&holder)
88+
func testAddress(holder: inout IHolder) -> NE {
89+
// Requires rdar://137608270 ([borrows] Add Builtin.addressof() support for @addressable arguments)
90+
depends(onPtr: Builtin.addressOfBorrow(holder))
91+
}
92+
93+
@_lifetime(borrow i)
94+
func depends(onInt i: @_addressable Int) -> NE {
95+
NE(p: Builtin.addressOfBorrow(i))
96+
}
97+
98+
// OK: no escape diagnostic because the addressable dependency is on the parameter address.
99+
@_lifetime(&holder)
100+
func testAddressableTrivialField(holder: inout IHolder) -> NE{
101+
// load holder.field
102+
// end_access holder.field
103+
// alloc_stack Int
104+
// store
105+
return depends(onInt: holder.field)
106+
// mark_dependence on alloc_stack
107+
// (the addressable dependence needs to be on the passed-in address)
108+
}
109+
110+
@_lifetime(borrow x)
111+
func depends(onCAddress x: @_addressable C) -> NE {
112+
let ne = NE(p: x.p)
113+
return _overrideLifetime(ne, borrowing: x)
114+
}
115+
116+
// OK: no escape diagnostic because the addressable dependency is on the parameter address.
117+
@_lifetime(&holder)
118+
func testAddressableObjectField(holder: inout CHolder) -> NE {
119+
// tmp = load [copy] holder.field
120+
// end_access holder.field
121+
// alloc_stack
122+
// store tmp
123+
return depends(onCAddress: holder.field)
124+
// mark_dependence ne on alloc_stack
125+
}
126+
127+
// Copyable to test the absence of temporaries.
128+
@_addressableForDependencies
129+
struct Cell<T> {
130+
var t: T
131+
}
132+
133+
struct CellHolder: ~Copyable {
134+
var field: Cell<Int>
135+
}
136+
137+
@_lifetime(borrow x)
138+
func depends(onCell x: borrowing Cell<Int>) -> NE {
139+
NE(p: Builtin.addressOfBorrow(x))
140+
}
141+
142+
// OK: no escape diagnostic because the addressable dependency is on the parameter address.
143+
@_lifetime(&holder)
144+
func testAddressableType(holder: inout CellHolder) -> NE {
145+
// tmp = load [copy] holder.field
146+
// end_access holder.field
147+
// alloc_stack
148+
// store tmp
149+
return depends(onCell: holder.field)
150+
// mark_dependence ne on alloc_stack
151+
}
152+
153+
/* FIXME: Invalid SIL: rdar://152273896 (SILGen: @_addressableSelf support for class methods)
154+
func testAddressableClass(c: C) {
155+
c.method()
156+
}
157+
*/
158+
159+
struct Object {
160+
var c: C
161+
162+
@_addressableSelf
163+
func method() {}
164+
}
165+
166+
struct UniquePointer<T>: ~Copyable {
167+
var _p: UnsafePointer<T>
168+
169+
var value: T { unsafeAddress { _p } }
170+
}
171+
172+
// No copy allowed. A copy would be invalid when class 'C' is imported from C++.
173+
//
174+
// CHECK-LABEL: sil hidden [ossa] @$s4test0A15AddressableSelf2upyAA13UniquePointerVyAA6ObjectVG_tF : $@convention(thin) (@guaranteed UniquePointer<Object>) -> () {
175+
// CHECK: bb0(%0 : @guaranteed $UniquePointer<Object>):
176+
// CHECK: [[CP:%[0-9]+]] = copy_value %0
177+
// CHECK: [[MNC:%[0-9]+]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[CP]]
178+
// CHECK: [[BB:%[0-9]+]] = begin_borrow [[MNC]]
179+
// CHECK: [[PTR:%[0-9]+]] = struct_extract %{{.*}}, #UnsafePointer._rawValue
180+
// CHECK: [[ADR:%[0-9]+]] = pointer_to_address [[PTR]] to [strict] $*Object
181+
// CHECK: [[MD:%[0-9]+]] = mark_dependence [unresolved] [[ADR]] on [[BB]]
182+
// CHECK-NOT: load
183+
// CHECK-NOT: alloc_stack
184+
// CHECK-NOT: store
185+
// CHECK: apply %{{.*}}([[MD]]) : $@convention(method) (@in_guaranteed Object) -> ()
186+
// CHECK-LABEL: } // end sil function '$s4test0A15AddressableSelf2upyAA13UniquePointerVyAA6ObjectVG_tF'
187+
func testAddressableSelf(up: borrowing UniquePointer<Object>) {
188+
// tmp = load [copy] up.value
189+
// end_access up.value
190+
// alloc_stack
191+
// store tmp
192+
// apply method(tmp)
193+
up.value.method()
194+
}

0 commit comments

Comments
 (0)