@@ -219,8 +219,13 @@ struct OwnershipKind {
219
219
return OwnershipKind::None;
220
220
return *this ;
221
221
}
222
+
223
+ // / Convert this ownership kind to a StringRef.
224
+ StringRef asString () const ;
222
225
};
223
226
227
+ llvm::raw_ostream &operator <<(llvm::raw_ostream &os, const OwnershipKind &kind);
228
+
224
229
// / A value representing the specific ownership semantics that a SILValue may
225
230
// / have.
226
231
struct ValueOwnershipKind {
@@ -566,150 +571,50 @@ inline bool ValueOwnershipKind::isCompatibleWith(SILValue other) const {
566
571
return isCompatibleWith (other.getOwnershipKind ());
567
572
}
568
573
569
- // / A map from a ValueOwnershipKind that an operand can accept to a
570
- // / UseLifetimeConstraint that describes the effect that the operand's use has
571
- // / on the underlying value. If a ValueOwnershipKind is not in this map then
572
- // / matching an operand with the value results in an ill formed program.
573
- // /
574
- // / So for instance, a map could specify that if a value is used as an owned
575
- // / parameter, then the use implies that the original value is destroyed at that
576
- // / point. In contrast, if the value is used as a guaranteed parameter, then the
577
- // / liveness constraint just requires that the value remains alive at the use
578
- // / point.
579
- struct OperandOwnershipKindMap {
580
- // One bit for if a value exists and if the value exists, what the
581
- // ownership constraint is. These are stored as pairs.
582
- //
583
- // NOTE: We are burning 1 bit per unset value. But this is without
584
- // matter since we are always going to need less bits than 64, so we
585
- // should always have a small case SmallBitVector, so there is no
586
- // difference in size.
587
- static constexpr unsigned NUM_DATA_BITS =
588
- 2 * (unsigned (OwnershipKind::LastValueOwnershipKind) + 1 );
589
-
590
- // / A bit vector representing our "map". Given a ValueOwnershipKind k, if the
591
- // / operand can accept k, the unsigned(k)*2 bit will be set to true. Assuming
592
- // / that bit is set, the unsigned(k)*2+1 bit is set to the use lifetime
593
- // / constraint provided by the value.
594
- SmallBitVector data;
595
-
596
- OperandOwnershipKindMap () : data(NUM_DATA_BITS) {}
597
- OperandOwnershipKindMap (ValueOwnershipKind kind,
598
- UseLifetimeConstraint constraint)
599
- : data(NUM_DATA_BITS) {
600
- add (kind, constraint);
601
- }
574
+ class OwnershipConstraint {
575
+ OwnershipKind ownershipKind;
576
+ UseLifetimeConstraint lifetimeConstraint;
602
577
603
- // / Return the OperandOwnershipKindMap that tests for compatibility with
604
- // / ValueOwnershipKind kind. This means that it will accept a element whose
605
- // / ownership is OwnershipKind::None.
606
- static OperandOwnershipKindMap
607
- compatibilityMap (ValueOwnershipKind kind, UseLifetimeConstraint constraint ) {
608
- OperandOwnershipKindMap set;
609
- set. addCompatibilityConstraint (kind, constraint);
610
- return set ;
578
+ public:
579
+ OwnershipConstraint (OwnershipKind inputOwnershipKind,
580
+ UseLifetimeConstraint inputLifetimeConstraint)
581
+ : ownershipKind(inputOwnershipKind),
582
+ lifetimeConstraint (inputLifetimeConstraint ) {
583
+ assert ((ownershipKind != OwnershipKind::None ||
584
+ lifetimeConstraint == UseLifetimeConstraint::NonLifetimeEnding) &&
585
+ " ValueOwnershipKind::None can never have their lifetime ended " ) ;
611
586
}
612
587
613
- // / Return a map that is compatible with any and all ValueOwnershipKinds
614
- // / except for \p kind.
615
- static OperandOwnershipKindMap
616
- compatibleWithAllExcept (ValueOwnershipKind kind) {
617
- OperandOwnershipKindMap map;
618
- unsigned index = 0 ;
619
- unsigned end = unsigned (OwnershipKind::LastValueOwnershipKind) + 1 ;
620
- for (; index != end; ++index) {
621
- if (ValueOwnershipKind (index) == kind) {
622
- continue ;
623
- }
624
- map.add (ValueOwnershipKind (index),
625
- UseLifetimeConstraint::NonLifetimeEnding);
626
- }
627
- return map;
588
+ OwnershipKind getPreferredKind () const {
589
+ return ownershipKind;
628
590
}
629
591
630
- // / Create a map that has compatibility constraints for each of the
631
- // / ValueOwnershipKind, UseLifetimeConstraints in \p args.
632
- static OperandOwnershipKindMap
633
- compatibilityMap (std::initializer_list<
634
- std::pair<ValueOwnershipKind, UseLifetimeConstraint>>
635
- args) {
636
- OperandOwnershipKindMap map;
637
- for (auto &p : args) {
638
- map.addCompatibilityConstraint (p.first , p.second );
639
- }
640
- return map;
592
+ bool isLifetimeEnding () const {
593
+ return lifetimeConstraint == UseLifetimeConstraint::LifetimeEnding;
641
594
}
642
595
643
- // / Return a map that states that an operand can take any ownership with each
644
- // / ownership having a must be live constraint.
645
- static OperandOwnershipKindMap allLive () {
646
- OperandOwnershipKindMap map;
647
- unsigned index = 0 ;
648
- unsigned end = unsigned (OwnershipKind::LastValueOwnershipKind) + 1 ;
649
- while (index != end) {
650
- map.add (ValueOwnershipKind (index),
651
- UseLifetimeConstraint::NonLifetimeEnding);
652
- ++index;
653
- }
654
- return map;
596
+ UseLifetimeConstraint getLifetimeConstraint () const {
597
+ return lifetimeConstraint;
655
598
}
656
599
657
- // / Specify that the operand associated with this set can accept a value with
658
- // / ValueOwnershipKind \p kind. The value provided by the operand will have a
659
- // / new ownership enforced constraint defined by \p constraint.
660
- void add (ValueOwnershipKind kind, UseLifetimeConstraint constraint) {
661
- unsigned index = unsigned (kind);
662
- unsigned kindOffset = index * 2 ;
663
- unsigned constraintOffset = index * 2 + 1 ;
664
-
665
- // If we have already put this kind into the map, we require the constraint
666
- // offset to be the same, i.e. we only allow for a kind to be added twice if
667
- // the constraint is idempotent. We assert otherwise.
668
- assert ((!data[kindOffset] || UseLifetimeConstraint (bool (
669
- data[constraintOffset])) == constraint) &&
670
- " Adding kind twice to the map with different constraints?!" );
671
- data[kindOffset] = true ;
672
- data[constraintOffset] = bool (constraint);
600
+ static OwnershipConstraint anyValueAcceptingConstraint () {
601
+ return {OwnershipKind::Any, UseLifetimeConstraint::NonLifetimeEnding};
673
602
}
674
603
675
- void addCompatibilityConstraint (ValueOwnershipKind kind,
676
- UseLifetimeConstraint constraint) {
677
- add (OwnershipKind::None, UseLifetimeConstraint::NonLifetimeEnding);
678
- add (kind, constraint);
679
- }
604
+ bool satisfiedBy (const Operand *use) const ;
680
605
681
- bool canAcceptKind (ValueOwnershipKind kind) const {
682
- unsigned index = unsigned (kind);
683
- unsigned kindOffset = index * 2 ;
684
- return data[kindOffset];
606
+ bool satisfiesConstraint (ValueOwnershipKind testKind) const {
607
+ return ownershipKind.join (testKind) == testKind;
685
608
}
686
609
687
- UseLifetimeConstraint getLifetimeConstraint (ValueOwnershipKind kind ) const ;
688
-
689
- void print (llvm::raw_ostream &os) const ;
690
- SWIFT_DEBUG_DUMP;
610
+ bool operator ==( const OwnershipConstraint &other ) const {
611
+ return ownershipKind == other. ownershipKind &&
612
+ isLifetimeEnding () == other. isLifetimeEnding () ;
613
+ }
691
614
};
692
615
693
- inline llvm::raw_ostream &operator <<(llvm::raw_ostream &os,
694
- OperandOwnershipKindMap map) {
695
- map.print (os);
696
- return os;
697
- }
698
-
699
- // Out of line to work around lack of forward declaration for operator <<.
700
- inline UseLifetimeConstraint
701
- OperandOwnershipKindMap::getLifetimeConstraint (ValueOwnershipKind kind) const {
702
- #ifndef NDEBUG
703
- if (!canAcceptKind (kind)) {
704
- llvm::errs () << " Can not lookup lifetime constraint: " << kind
705
- << " . Not in map!\n "
706
- << *this ;
707
- llvm_unreachable (" standard error assertion" );
708
- }
709
- #endif
710
- unsigned constraintOffset = unsigned (kind) * 2 + 1 ;
711
- return UseLifetimeConstraint (data[constraintOffset]);
712
- }
616
+ llvm::raw_ostream &operator <<(llvm::raw_ostream &os,
617
+ OwnershipConstraint constraint);
713
618
714
619
// / A formal SIL reference to a value, suitable for use as a stored
715
620
// / operand.
@@ -788,24 +693,25 @@ class Operand {
788
693
// / Return which operand this is in the operand list of the using instruction.
789
694
unsigned getOperandNumber () const ;
790
695
791
- // / Return the static map of ValueOwnershipKinds that this operand can
792
- // / potentially have to the UseLifetimeConstraint associated with that
793
- // / ownership kind
696
+ // / Return the ownership constraint that restricts what types of values this
697
+ // / Operand can contain. Returns none if the operand is a type dependent
698
+ // / operand.
794
699
// /
795
700
// / NOTE: This is implemented in OperandOwnership.cpp.
796
- OperandOwnershipKindMap getOwnershipKindMap () const ;
701
+ Optional<OwnershipConstraint> getOwnershipConstraint () const ;
702
+
703
+ // / Returns true if changing the operand to use a value with the given
704
+ // / ownership kind would not cause the operand to violate the operand's
705
+ // / ownership constraints. Returns false otherwise.
706
+ bool canAcceptKind (ValueOwnershipKind kind) const ;
707
+
708
+ // / Returns true if this operand and its value satisfy the operand's
709
+ // / operand constraint.
710
+ bool satisfiesConstraints () const ;
797
711
798
712
// / Returns true if this operand acts as a use that consumes its associated
799
713
// / value.
800
- bool isLifetimeEnding () const {
801
- // Type dependent uses can never be consuming and do not have valid
802
- // ownership maps since they do not participate in the ownership system.
803
- if (isTypeDependent ())
804
- return false ;
805
- auto map = getOwnershipKindMap ();
806
- auto constraint = map.getLifetimeConstraint (get ().getOwnershipKind ());
807
- return constraint == UseLifetimeConstraint::LifetimeEnding;
808
- }
714
+ bool isLifetimeEnding () const ;
809
715
810
716
SILBasicBlock *getParentBlock () const ;
811
717
SILFunction *getParentFunction () const ;
0 commit comments