@@ -149,7 +149,11 @@ class LocalVariableAccessInfo: CustomStringConvertible {
149
149
case . load:
150
150
self . _isFullyAssigned = false
151
151
case . store:
152
- self . _isFullyAssigned = true
152
+ if let store = localAccess. instruction as? StoringInstruction {
153
+ self . _isFullyAssigned = LocalVariableAccessInfo . isBase ( address: store. source)
154
+ } else {
155
+ self . _isFullyAssigned = true
156
+ }
153
157
case . apply:
154
158
let apply = localAccess. instruction as! FullApplySite
155
159
if let convention = apply. convention ( of: localAccess. operand!) {
@@ -191,6 +195,18 @@ class LocalVariableAccessInfo: CustomStringConvertible {
191
195
return " full-assign: \( _isFullyAssigned == nil ? " unknown " : String ( describing: _isFullyAssigned!) ) "
192
196
+ " \( access) "
193
197
}
198
+
199
+ // Does this address correspond to the local variable's base address? Any writes to this address will be a full
200
+ // assignment. This should match any instructions that the LocalVariableAccessMap initializer below recognizes as an
201
+ // allocation.
202
+ static private func isBase( address: Value ) -> Bool {
203
+ switch address {
204
+ case is AllocBoxInst , is AllocStackInst , is BeginAccessInst :
205
+ return true
206
+ default :
207
+ return false
208
+ }
209
+ }
194
210
}
195
211
196
212
/// Model the formal accesses of an addressible variable introduced by an alloc_box, alloc_stack, or indirect
@@ -363,24 +379,14 @@ extension LocalVariableAccessWalker: AddressUseVisitor {
363
379
return . continueWalk
364
380
}
365
381
366
- // Handle storage type projections, like MarkUninitializedInst. Path projections should not be visited. They only
367
- // occur inside the access .
382
+ // Handle storage type projections, like MarkUninitializedInst. Path projections are visited for field
383
+ // initialization because SILGen does not emit begin_access [init] consistently .
368
384
//
369
- // Exception: stack -allocated temporaries may be treated like local variables for the purpose of finding all
370
- // uses. Such temporaries do not have access scopes, so we need to walk down any projection that may be used to
371
- // initialize the temporary.
385
+ // Stack -allocated temporaries are also treated like local variables for the purpose of finding all uses. Such
386
+ // temporaries do not have access scopes, so we need to walk down any projection that may be used to initialize the
387
+ // temporary.
372
388
mutating func projectedAddressUse( of operand: Operand , into value: Value ) -> WalkResult {
373
- // TODO: we need an abstraction for path projections. For local variables, these cannot occur outside of an access.
374
- switch operand. instruction {
375
- case is StructElementAddrInst , is TupleElementAddrInst , is IndexAddrInst , is TailAddrInst ,
376
- is UncheckedTakeEnumDataAddrInst , is OpenExistentialAddrInst :
377
- return . abortWalk
378
- // Projections used to initialize a temporary
379
- case is InitEnumDataAddrInst , is InitExistentialAddrInst :
380
- fallthrough
381
- default :
382
- return walkDownAddressUses ( address: value)
383
- }
389
+ return walkDownAddressUses ( address: value)
384
390
}
385
391
386
392
mutating func scopedAddressUse( of operand: Operand ) -> WalkResult {
0 commit comments