@@ -88,13 +88,45 @@ enum class UseLifetimeConstraint {
8888llvm::raw_ostream &operator <<(llvm::raw_ostream &os,
8989 UseLifetimeConstraint constraint);
9090
91- // / A value representing the specific ownership semantics that a SILValue may
92- // / have.
93- struct ValueOwnershipKind {
91+ // / A lattice that we use to classify ownership at the SIL level. None is top
92+ // / and Any is bottom and all of the other ownership kinds are mid level nodes
93+ // / in the lattice. Graphically the lattice looks as follows:
94+ // / +----+
95+ // / +-------|None|---------+
96+ // / | +----+ |
97+ // / | | |
98+ // / v v v
99+ // / +-------+ +-----+ +----------+
100+ // / |Unowned| |Owned| |Guaranteed|
101+ // / +-------+ +-----+ +----------+
102+ // / | | |
103+ // / | v |
104+ // / | +---+ |
105+ // / +------->|Any|<--------+
106+ // / +---+
107+ // /
108+ // / One moves up the lattice by performing a join operation and one moves down
109+ // / the lattice by performing a meet operation.
110+ // /
111+ // / This type is used in two different composition types:
112+ // /
113+ // / * ValueOwnershipKind: This represents the ownership kind that a value can
114+ // / take. Since our ownership system is strict, we require that all values
115+ // / have a non-Any ownership since Any represents a type of ownership unknown
116+ // / statically. Thus we treat Any as representing an invalid
117+ // / value. ValueOwnershipKinds can only perform a meet operation to determine
118+ // / if two ownership kinds are compatible with a merge of Any showing the
119+ // / merge is impossible since values can not have any ownership.
120+ // /
121+ // / * OperandConstraint: This represents a constraint on the values that can be
122+ // / used by a specific operand. Here Any is valid.
123+ struct OwnershipKind {
94124 enum innerty : uint8_t {
95- // / A value used to signal that two merged ValueOwnershipKinds were
96- // / incompatible.
97- Invalid = 0 ,
125+ // / An ownership kind that models an ownership that is unknown statically at
126+ // / compile time. It is invalid when applied to values because we have
127+ // / strict ownership rules for values. But it is an expected/normal state
128+ // / when constraining ownership kinds.
129+ Any = 0 ,
98130
99131 // / A SILValue with `Unowned` ownership kind is an independent value that
100132 // / has a lifetime that is only guaranteed to last until the next program
@@ -134,58 +166,116 @@ struct ValueOwnershipKind {
134166 None,
135167
136168 LastValueOwnershipKind = None,
137- } Value ;
169+ } value ;
138170
139171 using UnderlyingType = std::underlying_type<innerty>::type;
140172 static constexpr unsigned NumBits = SILNode::NumVOKindBits;
141173 static constexpr UnderlyingType MaxValue = (UnderlyingType(1 ) << NumBits);
142174 static constexpr uint64_t Mask = MaxValue - 1 ;
143- static_assert (unsigned (ValueOwnershipKind ::LastValueOwnershipKind) < MaxValue,
175+ static_assert (unsigned (OwnershipKind ::LastValueOwnershipKind) < MaxValue,
144176 " LastValueOwnershipKind is larger than max representable "
145177 " ownership value?!" );
146178
147- ValueOwnershipKind (innerty NewValue) : Value(NewValue) {}
148- explicit ValueOwnershipKind (unsigned NewValue) : Value(innerty(NewValue)) {}
149- ValueOwnershipKind (const SILFunction &F, SILType Type,
150- SILArgumentConvention Convention);
179+ OwnershipKind (OwnershipKind::innerty other) : value(other) {}
180+ OwnershipKind (const OwnershipKind &other) : value(other.value) {}
181+
182+ OwnershipKind &operator =(const OwnershipKind &other) {
183+ value = other.value ;
184+ return *this ;
185+ }
186+
187+ OwnershipKind &operator =(OwnershipKind::innerty other) {
188+ value = other;
189+ return *this ;
190+ }
191+
192+ operator OwnershipKind::innerty () const { return value; }
193+
194+ // / Move down the lattice.
195+ OwnershipKind meet (OwnershipKind other) const {
196+ // None merges with anything.
197+ if (*this == OwnershipKind::None)
198+ return other;
199+ if (other == OwnershipKind::None)
200+ return *this ;
201+
202+ // At this point, if the two ownership kinds don't line up, the merge
203+ // fails. Return any to show that we have lost information and now have a
204+ // value kind that is invalid on values.
205+ if (*this != other)
206+ return OwnershipKind::Any;
207+
208+ // Otherwise, we are good, return *this.
209+ return *this ;
210+ }
211+
212+ // / Move up the lattice.
213+ OwnershipKind join (OwnershipKind other) const {
214+ if (*this == OwnershipKind::Any)
215+ return other;
216+ if (other == OwnershipKind::Any)
217+ return *this ;
218+ if (*this != other)
219+ return OwnershipKind::None;
220+ return *this ;
221+ }
222+ };
223+
224+ // / A value representing the specific ownership semantics that a SILValue may
225+ // / have.
226+ struct ValueOwnershipKind {
227+ using innerty = OwnershipKind::innerty;
228+
229+ OwnershipKind value;
230+
231+ ValueOwnershipKind (innerty newValue) : value(newValue) {}
232+ ValueOwnershipKind (OwnershipKind newValue) : value(newValue) {}
233+ explicit ValueOwnershipKind (unsigned newValue) : value(innerty(newValue)) {}
234+ ValueOwnershipKind (const SILFunction &f, SILType type,
235+ SILArgumentConvention convention);
151236
152237 // / Parse Value into a ValueOwnershipKind.
153238 // /
154239 // / *NOTE* Emits an unreachable if an invalid value is passed in.
155- explicit ValueOwnershipKind (StringRef Value);
240+ explicit ValueOwnershipKind (StringRef value);
241+
242+ operator OwnershipKind () const { return value; }
243+ explicit operator unsigned () const { return value; }
244+ operator innerty () const { return value; }
156245
157- operator innerty () const { return Value ; }
246+ explicit operator bool () const { return value != OwnershipKind::Any ; }
158247
159- bool operator ==(const swift:: ValueOwnershipKind::innerty& b) {
160- return Value == b ;
248+ bool operator ==(ValueOwnershipKind other) const {
249+ return value == other. value ;
161250 }
162251
163- // / Returns true if this ValueOwnershipKind is not invalid.
164- explicit operator bool () const { return Value != Invalid; }
252+ bool operator ==(innerty other) const { return value == other; }
165253
166- ValueOwnershipKind merge (ValueOwnershipKind RHS) const ;
254+ // / We merge by moving down the lattice.
255+ ValueOwnershipKind merge (ValueOwnershipKind rhs) const {
256+ return value.meet (rhs.value );
257+ }
167258
168259 // / Given that there is an aggregate value (like a struct or enum) with this
169260 // / ownership kind, and a subobject of type Proj is being projected from the
170261 // / aggregate, return Trivial if Proj has trivial type and the aggregate's
171262 // / ownership kind otherwise.
172- ValueOwnershipKind getProjectedOwnershipKind (const SILFunction &F ,
173- SILType Proj ) const ;
263+ ValueOwnershipKind getProjectedOwnershipKind (const SILFunction &func ,
264+ SILType projType ) const ;
174265
175266 // / Return the lifetime constraint semantics for this
176267 // / ValueOwnershipKind when forwarding ownership.
177268 // /
178269 // / This is MustBeInvalidated for Owned and MustBeLive for all other ownership
179270 // / kinds.
180271 UseLifetimeConstraint getForwardingLifetimeConstraint () const {
181- switch (Value) {
182- case ValueOwnershipKind::Invalid:
183- llvm_unreachable (" Invalid ownership doesnt have a lifetime constraint!" );
184- case ValueOwnershipKind::None:
185- case ValueOwnershipKind::Guaranteed:
186- case ValueOwnershipKind::Unowned:
272+ switch (value) {
273+ case OwnershipKind::Any:
274+ case OwnershipKind::None:
275+ case OwnershipKind::Guaranteed:
276+ case OwnershipKind::Unowned:
187277 return UseLifetimeConstraint::NonLifetimeEnding;
188- case ValueOwnershipKind ::Owned:
278+ case OwnershipKind ::Owned:
189279 return UseLifetimeConstraint::LifetimeEnding;
190280 }
191281 llvm_unreachable (" covered switch" );
@@ -195,7 +285,7 @@ struct ValueOwnershipKind {
195285 // / that the two ownership kinds are "compatibile".
196286 // /
197287 // / The reason why we do not compare directy is to allow for
198- // / ValueOwnershipKind ::None to merge into other forms of ValueOwnershipKind.
288+ // / OwnershipKind ::None to merge into other forms of ValueOwnershipKind.
199289 bool isCompatibleWith (ValueOwnershipKind other) const {
200290 return bool (merge (other));
201291 }
@@ -207,7 +297,7 @@ struct ValueOwnershipKind {
207297 bool isCompatibleWith (SILValue other) const ;
208298
209299 template <typename RangeTy> static ValueOwnershipKind merge (RangeTy &&r) {
210- auto initial = ValueOwnershipKind ::None;
300+ auto initial = OwnershipKind ::None;
211301 return accumulate (std::forward<RangeTy>(r), initial,
212302 [](ValueOwnershipKind acc, ValueOwnershipKind x) {
213303 if (!acc)
@@ -495,7 +585,7 @@ struct OperandOwnershipKindMap {
495585 // should always have a small case SmallBitVector, so there is no
496586 // difference in size.
497587 static constexpr unsigned NUM_DATA_BITS =
498- 2 * (unsigned (ValueOwnershipKind ::LastValueOwnershipKind) + 1 );
588+ 2 * (unsigned (OwnershipKind ::LastValueOwnershipKind) + 1 );
499589
500590 // / A bit vector representing our "map". Given a ValueOwnershipKind k, if the
501591 // / operand can accept k, the unsigned(k)*2 bit will be set to true. Assuming
@@ -512,7 +602,7 @@ struct OperandOwnershipKindMap {
512602
513603 // / Return the OperandOwnershipKindMap that tests for compatibility with
514604 // / ValueOwnershipKind kind. This means that it will accept a element whose
515- // / ownership is ValueOwnershipKind ::None.
605+ // / ownership is OwnershipKind ::None.
516606 static OperandOwnershipKindMap
517607 compatibilityMap (ValueOwnershipKind kind, UseLifetimeConstraint constraint) {
518608 OperandOwnershipKindMap set;
@@ -526,7 +616,7 @@ struct OperandOwnershipKindMap {
526616 compatibleWithAllExcept (ValueOwnershipKind kind) {
527617 OperandOwnershipKindMap map;
528618 unsigned index = 0 ;
529- unsigned end = unsigned (ValueOwnershipKind ::LastValueOwnershipKind) + 1 ;
619+ unsigned end = unsigned (OwnershipKind ::LastValueOwnershipKind) + 1 ;
530620 for (; index != end; ++index) {
531621 if (ValueOwnershipKind (index) == kind) {
532622 continue ;
@@ -555,7 +645,7 @@ struct OperandOwnershipKindMap {
555645 static OperandOwnershipKindMap allLive () {
556646 OperandOwnershipKindMap map;
557647 unsigned index = 0 ;
558- unsigned end = unsigned (ValueOwnershipKind ::LastValueOwnershipKind) + 1 ;
648+ unsigned end = unsigned (OwnershipKind ::LastValueOwnershipKind) + 1 ;
559649 while (index != end) {
560650 map.add (ValueOwnershipKind (index),
561651 UseLifetimeConstraint::NonLifetimeEnding);
@@ -584,7 +674,7 @@ struct OperandOwnershipKindMap {
584674
585675 void addCompatibilityConstraint (ValueOwnershipKind kind,
586676 UseLifetimeConstraint constraint) {
587- add (ValueOwnershipKind ::None, UseLifetimeConstraint::NonLifetimeEnding);
677+ add (OwnershipKind ::None, UseLifetimeConstraint::NonLifetimeEnding);
588678 add (kind, constraint);
589679 }
590680
0 commit comments