Skip to content

Commit 1ff9147

Browse files
authored
Merge pull request swiftlang#34659 from gottesmm/pr-5755ffcaf1433708dd6843521b63d70405f75d65
[ownership] Convert ValueOwnershipKind to have an Invalid state instead of using optional.
2 parents 9d4341e + f16c4ba commit 1ff9147

File tree

8 files changed

+60
-32
lines changed

8 files changed

+60
-32
lines changed

include/swift/SIL/SILValue.h

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,10 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
9292
/// have.
9393
struct ValueOwnershipKind {
9494
enum innerty : uint8_t {
95+
/// A value used to signal that two merged ValueOwnershipKinds were
96+
/// incompatible.
97+
Invalid = 0,
98+
9599
/// A SILValue with `Unowned` ownership kind is an independent value that
96100
/// has a lifetime that is only guaranteed to last until the next program
97101
/// visible side-effect. To maintain the lifetime of an unowned value, it
@@ -156,7 +160,10 @@ struct ValueOwnershipKind {
156160
return Value == b;
157161
}
158162

159-
Optional<ValueOwnershipKind> merge(ValueOwnershipKind RHS) const;
163+
/// Returns true if this ValueOwnershipKind is not invalid.
164+
explicit operator bool() const { return Value != Invalid; }
165+
166+
ValueOwnershipKind merge(ValueOwnershipKind RHS) const;
160167

161168
/// Given that there is an aggregate value (like a struct or enum) with this
162169
/// ownership kind, and a subobject of type Proj is being projected from the
@@ -172,6 +179,8 @@ struct ValueOwnershipKind {
172179
/// kinds.
173180
UseLifetimeConstraint getForwardingLifetimeConstraint() const {
174181
switch (Value) {
182+
case ValueOwnershipKind::Invalid:
183+
llvm_unreachable("Invalid ownership doesnt have a lifetime constraint!");
175184
case ValueOwnershipKind::None:
176185
case ValueOwnershipKind::Guaranteed:
177186
case ValueOwnershipKind::Unowned:
@@ -188,7 +197,7 @@ struct ValueOwnershipKind {
188197
/// The reason why we do not compare directy is to allow for
189198
/// ValueOwnershipKind::None to merge into other forms of ValueOwnershipKind.
190199
bool isCompatibleWith(ValueOwnershipKind other) const {
191-
return merge(other).hasValue();
200+
return bool(merge(other));
192201
}
193202

194203
/// Returns isCompatibleWith(other.getOwnershipKind()).
@@ -197,16 +206,14 @@ struct ValueOwnershipKind {
197206
/// dependencies.
198207
bool isCompatibleWith(SILValue other) const;
199208

200-
template <typename RangeTy>
201-
static Optional<ValueOwnershipKind> merge(RangeTy &&r) {
202-
auto initial = Optional<ValueOwnershipKind>(ValueOwnershipKind::None);
203-
return accumulate(
204-
std::forward<RangeTy>(r), initial,
205-
[](Optional<ValueOwnershipKind> acc, ValueOwnershipKind x) {
206-
if (!acc)
207-
return acc;
208-
return acc.getValue().merge(x);
209-
});
209+
template <typename RangeTy> static ValueOwnershipKind merge(RangeTy &&r) {
210+
auto initial = ValueOwnershipKind::None;
211+
return accumulate(std::forward<RangeTy>(r), initial,
212+
[](ValueOwnershipKind acc, ValueOwnershipKind x) {
213+
if (!acc)
214+
return acc;
215+
return acc.merge(x);
216+
});
210217
}
211218

212219
StringRef asString() const;

lib/SIL/IR/SILInstructions.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2886,5 +2886,8 @@ ReturnInst::ReturnInst(SILFunction &func, SILDebugLocation debugLoc,
28862886
});
28872887

28882888
// Then merge all of our ownership kinds. Assert if we fail to merge.
2889-
ownershipKind = *ValueOwnershipKind::merge(ownershipKindRange);
2889+
ownershipKind = ValueOwnershipKind::merge(ownershipKindRange);
2890+
assert(ownershipKind != ValueOwnershipKind::Invalid &&
2891+
"Conflicting ownership kinds when creating term inst from function "
2892+
"result info?!");
28902893
}

lib/SIL/IR/SILValue.cpp

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,8 @@ ValueOwnershipKind::ValueOwnershipKind(const SILFunction &F, SILType Type,
198198

199199
StringRef ValueOwnershipKind::asString() const {
200200
switch (Value) {
201+
case ValueOwnershipKind::Invalid:
202+
return "invalid";
201203
case ValueOwnershipKind::Unowned:
202204
return "unowned";
203205
case ValueOwnershipKind::Owned:
@@ -215,21 +217,27 @@ llvm::raw_ostream &swift::operator<<(llvm::raw_ostream &os,
215217
return os << kind.asString();
216218
}
217219

218-
Optional<ValueOwnershipKind>
219-
ValueOwnershipKind::merge(ValueOwnershipKind RHS) const {
220-
auto LHSVal = Value;
221-
auto RHSVal = RHS.Value;
220+
ValueOwnershipKind ValueOwnershipKind::merge(ValueOwnershipKind rhs) const {
221+
auto lhsVal = Value;
222+
auto rhsVal = rhs.Value;
222223

223-
// Any merges with anything.
224-
if (LHSVal == ValueOwnershipKind::None) {
225-
return ValueOwnershipKind(RHSVal);
226-
}
227-
// Any merges with anything.
228-
if (RHSVal == ValueOwnershipKind::None) {
229-
return ValueOwnershipKind(LHSVal);
230-
}
224+
// If either lhs or rhs are invalid, return invalid.
225+
if (lhsVal == ValueOwnershipKind::Invalid ||
226+
rhsVal == ValueOwnershipKind::Invalid)
227+
return ValueOwnershipKind::Invalid;
228+
229+
// None merges with anything.
230+
if (lhsVal == ValueOwnershipKind::None)
231+
return ValueOwnershipKind(rhsVal);
232+
if (rhsVal == ValueOwnershipKind::None)
233+
return ValueOwnershipKind(lhsVal);
231234

232-
return (LHSVal == RHSVal) ? Optional<ValueOwnershipKind>(*this) : llvm::None;
235+
// At this point, if the two ownership kinds don't line up, the merge fails.
236+
if (lhsVal != rhsVal)
237+
return ValueOwnershipKind::Invalid;
238+
239+
// Otherwise, we are good, return *this.
240+
return *this;
233241
}
234242

235243
ValueOwnershipKind::ValueOwnershipKind(StringRef S) {

lib/SIL/IR/ValueOwnership.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ ValueOwnershipKindClassifier::visitForwardingInst(SILInstruction *i,
225225
return op.get().getOwnershipKind();
226226
}));
227227

228-
if (!mergedValue.hasValue()) {
228+
if (!mergedValue) {
229229
// If we have mismatched SILOwnership and sil ownership is not enabled,
230230
// just return None for staging purposes. If SILOwnership is enabled, then
231231
// we must assert!
@@ -235,7 +235,7 @@ ValueOwnershipKindClassifier::visitForwardingInst(SILInstruction *i,
235235
llvm_unreachable("Forwarding inst with mismatching ownership kinds?!");
236236
}
237237

238-
return mergedValue.getValue();
238+
return mergedValue;
239239
}
240240

241241
#define FORWARDING_OWNERSHIP_INST(INST) \
@@ -341,7 +341,7 @@ ValueOwnershipKind ValueOwnershipKindClassifier::visitApplyInst(ApplyInst *ai) {
341341
llvm_unreachable("Forwarding inst with mismatching ownership kinds?!");
342342
}
343343

344-
return *mergedOwnershipKind;
344+
return mergedOwnershipKind;
345345
}
346346

347347
ValueOwnershipKind ValueOwnershipKindClassifier::visitLoadInst(LoadInst *LI) {

lib/SIL/Verifier/SILOwnershipVerifier.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,8 @@ bool SILValueOwnershipChecker::gatherUsers(
487487
bool SILValueOwnershipChecker::checkFunctionArgWithoutLifetimeEndingUses(
488488
SILFunctionArgument *arg) {
489489
switch (arg->getOwnershipKind()) {
490+
case ValueOwnershipKind::Invalid:
491+
llvm_unreachable("Invalid ownership kind used?!");
490492
case ValueOwnershipKind::Guaranteed:
491493
case ValueOwnershipKind::Unowned:
492494
case ValueOwnershipKind::None:
@@ -507,6 +509,8 @@ bool SILValueOwnershipChecker::checkFunctionArgWithoutLifetimeEndingUses(
507509
bool SILValueOwnershipChecker::checkYieldWithoutLifetimeEndingUses(
508510
BeginApplyResult *yield, ArrayRef<Operand *> regularUses) {
509511
switch (yield->getOwnershipKind()) {
512+
case ValueOwnershipKind::Invalid:
513+
llvm_unreachable("Invalid ownership kind used?!");
510514
case ValueOwnershipKind::Unowned:
511515
case ValueOwnershipKind::None:
512516
return true;

lib/SILGen/RValue.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -388,7 +388,7 @@ static void verifyHelper(ArrayRef<ManagedValue> values,
388388
NullablePtr<SILGenFunction> SGF = nullptr) {
389389
// This is a no-op in non-assert builds.
390390
#ifndef NDEBUG
391-
auto result = Optional<ValueOwnershipKind>(ValueOwnershipKind::None);
391+
ValueOwnershipKind result = ValueOwnershipKind::None;
392392
Optional<bool> sameHaveCleanups;
393393
for (ManagedValue v : values) {
394394
assert((!SGF || !v.getType().isLoadable(SGF.get()->F) ||
@@ -408,8 +408,8 @@ static void verifyHelper(ArrayRef<ManagedValue> values,
408408

409409
// This variable is here so that if the assert below fires, the current
410410
// reduction value is still available.
411-
auto newResult = result.getValue().merge(kind);
412-
assert(newResult.hasValue());
411+
auto newResult = result.merge(kind);
412+
assert(newResult);
413413
result = newResult;
414414
}
415415
#endif

lib/SILOptimizer/Differentiation/Thunk.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,8 @@ SILFunction *getOrCreateReabstractionThunk(SILOptFunctionBuilder &fb,
496496
// Owned values need to be destroyed.
497497
for (auto arg : valuesToCleanup) {
498498
switch (arg.getOwnershipKind()) {
499+
case ValueOwnershipKind::Invalid:
500+
llvm_unreachable("Invalid ownership kind?!");
499501
case ValueOwnershipKind::Guaranteed:
500502
builder.emitEndBorrowOperation(loc, arg);
501503
break;

test/SIL/ownership-verifier/undef.sil

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ struct MyInt {
2020
// CHECK-NEXT: Operand Ownership Map:
2121
// CHECK-NEXT: Op #: 0
2222
// CHECK-NEXT: Ownership Map: -- OperandOwnershipKindMap --
23+
// CHECK-NEXT: invalid: No.
2324
// CHECK-NEXT: unowned: No.
2425
// CHECK-NEXT: owned: Yes. Liveness: LifetimeEnding
2526
// CHECK-NEXT: guaranteed: No.
@@ -28,6 +29,7 @@ struct MyInt {
2829
// CHECK-NEXT: Operand Ownership Map:
2930
// CHECK-NEXT: Op #: 0
3031
// CHECK-NEXT: Ownership Map: -- OperandOwnershipKindMap --
32+
// CHECK-NEXT: invalid: No.
3133
// CHECK-NEXT: unowned: No.
3234
// CHECK-NEXT: owned: Yes. Liveness: LifetimeEnding
3335
// CHECK-NEXT: guaranteed: No.
@@ -36,6 +38,7 @@ struct MyInt {
3638
// CHECK-NEXT: Operand Ownership Map:
3739
// CHECK-NEXT: Op #: 0
3840
// CHECK-NEXT: Ownership Map: -- OperandOwnershipKindMap --
41+
// CHECK-NEXT: invalid: No.
3942
// CHECK-NEXT: unowned: No.
4043
// CHECK-NEXT: owned: Yes. Liveness: LifetimeEnding
4144
// CHECK-NEXT: guaranteed: No.
@@ -44,6 +47,7 @@ struct MyInt {
4447
// CHECK-NEXT: Operand Ownership Map:
4548
// CHECK-NEXT: Op #: 0
4649
// CHECK-NEXT: Ownership Map: -- OperandOwnershipKindMap --
50+
// CHECK-NEXT: invalid: No.
4751
// CHECK-NEXT: unowned: No.
4852
// CHECK-NEXT: owned: No.
4953
// CHECK-NEXT: guaranteed: No.

0 commit comments

Comments
 (0)