Files
swift-mirror/lib/SIL/OwnershipUtils.cpp
Michael Gottesman 0af0d5fddc [ownership] Replace ValueOwnershipKind::Trivial with ValueOwnershipKind::Any.
In a previous commit, I banned in the verifier any SILValue from producing
ValueOwnershipKind::Any in preparation for this.

This change arises out of discussions in between John, Andy, and I around
ValueOwnershipKind::Trivial. The specific realization was that this ownership
kind was an unnecessary conflation of the a type system idea (triviality) with
an ownership idea (@any, an ownership kind that is compatible with any other
ownership kind at value merge points and can only create). This caused the
ownership model to have to contort to handle the non-payloaded or trivial cases
of non-trivial enums. This is unnecessary if we just eliminate the any case and
in the verifier separately verify that trivial => @any (notice that we do not
verify that @any => trivial).

NOTE: This is technically an NFC intended change since I am just replacing
Trivial with Any. That is why if you look at the tests you will see that I
actually did not need to update anything except removing some @trivial ownership
since @any ownership is represented without writing @any in the parsed sil.

rdar://46294760
2018-12-04 23:01:43 -08:00

128 lines
4.1 KiB
C++

//===--- OwnershipUtils.cpp -----------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#include "swift/SIL/OwnershipUtils.h"
#include "swift/SIL/SILArgument.h"
#include "swift/SIL/SILInstruction.h"
using namespace swift;
bool swift::isValueAddressOrTrivial(SILValue v, SILModule &m) {
return v->getType().isAddress() ||
v.getOwnershipKind() == ValueOwnershipKind::Any;
}
// These operations forward both owned and guaranteed ownership.
bool swift::isOwnershipForwardingValueKind(SILNodeKind kind) {
switch (kind) {
case SILNodeKind::TupleInst:
case SILNodeKind::StructInst:
case SILNodeKind::EnumInst:
case SILNodeKind::OpenExistentialRefInst:
case SILNodeKind::UpcastInst:
case SILNodeKind::UncheckedRefCastInst:
case SILNodeKind::ConvertFunctionInst:
case SILNodeKind::RefToBridgeObjectInst:
case SILNodeKind::BridgeObjectToRefInst:
case SILNodeKind::UnconditionalCheckedCastInst:
case SILNodeKind::UncheckedEnumDataInst:
case SILNodeKind::MarkUninitializedInst:
case SILNodeKind::SelectEnumInst:
case SILNodeKind::SwitchEnumInst:
case SILNodeKind::CheckedCastBranchInst:
case SILNodeKind::BranchInst:
case SILNodeKind::CondBranchInst:
case SILNodeKind::DestructureStructInst:
case SILNodeKind::DestructureTupleInst:
return true;
default:
return false;
}
}
// These operations forward guaranteed ownership, but don't necessarily forward
// owned values.
bool swift::isGuaranteedForwardingValueKind(SILNodeKind kind) {
switch (kind) {
case SILNodeKind::TupleExtractInst:
case SILNodeKind::StructExtractInst:
case SILNodeKind::OpenExistentialValueInst:
case SILNodeKind::OpenExistentialBoxValueInst:
return true;
default:
return isOwnershipForwardingValueKind(kind);
}
}
bool swift::isGuaranteedForwardingValue(SILValue value) {
return isGuaranteedForwardingValueKind(
value->getKindOfRepresentativeSILNodeInObject());
}
bool swift::isGuaranteedForwardingInst(SILInstruction *i) {
return isGuaranteedForwardingValueKind(SILNodeKind(i->getKind()));
}
bool swift::isOwnershipForwardingInst(SILInstruction *i) {
return isOwnershipForwardingValueKind(SILNodeKind(i->getKind()));
}
bool swift::getUnderlyingBorrowIntroducers(SILValue inputValue,
SmallVectorImpl<SILValue> &out) {
if (inputValue.getOwnershipKind() != ValueOwnershipKind::Guaranteed)
return false;
SmallVector<SILValue, 32> worklist;
worklist.emplace_back(inputValue);
while (!worklist.empty()) {
SILValue v = worklist.pop_back_val();
// First check if v is an introducer. If so, stash it and continue.
if (isa<LoadBorrowInst>(v) ||
isa<BeginBorrowInst>(v)) {
out.push_back(v);
continue;
}
// If we have a function argument with guaranteed convention, it is also an
// introducer.
if (auto *arg = dyn_cast<SILFunctionArgument>(v)) {
if (arg->getOwnershipKind() == ValueOwnershipKind::Guaranteed) {
out.push_back(v);
continue;
}
// Otherwise, we do not know how to handle this function argument, so
// bail.
return false;
}
// Otherwise if v is an ownership forwarding value, add its defining
// instruction
if (isGuaranteedForwardingValue(v)) {
auto *i = v->getDefiningInstruction();
assert(i);
transform(i->getAllOperands(), std::back_inserter(worklist),
[](const Operand &op) -> SILValue { return op.get(); });
continue;
}
// If v produces any ownership, then we can ignore it. Otherwise, we need to
// return false since this is an introducer we do not understand.
if (v.getOwnershipKind() != ValueOwnershipKind::Any)
return false;
}
return true;
}