@@ -181,6 +181,16 @@ static bool isExternalGlobalAddressor(ApplyInst *AI) {
181
181
return funcRef->isGlobalInit () && funcRef->isExternalDeclaration ();
182
182
}
183
183
184
+ // Return true if the given StructExtractInst extracts the RawPointer from
185
+ // Unsafe[Mutable]Pointer.
186
+ static bool isUnsafePointerExtraction (StructExtractInst *SEI) {
187
+ assert (isa<BuiltinRawPointerType>(SEI->getType ().getASTType ()));
188
+ auto &C = SEI->getModule ().getASTContext ();
189
+ auto *decl = SEI->getStructDecl ();
190
+ return decl == C.getUnsafeMutablePointerDecl ()
191
+ || decl == C.getUnsafePointerDecl ();
192
+ }
193
+
184
194
// Given an address base is a block argument, verify that it is actually a box
185
195
// projected from a switch_enum. This is a valid pattern at any SIL stage
186
196
// resulting in a block-type phi. In later SIL stages, the optimizer may form
@@ -231,6 +241,12 @@ AccessedStorage swift::findAccessedStorage(SILValue sourceAddr) {
231
241
if (kind != AccessedStorage::Unidentified)
232
242
return AccessedStorage (address, kind);
233
243
244
+ // If the address producer cannot immediately be classified, follow the
245
+ // use-def chain of address, box, or RawPointer producers.
246
+ assert (address->getType ().isAddress ()
247
+ || isa<SILBoxType>(address->getType ().getASTType ())
248
+ || isa<BuiltinRawPointerType>(address->getType ().getASTType ()));
249
+
234
250
// Handle other unidentified address sources.
235
251
switch (address->getKind ()) {
236
252
default :
@@ -248,6 +264,14 @@ AccessedStorage swift::findAccessedStorage(SILValue sourceAddr) {
248
264
// Don't currently allow any other calls to return an accessed address.
249
265
return AccessedStorage ();
250
266
267
+ case ValueKind::StructExtractInst:
268
+ // Handle nested access to a KeyPath projection. The projection itself
269
+ // uses a Builtin. However, the returned UnsafeMutablePointer may be
270
+ // converted to an address and accessed via an inout argument.
271
+ if (isUnsafePointerExtraction (cast<StructExtractInst>(address)))
272
+ return AccessedStorage (address, AccessedStorage::Unidentified);
273
+ return AccessedStorage ();
274
+
251
275
// A block argument may be a box value projected out of
252
276
// switch_enum. Address-type block arguments are not allowed.
253
277
case ValueKind::SILPHIArgument:
@@ -276,6 +300,12 @@ AccessedStorage swift::findAccessedStorage(SILValue sourceAddr) {
276
300
return AccessedStorage ();
277
301
}
278
302
303
+ // ref_tail_addr project an address from a reference.
304
+ // This is a valid address producer for nested @inout argument
305
+ // access, but it is never used for formal access of identified objects.
306
+ case ValueKind::RefTailAddrInst:
307
+ return AccessedStorage (address, AccessedStorage::Unidentified);
308
+
279
309
// Inductive cases:
280
310
// Look through address casts to find the source address.
281
311
case ValueKind::MarkUninitializedInst:
@@ -297,8 +327,8 @@ AccessedStorage swift::findAccessedStorage(SILValue sourceAddr) {
297
327
continue ;
298
328
299
329
// Access to a Builtin.RawPointer. Treat this like the inductive cases
300
- // above because some RawPointer's originate from identified locations. See
301
- // the special case for global addressors, which return RawPointer above.
330
+ // above because some RawPointers originate from identified locations. See
331
+ // the special case for global addressors, which return RawPointer, above.
302
332
//
303
333
// If the inductive search does not find a valid addressor, it will
304
334
// eventually reach the default case that returns in invalid location. This
@@ -320,11 +350,10 @@ AccessedStorage swift::findAccessedStorage(SILValue sourceAddr) {
320
350
address = cast<SingleValueInstruction>(address)->getOperand (0 );
321
351
continue ;
322
352
323
- // Subobject projections.
353
+ // Address-to-address subobject projections.
324
354
case ValueKind::StructElementAddrInst:
325
355
case ValueKind::TupleElementAddrInst:
326
356
case ValueKind::UncheckedTakeEnumDataAddrInst:
327
- case ValueKind::RefTailAddrInst:
328
357
case ValueKind::TailAddrInst:
329
358
case ValueKind::IndexAddrInst:
330
359
address = cast<SingleValueInstruction>(address)->getOperand (0 );
0 commit comments