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