@@ -233,6 +233,9 @@ extension LifetimeDependence {
233
233
234
234
/// Construct LifetimeDependence from mark_dependence [unresolved]
235
235
///
236
+ /// For any LifetimeDependence constructed from a mark_dependence,
237
+ /// its `dependentValue` will be the result of the mark_dependence.
238
+ ///
236
239
/// TODO: Add SIL verification that all mark_depedence [unresolved]
237
240
/// have a valid LifetimeDependence.
238
241
init ? ( _ markDep: MarkDependenceInst , _ context: some Context ) {
@@ -485,8 +488,7 @@ extension LifetimeDependence {
485
488
-> WalkResult {
486
489
var useDefVisitor = UseDefVisitor ( context, visitor)
487
490
defer { useDefVisitor. deinitialize ( ) }
488
- let owner = value. ownership == . owned ? value : nil
489
- return useDefVisitor. walkUp ( value: value, owner)
491
+ return useDefVisitor. walkUp ( valueOrAddress: value)
490
492
}
491
493
492
494
private struct UseDefVisitor : LifetimeDependenceUseDefWalker {
@@ -534,6 +536,18 @@ extension LifetimeDependence {
534
536
}
535
537
}
536
538
539
+ /// Walk up the lifetime dependence
540
+ ///
541
+ /// This uses LifetimeDependenceUseDefWalker to find the introducers
542
+ /// of a dependence chain, which represent the value's "inherited"
543
+ /// dependencies. This stops at an address, unless the address refers
544
+ /// to a singly-initialized temprorary, in which case it continues to
545
+ /// walk up the stored value.
546
+ ///
547
+ /// This overrides LifetimeDependenceUseDefWalker to stop at a value
548
+ /// that introduces an immutable variable: move_value [var_decl] or
549
+ /// begin_borrow [var_decl], and to stop at an access of a mutable
550
+ /// variable: begin_access.
537
551
struct VariableIntroducerUseDefWalker : LifetimeDependenceUseDefWalker {
538
552
let context : Context
539
553
// This visited set is only really needed for instructions with
@@ -576,24 +590,36 @@ struct VariableIntroducerUseDefWalker : LifetimeDependenceUseDefWalker {
576
590
}
577
591
return walkUpDefault ( dependent: value, owner: owner)
578
592
}
593
+
594
+ mutating func walkUp( address: Value ) -> WalkResult {
595
+ if let beginAccess = address. definingInstruction as? BeginAccessInst {
596
+ return introducer ( beginAccess, nil )
597
+ }
598
+ return walkUpDefault ( address: address)
599
+ }
579
600
}
580
601
581
- /// Walk up dominating dependent values .
602
+ /// Walk up the lifetime dependence chain .
582
603
///
583
- /// Find the roots of a dependence chain stopping at phis. These root
584
- /// LifeDependence instances are the value's "inherited"
585
- /// dependencies. In this example, the dependence root is copied,
586
- /// borrowed, and forwarded before being used as the base operand of
587
- /// `mark_dependence`. The dependence "root" is the parent of the
588
- /// outer-most dependence scope.
604
+ /// This finds the introducers of a dependence chain. which represent
605
+ /// the value's "inherited" dependencies. This stops at phis; all
606
+ /// introducers dominate. This stops at addresses in general, but if
607
+ /// the value is loaded from a singly-initialized location, then it
608
+ /// continues walking up the value stored by the initializer. This
609
+ /// bypasses the copies to temporary memory locations emitted by SILGen.
610
+ ///
611
+ /// In this example, the dependence root is
612
+ /// copied, borrowed, and forwarded before being used as the base
613
+ /// operand of `mark_dependence`. The dependence "root" is the parent
614
+ /// of the outer-most dependence scope.
589
615
///
590
616
/// %root = apply // lifetime dependence root
591
617
/// %copy = copy_value %root
592
618
/// %parent = begin_borrow %copy // lifetime dependence parent value
593
619
/// %base = struct_extract %parent // lifetime dependence base value
594
620
/// %dependent = mark_dependence [nonescaping] %value on %base
595
621
///
596
- /// This extends the ForwardingDefUseWalker , which finds the
622
+ /// This extends the ForwardingUseDefWalker , which finds the
597
623
/// forward-extended lifetime introducers. Certain forward-extended
598
624
/// lifetime introducers can inherit a lifetime dependency from their
599
625
/// operand: namely copies, moves, and borrows. These introducers are
@@ -631,7 +657,7 @@ struct VariableIntroducerUseDefWalker : LifetimeDependenceUseDefWalker {
631
657
/// needWalk(for value: Value) -> Bool
632
658
///
633
659
/// Start walking:
634
- /// walkUp(value : Value) -> WalkResult
660
+ /// walkUp(valueOrAddress : Value) -> WalkResult
635
661
protocol LifetimeDependenceUseDefWalker : ForwardingUseDefWalker where PathContext == Value ? {
636
662
var context : Context { get }
637
663
@@ -642,14 +668,28 @@ protocol LifetimeDependenceUseDefWalker : ForwardingUseDefWalker where PathConte
642
668
mutating func needWalk( for value: Value , _ owner: Value ? ) -> Bool
643
669
644
670
mutating func walkUp( value: Value , _ owner: Value ? ) -> WalkResult
671
+
672
+ mutating func walkUp( address: Value ) -> WalkResult
645
673
}
646
674
647
675
// Implement ForwardingUseDefWalker
648
676
extension LifetimeDependenceUseDefWalker {
677
+ mutating func walkUp( valueOrAddress: Value ) -> WalkResult {
678
+ if valueOrAddress. type. isAddress {
679
+ return walkUp ( address: valueOrAddress)
680
+ }
681
+ let owner = valueOrAddress. ownership == . owned ? valueOrAddress : nil
682
+ return walkUp ( value: valueOrAddress, owner)
683
+ }
684
+
649
685
mutating func walkUp( value: Value , _ owner: Value ? ) -> WalkResult {
650
686
walkUpDefault ( dependent: value, owner: owner)
651
687
}
652
688
689
+ mutating func walkUp( address: Value ) -> WalkResult {
690
+ walkUpDefault ( address: address)
691
+ }
692
+
653
693
// Extend ForwardingUseDefWalker to handle copies, moves, and
654
694
// borrows. Also transitively walk up other lifetime dependencies to
655
695
// find the roots.
@@ -691,17 +731,12 @@ extension LifetimeDependenceUseDefWalker {
691
731
return walkUpDefault ( forwarded: value, owner)
692
732
}
693
733
694
- private mutating func walkUp( newLifetime: Value ) -> WalkResult {
695
- let newOwner = newLifetime. ownership == . owned ? newLifetime : nil
696
- return walkUp ( value: newLifetime, newOwner)
697
- }
698
-
699
734
// Walk up from a load of a singly-initialized address to find the
700
735
// dependence root of the stored value. This ignores mutable
701
736
// variables, which require an access scope. This ignores applies
702
737
// because an lifetime dependence will already be expressed as a
703
738
// mark_dependence.
704
- private mutating func walkUp ( address: Value ) -> WalkResult {
739
+ mutating func walkUpDefault ( address: Value ) -> WalkResult {
705
740
if let ( _, initializingStore) =
706
741
address. accessBase. findSingleInitializer ( context) {
707
742
switch initializingStore {
@@ -715,6 +750,11 @@ extension LifetimeDependenceUseDefWalker {
715
750
}
716
751
return introducer ( address, nil )
717
752
}
753
+
754
+ private mutating func walkUp( newLifetime: Value ) -> WalkResult {
755
+ let newOwner = newLifetime. ownership == . owned ? newLifetime : nil
756
+ return walkUp ( value: newLifetime, newOwner)
757
+ }
718
758
}
719
759
720
760
/// Walk down dependent values.
0 commit comments