ValueOwnershipKind ValueOwnershipKindVisitor::visitApplyInst(ApplyInst *AI) { SILModule &M = AI->getModule(); bool IsTrivial = AI->getType().isTrivial(M); auto Results = AI->getSubstCalleeType()->getDirectResults(); // No results => empty tuple result => Trivial. if (Results.empty() || IsTrivial) return ValueOwnershipKind::Trivial; // Find the first index where we have a trivial value. auto Iter = find_if(Results, [&M](const SILResultInfo &Info) -> bool { return Info.getOwnershipKind(M) != ValueOwnershipKind::Trivial; }); // If we have all trivial, then we must be trivial. if (Iter == Results.end()) return ValueOwnershipKind::Trivial; unsigned Index = std::distance(Results.begin(), Iter); ValueOwnershipKind Base = Results[Index].getOwnershipKind(M); for (const SILResultInfo &ResultInfo : Results.slice(Index+1)) { auto RKind = ResultInfo.getOwnershipKind(M); if (RKind.merge(ValueOwnershipKind::Trivial)) continue; auto MergedValue = Base.merge(RKind.Value); if (!MergedValue.hasValue()) { llvm_unreachable("Forwarding inst with mismatching ownership kinds?!"); } } return Base; }
ValueOwnershipKind ValueOwnershipKindClassifier::visitApplyInst(ApplyInst *AI) { SILModule &M = AI->getModule(); bool IsTrivial = AI->getType().isTrivial(M); SILFunctionConventions fnConv(AI->getSubstCalleeType(), M); auto Results = fnConv.getDirectSILResults(); // No results => empty tuple result => Trivial. if (Results.empty() || IsTrivial) return ValueOwnershipKind::Trivial; CanGenericSignature Sig = AI->getSubstCalleeType()->getGenericSignature(); // Find the first index where we have a trivial value. auto Iter = find_if(Results, [&M, &Sig](const SILResultInfo &Info) -> bool { return Info.getOwnershipKind(M, Sig) != ValueOwnershipKind::Trivial; }); // If we have all trivial, then we must be trivial. if (Iter == Results.end()) return ValueOwnershipKind::Trivial; ValueOwnershipKind Base = Iter->getOwnershipKind(M, Sig); for (const SILResultInfo &ResultInfo : SILFunctionConventions::DirectSILResultRange(next(Iter), Results.end())) { auto RKind = ResultInfo.getOwnershipKind(M, Sig); if (RKind.merge(ValueOwnershipKind::Trivial)) continue; auto MergedValue = Base.merge(RKind.Value); if (!MergedValue.hasValue()) { llvm_unreachable("Forwarding inst with mismatching ownership kinds?!"); } } return Base; }
OwnershipUseCheckerResult OwnershipCompatibilityUseChecker::visitForwardingInst(SILInstruction *I) { assert(I->getNumOperands() && "Expected to have non-zero operands"); ArrayRef<Operand> Ops = I->getAllOperands(); ValueOwnershipKind Base = getOwnershipKind(); for (const Operand &Op : Ops) { auto MergedValue = Base.merge(Op.get().getOwnershipKind()); if (!MergedValue.hasValue()) return {false, true}; Base = MergedValue.getValue(); } return {true, !isAddressOrTrivialType()}; }
// For a forwarding instruction, we loop over all operands and make sure that // all non-trivial values have the same ownership. ValueOwnershipKind ValueOwnershipKindClassifier::visitForwardingInst(SILInstruction *I, ArrayRef<Operand> Ops) { // A forwarding inst without operands must be trivial. if (Ops.empty()) return ValueOwnershipKind::Trivial; // Find the first index where we have a trivial value. auto Iter = find_if(Ops, [&I](const Operand &Op) -> bool { if (I->isTypeDependentOperand(Op)) return false; return Op.get().getOwnershipKind() != ValueOwnershipKind::Trivial; }); // All trivial. if (Iter == Ops.end()) { return ValueOwnershipKind::Trivial; } // See if we have any Any. If we do, just return that for now. if (any_of(Ops, [&I](const Operand &Op) -> bool { if (I->isTypeDependentOperand(Op)) return false; return Op.get().getOwnershipKind() == ValueOwnershipKind::Any; })) return ValueOwnershipKind::Any; unsigned Index = std::distance(Ops.begin(), Iter); ValueOwnershipKind Base = Ops[Index].get().getOwnershipKind(); for (const Operand &Op : Ops.slice(Index + 1)) { if (I->isTypeDependentOperand(Op)) continue; auto OpKind = Op.get().getOwnershipKind(); if (OpKind.merge(ValueOwnershipKind::Trivial)) continue; auto MergedValue = Base.merge(OpKind.Value); if (!MergedValue.hasValue()) { // If we have mismatched SILOwnership and sil ownership is not enabled, // just return Any for staging purposes. If SILOwnership is enabled, then // we must assert! if (!I->getModule().getOptions().EnableSILOwnership) { return ValueOwnershipKind::Any; } llvm_unreachable("Forwarding inst with mismatching ownership kinds?!"); } } return Base; }
OwnershipUseCheckerResult OwnershipCompatibilityUseChecker::visitReturnInst(ReturnInst *RI) { SILModule &M = RI->getModule(); bool IsTrivial = RI->getOperand()->getType().isTrivial(M); auto Results = RI->getFunction()->getLoweredFunctionType()->getDirectResults(); if (Results.empty() || IsTrivial) { return {compatibleWithOwnership(ValueOwnershipKind::Trivial), false}; } // Find the first index where we have a trivial value. auto Iter = find_if(Results, [&M](const SILResultInfo &Info) -> bool { return Info.getOwnershipKind(M) != ValueOwnershipKind::Trivial; }); // If we have all trivial, then we must be trivial. Why wasn't our original // type trivial? This is a hard error since this is a logic error in our code // here. if (Iter == Results.end()) llvm_unreachable("Should have already checked a trivial type?!"); unsigned Index = std::distance(Results.begin(), Iter); ValueOwnershipKind Base = Results[Index].getOwnershipKind(M); for (const SILResultInfo &ResultInfo : Results.slice(Index + 1)) { auto RKind = ResultInfo.getOwnershipKind(M); // Ignore trivial types. if (RKind.merge(ValueOwnershipKind::Trivial)) continue; auto MergedValue = Base.merge(RKind); // If we fail to merge all types in, bail. We can not come up with a proper // result type. if (!MergedValue.hasValue()) { return {false, false}; } // In case Base is Any. Base = MergedValue.getValue(); } return {compatibleWithOwnership(Base), true}; }
// For a forwarding instruction, we loop over all operands and make sure that // all non-trivial values have the same ownership. ValueOwnershipKind ValueOwnershipKindVisitor::visitForwardingInst(SILInstruction *I) { ArrayRef<Operand> Ops = I->getAllOperands(); // A forwarding inst without operands must be trivial. if (Ops.empty()) return ValueOwnershipKind::Trivial; // Find the first index where we have a trivial value. auto Iter = find_if(Ops, [](const Operand &Op) -> bool { return Op.get().getOwnershipKind() != ValueOwnershipKind::Trivial; }); // All trivial. if (Iter == Ops.end()) { return ValueOwnershipKind::Trivial; } // See if we have any Any. If we do, just return that for now. if (any_of(Ops, [](const Operand &Op) -> bool { return Op.get().getOwnershipKind() == ValueOwnershipKind::Any; })) return ValueOwnershipKind::Any; unsigned Index = std::distance(Ops.begin(), Iter); ValueOwnershipKind Base = Ops[Index].get().getOwnershipKind(); for (const Operand &Op : Ops.slice(Index+1)) { auto OpKind = Op.get().getOwnershipKind(); if (OpKind.merge(ValueOwnershipKind::Trivial)) continue; auto MergedValue = Base.merge(OpKind.Value); if (!MergedValue.hasValue()) { llvm_unreachable("Forwarding inst with mismatching ownership kinds?!"); } } return Base; }
static bool compatibleOwnershipKinds(ValueOwnershipKind K1, ValueOwnershipKind K2) { return K1.merge(K2).hasValue(); }