@@ -145,6 +145,8 @@ class SILValueOwnershipChecker {
145
145
bool isSubobjectProjectionWithLifetimeEndingUses (
146
146
SILValue value,
147
147
const SmallVectorImpl<Operand *> &lifetimeEndingUsers) const ;
148
+ bool hasGuaranteedForwardingIncomingPhiOperandsOnZeroOrAllPaths (
149
+ SILPhiArgument *phi) const ;
148
150
};
149
151
150
152
} // namespace swift
@@ -624,6 +626,39 @@ bool SILValueOwnershipChecker::isSubobjectProjectionWithLifetimeEndingUses(
624
626
});
625
627
}
626
628
629
+ bool SILValueOwnershipChecker::
630
+ hasGuaranteedForwardingIncomingPhiOperandsOnZeroOrAllPaths (
631
+ SILPhiArgument *phi) const {
632
+ bool foundGuaranteedForwardingPhiOperand = false ;
633
+ bool foundNonGuaranteedForwardingPhiOperand = false ;
634
+ phi->visitTransitiveIncomingPhiOperands ([&](auto *, auto *operand) -> bool {
635
+ auto value = operand->get ();
636
+ if (canOpcodeForwardGuaranteedValues (value) ||
637
+ isa<SILFunctionArgument>(value)) {
638
+ foundGuaranteedForwardingPhiOperand = true ;
639
+ if (foundNonGuaranteedForwardingPhiOperand) {
640
+ return false ; /* found error, stop visiting */
641
+ }
642
+ return true ;
643
+ }
644
+ foundNonGuaranteedForwardingPhiOperand = true ;
645
+ if (foundGuaranteedForwardingPhiOperand) {
646
+ return false ; /* found error, stop visiting */
647
+ }
648
+ return true ;
649
+ });
650
+ if (foundGuaranteedForwardingPhiOperand ^
651
+ foundNonGuaranteedForwardingPhiOperand) {
652
+ return true ;
653
+ }
654
+ return errorBuilder.handleMalformedSIL ([&] {
655
+ llvm::errs () << " Malformed @guaranteed phi!\n "
656
+ << " Phi: " << *phi;
657
+ llvm::errs () << " Guaranteed forwarding operand on one path and reborrow "
658
+ " on another!\n " ;
659
+ });
660
+ }
661
+
627
662
bool SILValueOwnershipChecker::checkUses () {
628
663
LLVM_DEBUG (llvm::dbgs () << " Gathering and classifying uses!\n " );
629
664
@@ -686,6 +721,13 @@ bool SILValueOwnershipChecker::checkUses() {
686
721
return false ;
687
722
}
688
723
}
724
+ auto *phi = dyn_cast<SILPhiArgument>(value);
725
+ if (phi && phi->isPhi () &&
726
+ phi->getOwnershipKind () == OwnershipKind::Guaranteed) {
727
+ if (!hasGuaranteedForwardingIncomingPhiOperandsOnZeroOrAllPaths (phi)) {
728
+ return false ;
729
+ }
730
+ }
689
731
690
732
if (isa<LoadBorrowInst>(value) || isa<BeginBorrowInst>(value)) {
691
733
guaranteedPhiVerifier.verifyGuaranteedForwardingPhis (BorrowedValue (value));
0 commit comments