//===--- 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 &out) { if (inputValue.getOwnershipKind() != ValueOwnershipKind::Guaranteed) return false; SmallVector 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(v) || isa(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(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; }