Skip to content

Commit e2f427a

Browse files
authored
Merge pull request swiftlang#35152 from atrick/ownershipenum
Convert OperandOwnership from an enum class to a struct enum.
2 parents c9283e3 + f777e0a commit e2f427a

File tree

4 files changed

+125
-113
lines changed

4 files changed

+125
-113
lines changed

include/swift/SIL/SILValue.h

Lines changed: 100 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ struct OwnershipKind {
226226

227227
llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const OwnershipKind &kind);
228228

229-
enum class OperandOwnership;
229+
struct OperandOwnership;
230230

231231
/// A value representing the specific ownership semantics that a SILValue may
232232
/// have.
@@ -624,86 +624,108 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
624624
/// Used to verify completeness of the ownership use model and exhaustively
625625
/// switch over any category of ownership use. Implies ownership constraints and
626626
/// lifetime constraints.
627-
enum class OperandOwnership {
628-
/// Uses of ownership None. These uses are incompatible with values that have
629-
/// ownership but are otherwise not verified.
630-
None,
631-
632-
/// Use the value only for the duration of the operation, which may have side
633-
/// effects. Requires an owned or guaranteed value.
634-
/// (single-instruction apply with @guaranteed argument)
635-
InstantaneousUse,
636-
637-
/// MARK: Uses of Any ownership values:
638-
639-
/// Use a value without requiring or propagating ownership. The operation may
640-
/// not have side-effects that could affect ownership. This is limited to a
641-
/// small number of operations that are allowed to take Unowned values.
642-
/// (copy_value, single-instruction apply with @unowned argument))
643-
UnownedInstantaneousUse,
644-
645-
/// Forwarding instruction with an Unowned result. Its operands may have any
646-
/// ownership.
647-
ForwardingUnowned,
648-
649-
// Escape a pointer into a value in a way that cannot be tracked or verified.
650-
//
651-
// TODO: Eliminate the PointerEscape category. All pointer escapes should be
652-
// InteriorPointer, guarded by a borrow scope, and verified.
653-
PointerEscape,
654-
655-
/// Bitwise escape. Escapes the nontrivial contents of the value.
656-
/// OSSA does not enforce the lifetime of the escaping bits.
657-
/// The programmer must explicitly force lifetime extension.
658-
/// (ref_to_unowned, unchecked_trivial_bitcast)
659-
BitwiseEscape,
660-
661-
/// MARK: Uses of Owned values:
662-
663-
/// Borrow. Propagates the owned value within a scope, without consuming it.
664-
/// (begin_borrow, begin_apply with @guaranteed argument)
665-
Borrow,
666-
/// Destroying Consume. Destroys the owned value immediately.
667-
/// (store, destroy, @owned destructure).
668-
DestroyingConsume,
669-
/// Forwarding Consume. Consumes the owned value indirectly via a move.
670-
/// (br, destructure, tuple, struct, cast, switch).
671-
ForwardingConsume,
672-
673-
/// MARK: Uses of Guaranteed values:
674-
675-
/// Nested Borrow. Propagates the guaranteed value within a nested borrow
676-
/// scope, without ending the outer borrow scope, following stack discipline.
677-
/// (begin_borrow, begin_apply with @guaranteed).
678-
NestedBorrow,
679-
/// Interior Pointer. Propagates a trivial value (e.g. address, pointer, or
680-
/// no-escape closure) that depends on the guaranteed value within the base's
681-
/// borrow scope. The verifier checks that all uses of the trivial value are
682-
/// in scope. (ref_element_addr, open_existential_box)
683-
InteriorPointer,
684-
/// Forwarded Borrow. Propagates the guaranteed value within the base's
685-
/// borrow scope.
686-
/// (tuple_extract, struct_extract, cast, switch)
687-
ForwardingBorrow,
688-
/// End Borrow. End the borrow scope opened directly by the operand.
689-
/// The operand must be a begin_borrow, begin_apply, or function argument.
690-
/// (end_borrow, end_apply)
691-
EndBorrow,
692-
// Reborrow. Ends the borrow scope opened directly by the operand and begins
693-
// one or multiple disjoint borrow scopes. If a forwarded value is reborrowed,
694-
// then its base must also be reborrowed at the same point.
695-
// (br, FIXME: should also include destructure, tuple, struct)
696-
Reborrow
627+
struct OperandOwnership {
628+
enum innerty : uint8_t {
629+
/// Uses of ownership None. These uses are incompatible with values that
630+
/// have ownership but are otherwise not verified.
631+
None,
632+
633+
/// Use the value only for the duration of the operation, which may have
634+
/// side effects. Requires an owned or guaranteed value.
635+
/// (single-instruction apply with @guaranteed argument)
636+
InstantaneousUse,
637+
638+
/// MARK: Uses of Any ownership values:
639+
640+
/// Use a value without requiring or propagating ownership. The operation
641+
/// may not have side-effects that could affect ownership. This is limited
642+
/// to a small number of operations that are allowed to take Unowned values.
643+
/// (copy_value, single-instruction apply with @unowned argument))
644+
UnownedInstantaneousUse,
645+
646+
/// Forwarding instruction with an Unowned result. Its operands may have any
647+
/// ownership.
648+
ForwardingUnowned,
649+
650+
// Escape a pointer into a value which cannot be tracked or verified.
651+
//
652+
// TODO: Eliminate the PointerEscape category. All pointer escapes should be
653+
// InteriorPointer, guarded by a borrow scope, and verified.
654+
PointerEscape,
655+
656+
/// Bitwise escape. Escapes the nontrivial contents of the value.
657+
/// OSSA does not enforce the lifetime of the escaping bits.
658+
/// The programmer must explicitly force lifetime extension.
659+
/// (ref_to_unowned, unchecked_trivial_bitcast)
660+
BitwiseEscape,
661+
662+
/// MARK: Uses of Owned values:
663+
664+
/// Borrow. Propagates the owned value within a scope, without consuming it.
665+
/// (begin_borrow, begin_apply with @guaranteed argument)
666+
Borrow,
667+
/// Destroying Consume. Destroys the owned value immediately.
668+
/// (store, destroy, @owned destructure).
669+
DestroyingConsume,
670+
/// Forwarding Consume. Consumes the owned value indirectly via a move.
671+
/// (br, destructure, tuple, struct, cast, switch).
672+
ForwardingConsume,
673+
674+
/// MARK: Uses of Guaranteed values:
675+
676+
/// Nested Borrow. Propagates the guaranteed value within a nested borrow
677+
/// scope, without ending the outer borrow scope, following stack
678+
/// discipline.
679+
/// (begin_borrow, begin_apply with @guaranteed).
680+
NestedBorrow,
681+
/// Interior Pointer. Propagates a trivial value (e.g. address, pointer, or
682+
/// no-escape closure) that depends on the guaranteed value within the
683+
/// base's borrow scope. The verifier checks that all uses of the trivial
684+
/// value are in scope.
685+
/// (ref_element_addr, open_existential_box)
686+
InteriorPointer,
687+
/// Forwarded Borrow. Propagates the guaranteed value within the base's
688+
/// borrow scope.
689+
/// (tuple_extract, struct_extract, cast, switch)
690+
ForwardingBorrow,
691+
/// End Borrow. End the borrow scope opened directly by the operand.
692+
/// The operand must be a begin_borrow, begin_apply, or function argument.
693+
/// (end_borrow, end_apply)
694+
EndBorrow,
695+
// Reborrow. Ends the borrow scope opened directly by the operand and begins
696+
// one or multiple disjoint borrow scopes. If a forwarded value is
697+
// reborrowed, then its base must also be reborrowed at the same point.
698+
// (br, FIXME: should also include destructure, tuple, struct)
699+
Reborrow
700+
} value;
701+
702+
OperandOwnership(innerty newValue) : value(newValue) {}
703+
OperandOwnership(const OperandOwnership &other): value(other.value) {}
704+
705+
OperandOwnership &operator=(const OperandOwnership &other) {
706+
value = other.value;
707+
return *this;
708+
}
709+
710+
OperandOwnership &operator=(OperandOwnership::innerty other) {
711+
value = other;
712+
return *this;
713+
}
714+
715+
operator innerty() const { return value; }
716+
717+
StringRef asString() const;
718+
719+
/// Return the OwnershipConstraint corresponding to this OperandOwnership.
720+
OwnershipConstraint getOwnershipConstraint();
697721
};
698722

699-
llvm::raw_ostream &operator<<(llvm::raw_ostream &os, OperandOwnership operandOwnership);
723+
llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
724+
const OperandOwnership &operandOwnership);
700725

701-
/// Return the OwnershipConstraint for a OperandOwnership.
702-
///
703726
/// Defined inline so the switch is eliminated for constant OperandOwnership.
704-
inline OwnershipConstraint
705-
getOwnershipConstraint(OperandOwnership operandOwnership) {
706-
switch (operandOwnership) {
727+
inline OwnershipConstraint OperandOwnership::getOwnershipConstraint() {
728+
switch (value) {
707729
case OperandOwnership::None:
708730
return {OwnershipKind::None, UseLifetimeConstraint::NonLifetimeEnding};
709731
case OperandOwnership::InstantaneousUse:
@@ -847,7 +869,7 @@ class Operand {
847869
if (!operandOwnership) {
848870
return None;
849871
}
850-
return swift::getOwnershipConstraint(operandOwnership.getValue());
872+
return operandOwnership->getOwnershipConstraint();
851873
}
852874

853875
/// Returns true if changing the operand to use a value with the given

lib/SIL/IR/OperandOwnership.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -791,7 +791,7 @@ Optional<OperandOwnership> Operand::getOperandOwnership() const {
791791
// If we don't have a function, then we must have a SILGlobalVariable. In
792792
// that case, we act as if we aren't in ownership.
793793
if (!func || !func->hasOwnership()) {
794-
return OperandOwnership::InstantaneousUse;
794+
return OperandOwnership(OperandOwnership::InstantaneousUse);
795795
}
796796
}
797797

lib/SIL/IR/SILValue.cpp

Lines changed: 22 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ bool Operand::canAcceptKind(ValueOwnershipKind kind) const {
346346
if (!operandOwnership) {
347347
return false;
348348
}
349-
auto constraint = ::getOwnershipConstraint(operandOwnership.getValue());
349+
auto constraint = operandOwnership->getOwnershipConstraint();
350350
if (constraint.satisfiesConstraint(kind)) {
351351
// Constraints aren't precise enough to enforce Unowned value uses.
352352
if (kind == OwnershipKind::Unowned) {
@@ -397,51 +397,40 @@ llvm::raw_ostream &swift::operator<<(llvm::raw_ostream &os,
397397
<< ">";
398398
}
399399

400-
llvm::raw_ostream &swift::operator<<(llvm::raw_ostream &os,
401-
OperandOwnership operandOwnership) {
402-
switch (operandOwnership) {
400+
StringRef OperandOwnership::asString() const {
401+
switch (value) {
403402
case OperandOwnership::None:
404-
os << "none";
405-
break;
403+
return "none";
406404
case OperandOwnership::InstantaneousUse:
407-
os << "instantaneous";
408-
break;
405+
return "instantaneous";
409406
case OperandOwnership::UnownedInstantaneousUse:
410-
os << "unowned-instantaneous";
411-
break;
407+
return "unowned-instantaneous";
412408
case OperandOwnership::ForwardingUnowned:
413-
os << "forwarding-unowned";
414-
break;
409+
return "forwarding-unowned";
415410
case OperandOwnership::PointerEscape:
416-
os << "pointer-escape";
417-
break;
411+
return "pointer-escape";
418412
case OperandOwnership::BitwiseEscape:
419-
os << "bitwise-escape";
420-
break;
413+
return "bitwise-escape";
421414
case OperandOwnership::Borrow:
422-
os << "borrow";
423-
break;
415+
return "borrow";
424416
case OperandOwnership::DestroyingConsume:
425-
os << "destroying-consume";
426-
break;
417+
return "destroying-consume";
427418
case OperandOwnership::ForwardingConsume:
428-
os << "forwarding-consume";
429-
break;
419+
return "forwarding-consume";
430420
case OperandOwnership::NestedBorrow:
431-
os << "nested-borrow";
432-
break;
421+
return "nested-borrow";
433422
case OperandOwnership::InteriorPointer:
434-
os << "interior-pointer";
435-
break;
423+
return "interior-pointer";
436424
case OperandOwnership::ForwardingBorrow:
437-
os << "forwarding-borrow";
438-
break;
425+
return "forwarding-borrow";
439426
case OperandOwnership::EndBorrow:
440-
os << "end-borrow";
441-
break;
427+
return "end-borrow";
442428
case OperandOwnership::Reborrow:
443-
os << "reborrow";
444-
break;
429+
return "reborrow";
445430
}
446-
return os;
431+
}
432+
433+
llvm::raw_ostream &swift::operator<<(llvm::raw_ostream &os,
434+
const OperandOwnership &operandOwnership) {
435+
return os << operandOwnership.asString();
447436
}

lib/SIL/Verifier/SILOwnershipVerifier.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,8 @@ bool SILValueOwnershipChecker::gatherUsers(
326326
// Example: A guaranteed parameter of a co-routine.
327327

328328
// Now check if we have a non guaranteed forwarding inst...
329-
if (op->getOperandOwnership() != OperandOwnership::ForwardingBorrow) {
329+
if (op->getOperandOwnership().getValue()
330+
!= OperandOwnership::ForwardingBorrow) {
330331
// First check if we are visiting an operand that is a consuming use...
331332
if (op->isLifetimeEnding()) {
332333
// If its underlying value is our original value, then this is a true

0 commit comments

Comments
 (0)