|
| 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