@@ -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
@@ -615,6 +617,38 @@ bool SILValueOwnershipChecker::isSubobjectProjectionWithLifetimeEndingUses(
615
617
});
616
618
}
617
619
620
+ bool SILValueOwnershipChecker::
621
+ hasGuaranteedForwardingIncomingPhiOperandsOnZeroOrAllPaths (
622
+ SILPhiArgument *phi) const {
623
+ bool foundGuaranteedForwardingPhiOperand = false ;
624
+ bool foundNonGuaranteedForwardingPhiOperand = false ;
625
+ phi->visitTransitiveIncomingPhiOperands ([&](auto *, auto *operand) -> bool {
626
+ auto value = operand->get ();
627
+ if (canOpcodeForwardInnerGuaranteedValues (value) ||
628
+ isa<SILFunctionArgument>(value)) {
629
+ foundGuaranteedForwardingPhiOperand = true ;
630
+ if (foundNonGuaranteedForwardingPhiOperand) {
631
+ return false ; /* found error, stop visiting */
632
+ }
633
+ return true ;
634
+ }
635
+ foundNonGuaranteedForwardingPhiOperand = true ;
636
+ if (foundGuaranteedForwardingPhiOperand) {
637
+ return false ; /* found error, stop visiting */
638
+ }
639
+ return true ;
640
+ });
641
+ if (foundGuaranteedForwardingPhiOperand ^
642
+ foundNonGuaranteedForwardingPhiOperand) {
643
+ return true ;
644
+ }
645
+ return errorBuilder.handleMalformedSIL ([&] {
646
+ llvm::errs () << " Malformed @guaranteed phi!\n "
647
+ << " Phi: " << *phi;
648
+ llvm::errs () << " Guaranteed forwarding operands not found on all paths!\n " ;
649
+ });
650
+ }
651
+
618
652
bool SILValueOwnershipChecker::checkUses () {
619
653
LLVM_DEBUG (llvm::dbgs () << " Gathering and classifying uses!\n " );
620
654
@@ -677,6 +711,13 @@ bool SILValueOwnershipChecker::checkUses() {
677
711
return false ;
678
712
}
679
713
}
714
+ auto *phi = dyn_cast<SILPhiArgument>(value);
715
+ if (phi && phi->isPhi () &&
716
+ phi->getOwnershipKind () == OwnershipKind::Guaranteed) {
717
+ if (!hasGuaranteedForwardingIncomingPhiOperandsOnZeroOrAllPaths (phi)) {
718
+ return false ;
719
+ }
720
+ }
680
721
681
722
if (isa<LoadBorrowInst>(value) || isa<BeginBorrowInst>(value)) {
682
723
guaranteedPhiVerifier.verifyGuaranteedForwardingPhis (BorrowedValue (value));
0 commit comments