@@ -88,13 +88,45 @@ enum class UseLifetimeConstraint {
88
88
llvm::raw_ostream &operator <<(llvm::raw_ostream &os,
89
89
UseLifetimeConstraint constraint);
90
90
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 {
94
124
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 ,
98
130
99
131
// / A SILValue with `Unowned` ownership kind is an independent value that
100
132
// / has a lifetime that is only guaranteed to last until the next program
@@ -134,58 +166,116 @@ struct ValueOwnershipKind {
134
166
None,
135
167
136
168
LastValueOwnershipKind = None,
137
- } Value ;
169
+ } value ;
138
170
139
171
using UnderlyingType = std::underlying_type<innerty>::type;
140
172
static constexpr unsigned NumBits = SILNode::NumVOKindBits;
141
173
static constexpr UnderlyingType MaxValue = (UnderlyingType(1 ) << NumBits);
142
174
static constexpr uint64_t Mask = MaxValue - 1 ;
143
- static_assert (unsigned (ValueOwnershipKind ::LastValueOwnershipKind) < MaxValue,
175
+ static_assert (unsigned (OwnershipKind ::LastValueOwnershipKind) < MaxValue,
144
176
" LastValueOwnershipKind is larger than max representable "
145
177
" ownership value?!" );
146
178
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);
151
236
152
237
// / Parse Value into a ValueOwnershipKind.
153
238
// /
154
239
// / *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; }
156
245
157
- operator innerty () const { return Value ; }
246
+ explicit operator bool () const { return value != OwnershipKind::Any ; }
158
247
159
- bool operator ==(const swift:: ValueOwnershipKind::innerty& b) {
160
- return Value == b ;
248
+ bool operator ==(ValueOwnershipKind other) const {
249
+ return value == other. value ;
161
250
}
162
251
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; }
165
253
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
+ }
167
258
168
259
// / Given that there is an aggregate value (like a struct or enum) with this
169
260
// / ownership kind, and a subobject of type Proj is being projected from the
170
261
// / aggregate, return Trivial if Proj has trivial type and the aggregate's
171
262
// / ownership kind otherwise.
172
- ValueOwnershipKind getProjectedOwnershipKind (const SILFunction &F ,
173
- SILType Proj ) const ;
263
+ ValueOwnershipKind getProjectedOwnershipKind (const SILFunction &func ,
264
+ SILType projType ) const ;
174
265
175
266
// / Return the lifetime constraint semantics for this
176
267
// / ValueOwnershipKind when forwarding ownership.
177
268
// /
178
269
// / This is MustBeInvalidated for Owned and MustBeLive for all other ownership
179
270
// / kinds.
180
271
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:
187
277
return UseLifetimeConstraint::NonLifetimeEnding;
188
- case ValueOwnershipKind ::Owned:
278
+ case OwnershipKind ::Owned:
189
279
return UseLifetimeConstraint::LifetimeEnding;
190
280
}
191
281
llvm_unreachable (" covered switch" );
@@ -195,7 +285,7 @@ struct ValueOwnershipKind {
195
285
// / that the two ownership kinds are "compatibile".
196
286
// /
197
287
// / 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.
199
289
bool isCompatibleWith (ValueOwnershipKind other) const {
200
290
return bool (merge (other));
201
291
}
@@ -207,7 +297,7 @@ struct ValueOwnershipKind {
207
297
bool isCompatibleWith (SILValue other) const ;
208
298
209
299
template <typename RangeTy> static ValueOwnershipKind merge (RangeTy &&r) {
210
- auto initial = ValueOwnershipKind ::None;
300
+ auto initial = OwnershipKind ::None;
211
301
return accumulate (std::forward<RangeTy>(r), initial,
212
302
[](ValueOwnershipKind acc, ValueOwnershipKind x) {
213
303
if (!acc)
@@ -495,7 +585,7 @@ struct OperandOwnershipKindMap {
495
585
// should always have a small case SmallBitVector, so there is no
496
586
// difference in size.
497
587
static constexpr unsigned NUM_DATA_BITS =
498
- 2 * (unsigned (ValueOwnershipKind ::LastValueOwnershipKind) + 1 );
588
+ 2 * (unsigned (OwnershipKind ::LastValueOwnershipKind) + 1 );
499
589
500
590
// / A bit vector representing our "map". Given a ValueOwnershipKind k, if the
501
591
// / operand can accept k, the unsigned(k)*2 bit will be set to true. Assuming
@@ -512,7 +602,7 @@ struct OperandOwnershipKindMap {
512
602
513
603
// / Return the OperandOwnershipKindMap that tests for compatibility with
514
604
// / ValueOwnershipKind kind. This means that it will accept a element whose
515
- // / ownership is ValueOwnershipKind ::None.
605
+ // / ownership is OwnershipKind ::None.
516
606
static OperandOwnershipKindMap
517
607
compatibilityMap (ValueOwnershipKind kind, UseLifetimeConstraint constraint) {
518
608
OperandOwnershipKindMap set;
@@ -526,7 +616,7 @@ struct OperandOwnershipKindMap {
526
616
compatibleWithAllExcept (ValueOwnershipKind kind) {
527
617
OperandOwnershipKindMap map;
528
618
unsigned index = 0 ;
529
- unsigned end = unsigned (ValueOwnershipKind ::LastValueOwnershipKind) + 1 ;
619
+ unsigned end = unsigned (OwnershipKind ::LastValueOwnershipKind) + 1 ;
530
620
for (; index != end; ++index) {
531
621
if (ValueOwnershipKind (index) == kind) {
532
622
continue ;
@@ -555,7 +645,7 @@ struct OperandOwnershipKindMap {
555
645
static OperandOwnershipKindMap allLive () {
556
646
OperandOwnershipKindMap map;
557
647
unsigned index = 0 ;
558
- unsigned end = unsigned (ValueOwnershipKind ::LastValueOwnershipKind) + 1 ;
648
+ unsigned end = unsigned (OwnershipKind ::LastValueOwnershipKind) + 1 ;
559
649
while (index != end) {
560
650
map.add (ValueOwnershipKind (index),
561
651
UseLifetimeConstraint::NonLifetimeEnding);
@@ -584,7 +674,7 @@ struct OperandOwnershipKindMap {
584
674
585
675
void addCompatibilityConstraint (ValueOwnershipKind kind,
586
676
UseLifetimeConstraint constraint) {
587
- add (ValueOwnershipKind ::None, UseLifetimeConstraint::NonLifetimeEnding);
677
+ add (OwnershipKind ::None, UseLifetimeConstraint::NonLifetimeEnding);
588
678
add (kind, constraint);
589
679
}
590
680
0 commit comments