static bool partialApplyEscapes(SILValue V, bool examineApply) { SILModuleConventions ModConv(*V->getModule()); llvm::SmallVector<Operand *, 32> Worklist(V->use_begin(), V->use_end()); while (!Worklist.empty()) { auto *Op = Worklist.pop_back_val(); // These instructions do not cause the address to escape. if (!useCaptured(Op)) continue; auto *User = Op->getUser(); // If we have a copy_value, the copy value does not cause an escape, but its // uses might do so... so add the copy_value's uses to the worklist and // continue. if (auto CVI = dyn_cast<CopyValueInst>(User)) { copy(CVI->getUses(), std::back_inserter(Worklist)); continue; } if (auto *Apply = dyn_cast<ApplyInst>(User)) { // Applying a function does not cause the function to escape. if (Op->getOperandNumber() == 0) continue; // apply instructions do not capture the pointer when it is passed // indirectly if (Apply->getArgumentConvention(Op->getOperandNumber() - 1) .isIndirectConvention()) continue; // Optionally drill down into an apply to see if the operand is // captured in or returned from the apply. if (examineApply && !partialApplyArgumentEscapes(Op)) continue; } // partial_apply instructions do not allow the pointer to escape // when it is passed indirectly, unless the partial_apply itself // escapes if (auto *PartialApply = dyn_cast<PartialApplyInst>(User)) { auto Args = PartialApply->getArguments(); auto Params = PartialApply->getSubstCalleeType()->getParameters(); Params = Params.slice(Params.size() - Args.size(), Args.size()); if (ModConv.isSILIndirect(Params[Op->getOperandNumber() - 1])) { if (partialApplyEscapes(PartialApply, /*examineApply = */ true)) return true; continue; } } return true; } return false; }