mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
128 lines
4.1 KiB
C++
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) {
|
|
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;
|
|
}
|