Skip to content

Commit 7b83c09

Browse files
committed
Unit tests for '@'_addressable lifetime dependence.
1 parent 3019c84 commit 7b83c09

File tree

2 files changed

+119
-4
lines changed

2 files changed

+119
-4
lines changed

test/SILOptimizer/lifetime_dependence/dependence_insertion.sil

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,17 @@ struct NCE: ~Escapable, ~Copyable {
2525
init()
2626
}
2727

28+
struct TrivialHolder {
29+
var pointer: UnsafeRawPointer
30+
}
31+
32+
struct Holder {
33+
var object: AnyObject
34+
}
35+
36+
@_addressableForDependencies
37+
struct AddressableForDeps {}
38+
2839
sil @getPtr : $@convention(thin) () -> @out UnsafeRawPointer
2940
sil @getSpan : $@convention(thin) (@in_guaranteed AnyObject) -> @lifetime(borrow 0) @out NE
3041
sil @getInoutSpan : $@convention(thin) (@inout AnyObject) -> @lifetime(borrow 0) @out NCE
@@ -92,3 +103,39 @@ bb0(%0 : $*AnyObject):
92103
dealloc_stack %1
93104
return %7
94105
}
106+
107+
// =============================================================================
108+
// @_addressable
109+
// =============================================================================
110+
111+
sil hidden [ossa] @addressableArg : $@convention(method) (@in_guaranteed Holder) -> @lifetime(borrow address 0) @owned NE {
112+
113+
sil hidden [ossa] @addressableTuple : $@convention(method) (@in_guaranteed (Holder, Holder)) -> @lifetime(borrow address 0) @owned NE {
114+
115+
sil hidden [ossa] @testAddressableArg : $@convention(thin) (Holder) -> Int {
116+
bb0(%0 : $Holder):
117+
debug_value %0, let, name "arg", argno 1
118+
%2 = alloc_stack $Holder
119+
store %0 to [trivial] %2
120+
%4 = function_ref @addressableArg : $@convention(thin) (@in_guaranteed Holder) -> @lifetime(borrow address 0) @owned NE
121+
%5 = apply %4(%2) : $@convention(thin) (@in_guaranteed Holder) -> @lifetime(borrow address 0) @owned NE
122+
dealloc_stack %2
123+
%7 = move_value [var_decl] %5
124+
debug_value %7, let, name "ne"
125+
%9 = alloc_stack $Int
126+
%10 = begin_borrow %7
127+
%11 = struct_extract %10, #NE.p
128+
%12 = metatype $@thin Int.Type
129+
%13 = metatype $@thick Int.Type
130+
131+
%14 = function_ref @$sSV4load14fromByteOffset2asxSi_xmtlFfA_ : $@convention(thin) <τ_0_0> () -> Int
132+
%15 = apply %14<Int>() : $@convention(thin) <τ_0_0> () -> Int
133+
134+
%16 = function_ref @$sSV4load14fromByteOffset2asxSi_xmtlF : $@convention(method) <τ_0_0> (Int, @thick τ_0_0.Type, UnsafeRawPointer) -> @out τ_0_0
135+
%17 = apply %16<Int>(%9, %15, %13, %11) : $@convention(method) <τ_0_0> (Int, @thick τ_0_0.Type, UnsafeRawPointer) -> @out τ_0_0
136+
end_borrow %10
137+
%19 = load [trivial] %9
138+
dealloc_stack %9
139+
destroy_value %7
140+
return %19
141+
}

test/SILOptimizer/lifetime_dependence/semantics.swift

Lines changed: 72 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,17 @@
33
// RUN: -verify \
44
// RUN: -sil-verify-all \
55
// RUN: -module-name test \
6+
// RUN: -enable-builtin-module \
67
// RUN: -enable-experimental-feature LifetimeDependence \
78
// RUN: -enable-experimental-feature AddressableParameters \
89
// RUN: -enable-experimental-feature AddressableTypes
910

1011
// REQUIRES: swift_in_compiler
1112
// REQUIRES: swift_feature_LifetimeDependence
13+
// REQUIRES: swift_feature_AddressableParameters
14+
// REQUIRES: swift_feature_AddressableTypes
15+
16+
import Builtin
1217

1318
@_unsafeNonescapableResult
1419
@_transparent
@@ -69,6 +74,12 @@ public struct Span<T>: ~Escapable {
6974
self.base = base
7075
self.count = count
7176
}
77+
78+
public subscript(_ position: Int) -> T {
79+
unsafeAddress {
80+
return base!.advanced(by: position)
81+
}
82+
}
7283
}
7384

7485
extension Span {
@@ -131,9 +142,24 @@ struct InnerTrivial {
131142
}
132143
}
133144

145+
struct TrivialHolder {
146+
var p: UnsafePointer<Int>
147+
var pa: UnsafePointer<AddressableInt>
148+
149+
var addressableInt: AddressableInt { unsafeAddress { pa } }
150+
151+
@lifetime(borrow self)
152+
borrowing func span() -> Span<Int> {
153+
Span(base: p, count: 1)
154+
}
155+
}
156+
134157
struct Holder {
135158
let object: AnyObject
136159
var p: UnsafePointer<Int>
160+
var pa: UnsafePointer<AddressableInt>
161+
162+
var addressableInt: AddressableInt { unsafeAddress { pa } }
137163

138164
@lifetime(borrow self)
139165
borrowing func span() -> Span<Int> {
@@ -143,10 +169,11 @@ struct Holder {
143169

144170
@_addressableForDependencies
145171
struct AddressableInt {
146-
let object: AnyObject
172+
let value: Int
147173

148174
@lifetime(borrow self)
149175
borrowing func span() -> Span<Int> {
176+
// TODO: we actually want the address of self.value
150177
let p = UnsafePointer<Int>(Builtin.unprotectedAddressOfBorrow(self))
151178
let span = Span(base: p, count: 1)
152179
return _overrideLifetime(span, borrowing: self)
@@ -159,6 +186,7 @@ struct AddressableObject {
159186

160187
@lifetime(borrow self)
161188
borrowing func span() -> Span<AnyObject> {
189+
// TODO: we actually want the address of self.object
162190
let p = UnsafePointer<AnyObject>(Builtin.unprotectedAddressOfBorrow(self))
163191
let span = Span(base: p, count: 1)
164192
return _overrideLifetime(span, borrowing: self)
@@ -506,29 +534,69 @@ func testReturnObjectTemp(outer: Outer) -> Span<Int> {
506534
// Scoped dependence on addressable parameters
507535
// =============================================================================
508536

537+
// @_addressableForDependencies supports returning a Span.
509538
@lifetime(borrow arg)
510539
func testAddressableInt(arg: AddressableInt) -> Span<Int> {
511540
arg.span()
512541
}
513542

543+
// @_addressableForDependencies supports returning a Span.
514544
@lifetime(borrow arg)
515545
func testAddressableObject(arg: AddressableObject) -> Span<AnyObject> {
516546
arg.span()
517547
}
518548

549+
// Helper: create a dependence on the argument's address.
519550
@lifetime(borrow arg)
520-
func borrowAddressHelper(arg: @addressable Holder) -> Span<Int> {
551+
func dependsOnTrivialAddressHelper(arg: @_addressable TrivialHolder) -> Span<Int> {
521552
arg.span()
522553
}
523554

555+
// Helper: create a dependence on the argument's address.
524556
@lifetime(borrow arg)
525-
func testNonAddressable(arg: Holder) -> Span<Int> {
526-
borrowAddressHelper(arg: arg)
557+
func dependsOnAddressHelper(arg: @_addressable Holder) -> Span<Int> {
558+
arg.span()
527559
}
528560

561+
/* TODO: requires -enable-address-dependencies
562+
563+
// Non-addressable error returning a Span.
564+
@lifetime(borrow arg)
565+
func testTrivialNonAddressable(arg: TrivialHolder) -> Span<Int> {
566+
dependsOnTrivialAddressHelper(arg: arg)
567+
// todo-error @-1{{lifetime-dependent value escapes its scope}
568+
// todo-note @-3{{it depends on the lifetime of variable 'arg'}}
569+
} // todo-note {{this use causes the lifetime-dependent value to escape}}
570+
571+
// Non-addressable error returning a Span.
572+
@lifetime(borrow arg)
573+
func testNonAddressable(arg: Holder) -> Span<Int> {
574+
dependsOnAddressHelper(arg: arg)
575+
// todo-error @-1{{lifetime-dependent value escapes its scope}
576+
// todo-note @-3{{it depends on the lifetime of variable 'arg'}}
577+
} // todo-note {{this use causes the lifetime-dependent value to escape}}
578+
*/
579+
529580
/* TODO: rdar://145872854 (SILGen: @addressable inout arguments are copied)
530581
@lifetime(borrow arg)
531582
func test(arg: inout AddressableInt) -> Span<Int> {
532583
arg.span()
533584
}
585+
586+
// unsafeAddress generates an addressable value with a local scope.
587+
@lifetime(borrow arg)
588+
func testBorrowedAddressableInt(arg: Holder) -> Int {
589+
let span = arg.addressableInt.span()
590+
return span[0]
591+
}
592+
593+
// unsafeAddress generates an addressable value.
594+
// Error returning a dependence on its local scope.
595+
@lifetime(borrow arg)
596+
func testBorrowedAddressableIntReturn(arg: Holder) -> Span<Int> {
597+
arg.addressableInt.span()
598+
// todo-error @-1{{lifetime-dependent value escapes its scope}
599+
// todo-note @-2{{it depends on the lifetime of this parent value}}
600+
} // todo-note {{this use causes the lifetime-dependent value to escape}}
601+
534602
*/

0 commit comments

Comments
 (0)