Skip to content

Commit c026e95

Browse files
committed
[ownership] Extract out SILOwnershipKind from ValueOwnershipKind into its own type and rename Invalid -> Any.
This makes it easier to understand conceptually why a ValueOwnershipKind with Any ownership is invalid and also allowed me to explicitly document the lattice that relates ownership constraints/value ownership kinds.
1 parent 1ff9147 commit c026e95

File tree

81 files changed

+548
-502
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

81 files changed

+548
-502
lines changed

include/swift/SIL/OwnershipUtils.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ class BorrowedValueKind {
253253

254254
public:
255255
static Optional<BorrowedValueKind> get(SILValue value) {
256-
if (value.getOwnershipKind() != ValueOwnershipKind::Guaranteed)
256+
if (value.getOwnershipKind() != OwnershipKind::Guaranteed)
257257
return None;
258258
switch (value->getKind()) {
259259
default:
@@ -571,7 +571,7 @@ class OwnedValueIntroducerKind {
571571

572572
public:
573573
static Optional<OwnedValueIntroducerKind> get(SILValue value) {
574-
if (value.getOwnershipKind() != ValueOwnershipKind::Owned)
574+
if (value.getOwnershipKind() != OwnershipKind::Owned)
575575
return None;
576576

577577
switch (value->getKind()) {

include/swift/SIL/SILBuilder.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -777,7 +777,7 @@ class SILBuilder {
777777

778778
SILValue emitBeginBorrowOperation(SILLocation loc, SILValue v) {
779779
if (!hasOwnership() ||
780-
v.getOwnershipKind().isCompatibleWith(ValueOwnershipKind::Guaranteed))
780+
v.getOwnershipKind().isCompatibleWith(OwnershipKind::Guaranteed))
781781
return v;
782782
return createBeginBorrow(loc, v);
783783
}
@@ -2255,7 +2255,7 @@ class SILBuilder {
22552255
/// lowering for the non-address value.
22562256
void emitDestroyValueOperation(SILLocation Loc, SILValue v) {
22572257
assert(!v->getType().isAddress());
2258-
if (F->hasOwnership() && v.getOwnershipKind() == ValueOwnershipKind::None)
2258+
if (F->hasOwnership() && v.getOwnershipKind() == OwnershipKind::None)
22592259
return;
22602260
auto &lowering = getTypeLowering(v->getType());
22612261
lowering.emitDestroyValue(*this, Loc, v);
@@ -2267,7 +2267,7 @@ class SILBuilder {
22672267
SILLocation Loc, SILValue v,
22682268
Lowering::TypeLowering::TypeExpansionKind expansionKind) {
22692269
assert(!v->getType().isAddress());
2270-
if (F->hasOwnership() && v.getOwnershipKind() == ValueOwnershipKind::None)
2270+
if (F->hasOwnership() && v.getOwnershipKind() == OwnershipKind::None)
22712271
return;
22722272
auto &lowering = getTypeLowering(v->getType());
22732273
lowering.emitLoweredDestroyValue(*this, Loc, v, expansionKind);

include/swift/SIL/SILCloner.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2389,8 +2389,8 @@ void SILCloner<ImplClass>::visitUncheckedOwnershipConversionInst(
23892389

23902390
ValueOwnershipKind Kind = SILValue(Inst).getOwnershipKind();
23912391
if (getOpValue(Inst->getOperand()).getOwnershipKind() ==
2392-
ValueOwnershipKind::None) {
2393-
Kind = ValueOwnershipKind::None;
2392+
OwnershipKind::None) {
2393+
Kind = OwnershipKind::None;
23942394
}
23952395
recordClonedInstruction(Inst, getBuilder().createUncheckedOwnershipConversion(
23962396
getOpLocation(Inst->getLoc()),

include/swift/SIL/SILInstruction.h

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -879,12 +879,15 @@ class OwnershipForwardingSingleValueInst : public SingleValueInstruction {
879879
SILDebugLocation debugLoc, SILType ty,
880880
ValueOwnershipKind ownershipKind)
881881
: SingleValueInstruction(kind, debugLoc, ty),
882-
ownershipKind(ownershipKind) {}
882+
ownershipKind(ownershipKind) {
883+
assert(ownershipKind);
884+
}
883885

884886
public:
885887
ValueOwnershipKind getOwnershipKind() const { return ownershipKind; }
886888
void setOwnershipKind(ValueOwnershipKind newOwnershipKind) {
887889
ownershipKind = newOwnershipKind;
890+
assert(ownershipKind);
888891
}
889892
};
890893

@@ -5229,8 +5232,8 @@ class ObjectInst final : public InstructionBaseWithTrailingOperands<
52295232
unsigned NumBaseElements, bool HasOwnership)
52305233
: InstructionBaseWithTrailingOperands(
52315234
Elements, DebugLoc, Ty,
5232-
HasOwnership ? *mergeSILValueOwnership(Elements)
5233-
: ValueOwnershipKind(ValueOwnershipKind::None)) {
5235+
HasOwnership ? mergeSILValueOwnership(Elements)
5236+
: ValueOwnershipKind(OwnershipKind::None)) {
52345237
SILInstruction::Bits.ObjectInst.NumBaseElements = NumBaseElements;
52355238
}
52365239

@@ -5276,8 +5279,8 @@ class TupleInst final : public InstructionBaseWithTrailingOperands<
52765279
bool HasOwnership)
52775280
: InstructionBaseWithTrailingOperands(
52785281
Elems, DebugLoc, Ty,
5279-
HasOwnership ? *mergeSILValueOwnership(Elems)
5280-
: ValueOwnershipKind(ValueOwnershipKind::None)) {}
5282+
HasOwnership ? mergeSILValueOwnership(Elems)
5283+
: ValueOwnershipKind(OwnershipKind::None)) {}
52815284

52825285
/// Construct a TupleInst.
52835286
static TupleInst *create(SILDebugLocation DebugLoc, SILType Ty,
@@ -5353,7 +5356,7 @@ class EnumInst : public InstructionBase<SILInstructionKind::EnumInst,
53535356
EnumElementDecl *Element, SILType ResultTy)
53545357
: InstructionBase(DebugLoc, ResultTy,
53555358
Operand ? Operand.getOwnershipKind()
5356-
: ValueOwnershipKind(ValueOwnershipKind::None)),
5359+
: ValueOwnershipKind(OwnershipKind::None)),
53575360
Element(Element) {
53585361
if (Operand) {
53595362
OptionalOperand.emplace(this, Operand);
@@ -5645,8 +5648,8 @@ class SelectEnumInst final
56455648
: InstructionBaseWithTrailingOperands(
56465649
Operand, CaseValues, DebugLoc, Type, bool(DefaultValue), CaseCounts,
56475650
DefaultCount,
5648-
HasOwnership ? *mergeSILValueOwnership(CaseValues)
5649-
: ValueOwnershipKind(ValueOwnershipKind::None)) {
5651+
HasOwnership ? mergeSILValueOwnership(CaseValues)
5652+
: ValueOwnershipKind(OwnershipKind::None)) {
56505653
assert(CaseValues.size() - DefaultValue == CaseDecls.size());
56515654
std::uninitialized_copy(CaseDecls.begin(), CaseDecls.end(),
56525655
getTrailingObjects<EnumElementDecl *>());

include/swift/SIL/SILUndef.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class SILUndef : public ValueBase {
3838
static SILUndef *getSentinelValue(SILType type, OwnerTy owner) {
3939
// Ownership kind isn't used here, the value just needs to have a unique
4040
// address.
41-
return new (*owner) SILUndef(type, ValueOwnershipKind::None);
41+
return new (*owner) SILUndef(type, OwnershipKind::None);
4242
}
4343

4444
ValueOwnershipKind getOwnershipKind() const { return ownershipKind; }

include/swift/SIL/SILValue.h

Lines changed: 125 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,45 @@ enum class UseLifetimeConstraint {
8888
llvm::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

include/swift/SIL/ValueUtils.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ namespace swift {
2222
///
2323
/// NOTE: This assumes that the passed in SILValues are not values used as type
2424
/// dependent operands.
25-
Optional<ValueOwnershipKind> mergeSILValueOwnership(ArrayRef<SILValue> values);
25+
ValueOwnershipKind mergeSILValueOwnership(ArrayRef<SILValue> values);
2626

2727
} // namespace swift
2828

0 commit comments

Comments
 (0)