@@ -118,3 +118,95 @@ public func testWithMemoryRebound<T, Result>(
118
118
}
119
119
return try body(.init(rawPtr))
120
120
}
121
+
122
+ @_silgen_name( " takeRawPointer" )
123
+ func takeRawPointer( _: UnsafeRawPointer)
124
+
125
+ @_silgen_name ( " takeObjectPointer " )
126
+ func takeObjectPointer( _: UnsafePointer < AnyObject > )
127
+
128
+ @_silgen_name( " takeStringPointer" )
129
+ func takeStringPointer( _: UnsafePointer < String > )
130
+
131
+ @_silgen_name( " takeDictionaryPointer" )
132
+ func takeDictionaryPointer( _: UnsafePointer < Dictionary < Int , Int > > )
133
+
134
+ // Test conversion of a dictionary to a raw pointer. This is not a sane
135
+ // conversion, but the compiler must still generate memory-safe code.
136
+ //
137
+ // A dictionary is an eager-move type, so it will be destroyed at its
138
+ // last use. An address_to_pointer operation escapes the pointer, so
139
+ // the compiler never sees those pointer uses. The pointer's scope
140
+ // must be protected by a fix_lifetime.
141
+ //
142
+ // NOTE: If this test triggers a compiler error because of the unsafe
143
+ // inout conversion, then we have arrived at a better world. Delete
144
+ // the test. The eagerMoveToPointer test below is sufficient.
145
+ //
146
+ // CHECK-LABEL: sil [stack_protection] @$s18pointer_conversion22dictionaryToRawPointeryyF : $@convention(thin) () -> () {
147
+ // CHECK: [[A:%.*]] = alloc_stack $Dictionary<Int, Int>, var, name "d"
148
+ // CHECK: [[PTR:%.*]] = address_to_pointer [stack_protection] [[A]] : $*Dictionary<Int, Int> to $Builtin.RawPointer
149
+ // CHECK: [[UP:%.*]] = struct $UnsafeRawPointer ([[PTR]] : $Builtin.RawPointer)
150
+ // CHECK: apply %{{.*}}([[UP]]) : $@convention(thin) (UnsafeRawPointer) -> ()
151
+ // CHECK: [[D:%.*]] = load %0 : $*Dictionary<Int, Int>
152
+ // CHECK: fix_lifetime [[D]] : $Dictionary<Int, Int>
153
+ // CHECK: release_value [[D]] : $Dictionary<Int, Int>
154
+ // CHECK: dealloc_stack [[A]] : $*Dictionary<Int, Int>
155
+ // CHECK-LABEL: } // end sil function '$s18pointer_conversion22dictionaryToRawPointeryyF'
156
+ public func dictionaryToRawPointer( ) {
157
+ var d = [ 1 : 1 ]
158
+ takeRawPointer ( & d)
159
+ }
160
+
161
+ // Test conversion of a non-trivial eager-move type to a raw pointer.
162
+ // This currently only applies to Dictionary, but converting a
163
+ // dictionary to a pointer will likely be a compiler error in the
164
+ // future. So force an eagerMove type here.
165
+ //
166
+ // An eager-move type will be destroyed at its last use. An
167
+ // address_to_pointer operation escapes the pointer, so the compiler
168
+ // never sees those pointer uses. The pointer's scope must be
169
+ // protected by a fix_lifetime.
170
+ // CHECK-LABEL: sil [stack_protection] @$s18pointer_conversion18eagerMoveToPointer1oyyXln_tF : $@convention(thin) (@owned AnyObject) -> () {
171
+ // CHECK: [[A:%.*]] = alloc_stack [moveable_value_debuginfo] $AnyObject, var, name "o"
172
+ // CHECK: [[PTR:%.*]] = address_to_pointer [stack_protection] [[A]] : $*AnyObject to $Builtin.RawPointer
173
+ // CHECK: [[UP:%.*]] = struct $UnsafePointer<AnyObject> ([[PTR]] : $Builtin.RawPointer)
174
+ // CHECK: apply %{{.*}}([[UP]]) : $@convention(thin) (UnsafePointer<AnyObject>) -> ()
175
+ // CHECK: [[O:%.*]] = load [[A]] : $*AnyObject
176
+ // CHECK: fix_lifetime [[O]] : $AnyObject
177
+ // CHECK: strong_release [[O]] : $AnyObject
178
+ // CHECK: dealloc_stack [[A]] : $*AnyObject
179
+ // CHECK-LABEL: } // end sil function '$s18pointer_conversion18eagerMoveToPointer1oyyXln_tF'
180
+ public func eagerMoveToPointer( @_eagerMove o: consuming AnyObject ) {
181
+ takeObjectPointer ( & o)
182
+ }
183
+
184
+ // CHECK-LABEL: sil [stack_protection] @$s18pointer_conversion15stringToPointer2ssySS_tF : $@convention(thin) (@guaranteed String) -> () {
185
+ // CHECK: [[A:%.*]] = alloc_stack $String, var, name "s"
186
+ // CHECK: [[PTR:%.*]] = address_to_pointer [stack_protection] [[A]] : $*String to $Builtin.RawPointer
187
+ // CHECK: [[UP:%.*]] = struct $UnsafePointer<String> ([[PTR]] : $Builtin.RawPointer)
188
+ // CHECK: apply {{.*}}([[UP]]) : $@convention(thin) (UnsafePointer<String>) -> ()
189
+ // CHECK: [[S:%.*]] = load [[A]] : $*String
190
+ // CHECK: fix_lifetime [[S]] : $String
191
+ // CHECK: release_value [[S]] : $String
192
+ // CHECK: dealloc_stack [[A]] : $*String
193
+ // CHECK-LABEL: } // end sil function '$s18pointer_conversion15stringToPointer2ssySS_tF'
194
+ public func stringToPointer( ss: String ) {
195
+ var s = ss
196
+ takeStringPointer ( & s)
197
+ }
198
+
199
+ // CHECK-LABEL: sil [stack_protection] @$s18pointer_conversion19dictionaryToPointer2ddySDyS2iG_tF : $@convention(thin) (@guaranteed Dictionary<Int, Int>) -> () {
200
+ // CHECK: [[A:%.*]] = alloc_stack $Dictionary<Int, Int>, var, name "d"
201
+ // CHECK: [[PTR:%.*]] = address_to_pointer [stack_protection] [[A]] : $*Dictionary<Int, Int> to $Builtin.RawPointer
202
+ // CHECK: [[UP:%.*]] = struct $UnsafePointer<Dictionary<Int, Int>> ([[PTR]] : $Builtin.RawPointer)
203
+ // CHECK: apply %{{.*}}([[UP]]) : $@convention(thin) (UnsafePointer<Dictionary<Int, Int>>) -> ()
204
+ // CHECK: [[D:%.*]] = load [[A]] : $*Dictionary<Int, Int>
205
+ // CHECK: fix_lifetime [[D]] : $Dictionary<Int, Int>
206
+ // CHECK: release_value [[D]] : $Dictionary<Int, Int>
207
+ // CHECK: dealloc_stack [[A]] : $*Dictionary<Int, Int>
208
+ // CHECK-LABEL: } // end sil function '$s18pointer_conversion19dictionaryToPointer2ddySDyS2iG_tF'
209
+ public func dictionaryToPointer( dd: Dictionary < Int , Int > ) {
210
+ var d = dd
211
+ takeDictionaryPointer ( & d)
212
+ }
0 commit comments