@@ -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,38 @@ 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 operands not found on all paths!\n " ;
657
+ });
658
+ }
659
+
626
660
bool SILValueOwnershipChecker::checkUses () {
627
661
LLVM_DEBUG (llvm::dbgs () << " Gathering and classifying uses!\n " );
628
662
@@ -685,6 +719,13 @@ bool SILValueOwnershipChecker::checkUses() {
685
719
return false ;
686
720
}
687
721
}
722
+ auto *phi = dyn_cast<SILPhiArgument>(value);
723
+ if (phi && phi->isPhi () &&
724
+ phi->getOwnershipKind () == OwnershipKind::Guaranteed) {
725
+ if (!hasGuaranteedForwardingIncomingPhiOperandsOnZeroOrAllPaths (phi)) {
726
+ return false ;
727
+ }
728
+ }
688
729
689
730
if (isa<LoadBorrowInst>(value) || isa<BeginBorrowInst>(value)) {
690
731
guaranteedPhiVerifier.verifyGuaranteedForwardingPhis (BorrowedValue (value));
0 commit comments