@@ -104,6 +104,7 @@ func gatherVariableIntroducers(for value: Value, _ context: Context)
104104/// A lifetime dependence identifies its parent value, the kind of
105105/// scope that the parent value represents, and a dependent value.
106106struct LifetimeDependence : CustomStringConvertible {
107+ // TODO: handle trivial values based on variable binding
107108 enum Scope : CustomStringConvertible {
108109 /// A guaranteed or inout argument whose scope is provided by the caller
109110 /// and covers the entire function and any dependent results or yields.
@@ -115,7 +116,7 @@ struct LifetimeDependence : CustomStringConvertible {
115116 /// An owned value whose OSSA lifetime encloses nonescapable values
116117 case owned( Value )
117118 /// An borrowed value whose OSSA lifetime encloses nonescapable values
118- case borrowed( Value )
119+ case borrowed( BeginBorrowValue )
119120 /// Singly-initialized addressable storage (likely for an
120121 /// immutable address-only value). The lifetime extends until the
121122 /// memory is destroyed. e.g. A value produced by an @in
@@ -127,7 +128,8 @@ struct LifetimeDependence : CustomStringConvertible {
127128 /// If `initializingStore` is nil, then the `initialAddress` is
128129 /// initialized on function entry.
129130 case initialized( initialAddress: Value , initializingStore: Instruction ? )
130- // TODO: make .unknown a SIL Verification error
131+ // TODO: Add SIL verification that no mark_depedence [unresolved] has an unknown LifetimeDependence.
132+ // This currently requires stack allocations to be singly initialized.
131133 case unknown( Value )
132134
133135 var parentValue : Value {
@@ -136,7 +138,7 @@ struct LifetimeDependence : CustomStringConvertible {
136138 case let . access( beginAccess) : return beginAccess
137139 case let . yield( value) : return value
138140 case let . owned( value) : return value
139- case let . borrowed( value ) : return value
141+ case let . borrowed( beginBorrow ) : return beginBorrow . value
140142 case let . initialized( initialAddress, _) : return initialAddress
141143 case let . unknown( value) : return value
142144 }
@@ -152,8 +154,8 @@ struct LifetimeDependence : CustomStringConvertible {
152154 precondition ( value. definingInstruction is BeginApplyInst )
153155 case let . owned( value) :
154156 precondition ( value. ownership == . owned)
155- case let . borrowed( value ) :
156- precondition ( value. ownership == . guaranteed)
157+ case let . borrowed( beginBorrow ) :
158+ precondition ( beginBorrow . value. ownership == . guaranteed)
157159 case let . initialized( initialAddress, initializingStore) :
158160 precondition ( initialAddress. type. isAddress, " expected an address " )
159161 precondition ( initialAddress is AllocStackInst
@@ -236,8 +238,7 @@ extension LifetimeDependence {
236238 /// For any LifetimeDependence constructed from a mark_dependence, its `dependentValue` will be the result of the
237239 /// mark_dependence.
238240 ///
239- /// TODO: Add SIL verification that all mark_depedence [unresolved]
240- /// have a valid LifetimeDependence.
241+ /// Returns 'nil' for dependence on a trivial value.
241242 init ? ( _ markDep: MarkDependenceInst , _ context: some Context ) {
242243 switch markDep. dependenceKind {
243244 case . Unresolved, . NonEscaping:
@@ -286,16 +287,15 @@ private extension Value {
286287}
287288
288289extension LifetimeDependence . Scope {
289- /// Construct a lifetime dependence scope from the base value that
290- /// other values depend on. This derives the kind of dependence
291- /// scope and its parentValue from `base`.
290+ /// Construct a lifetime dependence scope from the base value that other values depend on. This derives the kind of
291+ /// dependence scope and its parentValue from `base`.
292292 ///
293- /// `base` represents the OSSA lifetime that the dependent value
294- /// must be used within . If `base` is owned , then it directly
295- /// defines the parent lifetime. If `base` is guaranteed, then it
296- /// must have a single borrow introducer, which defines the parent
297- /// lifetime. `base` must not be derived from a guaranteed phi or
298- /// forwarded (via struct/tuple) from multiple guaranteed values .
293+ /// `base` represents the OSSA lifetime that the dependent value must be used within. If `base` is owned, then it
294+ /// directly defines the parent lifetime . If `base` is guaranteed , then it must have a single borrow introducer, which
295+ /// defines the parent lifetime. `base` must not be derived from a guaranteed phi or forwarded (via struct/tuple) from
296+ /// multiple guaranteed values.
297+ ///
298+ /// Returns 'nil' for dependence on a trivial value .
299299 init ? ( base: Value , _ context: some Context ) {
300300 if base. type. isAddress {
301301 guard let scope = Self ( address: base, context) else {
@@ -321,6 +321,7 @@ extension LifetimeDependence.Scope {
321321 }
322322 }
323323
324+ /// Returns 'nil' for dependence on a trivial value.
324325 private init ? ( address: Value , _ context: some Context ) {
325326 switch address. enclosingAccessScope {
326327 case let . scope( access) :
@@ -333,6 +334,7 @@ extension LifetimeDependence.Scope {
333334 }
334335 }
335336
337+ /// Returns 'nil' for dependence on a trivial value.
336338 init ? ( accessBase: AccessBase , address: Value , _ context: some Context ) {
337339 switch accessBase {
338340 case let . box( projectBox) :
@@ -342,10 +344,7 @@ extension LifetimeDependence.Scope {
342344 }
343345 self = scope
344346 case let . stack( allocStack) :
345- guard let scope = Self ( allocation: allocStack, context) else {
346- return nil
347- }
348- self = scope
347+ self = Self ( allocation: allocStack, context)
349348 case . global:
350349 self = . unknown( address)
351350 case . class, . tail:
@@ -378,6 +377,7 @@ extension LifetimeDependence.Scope {
378377 }
379378 }
380379
380+ /// Returns 'nil' for dependence on a trivial value.
381381 private init ? ( guaranteed base: Value , _ context: some Context ) {
382382 // If introducers is empty, then the dependence is on a trivial value, so
383383 // there is no dependence scope.
@@ -390,7 +390,7 @@ extension LifetimeDependence.Scope {
390390 " guaranteed phis not allowed when diagnosing lifetime dependence " )
391391 switch beginBorrow {
392392 case . beginBorrow, . loadBorrow:
393- self = . borrowed( beginBorrow. value )
393+ self = . borrowed( beginBorrow)
394394 case let . beginApply( value) :
395395 self = . yield( value)
396396 case let . functionArgument( arg) :
@@ -410,12 +410,33 @@ extension LifetimeDependence.Scope {
410410 self = . yield( result)
411411 }
412412
413- private init ? ( allocation: AllocStackInst , _ context: Context ) {
413+ private init ( allocation: AllocStackInst , _ context: Context ) {
414414 if let initializer = allocation. accessBase. findSingleInitializer ( context) {
415415 self = . initialized( initialAddress: initializer. initialAddress,
416416 initializingStore: initializer. initializingStore)
417+ return
418+ }
419+ self = . unknown( allocation)
420+ }
421+ }
422+
423+ extension LifetimeDependence . Scope {
424+ /// Ignore "irrelevent" borrow scopes: load_borrow or begin_borrow without [var_decl]
425+ func ignoreBorrowScope( _ context: some Context ) -> LifetimeDependence . Scope ? {
426+ guard case let . borrowed( beginBorrowVal) = self else {
427+ return self
428+ }
429+ switch beginBorrowVal {
430+ case let . beginBorrow( bb) :
431+ if bb. isFromVarDecl {
432+ return self
433+ }
434+ return LifetimeDependence . Scope ( base: bb. borrowedValue, context) ? . ignoreBorrowScope ( context)
435+ case let . loadBorrow( lb) :
436+ return LifetimeDependence . Scope ( base: lb. address, context)
437+ default :
438+ fatalError ( " Scope.borrowed must begin begin_borrow or load_borrow " )
417439 }
418- return nil
419440 }
420441}
421442
@@ -448,8 +469,8 @@ extension LifetimeDependence.Scope {
448469 // how would we ensure that the borrowed mark_dependence value
449470 // is within this value's OSSA lifetime?
450471 return computeLinearLiveness ( for: value, context)
451- case let . borrowed( value ) :
452- return computeLinearLiveness ( for: value, context)
472+ case let . borrowed( beginBorrow ) :
473+ return computeLinearLiveness ( for: beginBorrow . value, context)
453474 case let . initialized( initialAddress, initializingStore) :
454475 return LifetimeDependence . Scope. computeInitializedRange (
455476 initialAddress: initialAddress, initializingStore: initializingStore,
0 commit comments