int getStackDepth(SILBasicBlock *BB) { assert(Block2StackDepth.find(BB) != Block2StackDepth.end()); int Depth = Block2StackDepth.lookup(BB); assert(Depth >= 0 && "EndBlock not reachable from StartBlock"); return Depth; }
/// Process an apply instruction which uses a partial_apply /// as its callee. /// Returns true on success. bool PartialApplyCombiner::processSingleApply(FullApplySite AI) { Builder.setInsertionPoint(AI.getInstruction()); Builder.setCurrentDebugScope(AI.getDebugScope()); // Prepare the args. SmallVector<SILValue, 8> Args; // First the ApplyInst args. for (auto Op : AI.getArguments()) Args.push_back(Op); SILInstruction *InsertionPoint = &*Builder.getInsertionPoint(); // Next, the partial apply args. // Pre-process partial_apply arguments only once, lazily. if (isFirstTime) { isFirstTime = false; if (!allocateTemporaries()) return false; } // Now, copy over the partial apply args. for (auto Op : PAI->getArguments()) { auto Arg = Op; // If there is new temporary for this argument, use it instead. if (isa<AllocStackInst>(Arg)) { if (ArgToTmp.count(Arg)) { Op = ArgToTmp.lookup(Arg); } } Args.push_back(Op); } Builder.setInsertionPoint(InsertionPoint); Builder.setCurrentDebugScope(AI.getDebugScope()); // The thunk that implements the partial apply calls the closure function // that expects all arguments to be consumed by the function. However, the // captured arguments are not arguments of *this* apply, so they are not // pre-incremented. When we combine the partial_apply and this apply into // a new apply we need to retain all of the closure non-address type // arguments. auto ParamInfo = PAI->getSubstCalleeType()->getParameters(); auto PartialApplyArgs = PAI->getArguments(); // Set of arguments that need to be released after each invocation. SmallVector<SILValue, 8> ToBeReleasedArgs; for (unsigned i = 0, e = PartialApplyArgs.size(); i < e; ++i) { SILValue Arg = PartialApplyArgs[i]; if (!Arg->getType().isAddress()) { // Retain the argument as the callee may consume it. Builder.emitRetainValueOperation(PAI->getLoc(), Arg); // For non consumed parameters (e.g. guaranteed), we also need to // insert releases after each apply instruction that we create. if (!ParamInfo[ParamInfo.size() - PartialApplyArgs.size() + i]. isConsumed()) ToBeReleasedArgs.push_back(Arg); } } auto *F = FRI->getReferencedFunction(); SILType FnType = F->getLoweredType(); SILType ResultTy = F->getLoweredFunctionType()->getSILResult(); ArrayRef<Substitution> Subs = PAI->getSubstitutions(); if (!Subs.empty()) { FnType = FnType.substGenericArgs(PAI->getModule(), Subs); ResultTy = FnType.getAs<SILFunctionType>()->getSILResult(); } FullApplySite NAI; if (auto *TAI = dyn_cast<TryApplyInst>(AI)) NAI = Builder.createTryApply(AI.getLoc(), FRI, FnType, Subs, Args, TAI->getNormalBB(), TAI->getErrorBB()); else NAI = Builder.createApply(AI.getLoc(), FRI, FnType, ResultTy, Subs, Args, cast<ApplyInst>(AI)->isNonThrowing()); // We also need to release the partial_apply instruction itself because it // is consumed by the apply_instruction. if (auto *TAI = dyn_cast<TryApplyInst>(AI)) { Builder.setInsertionPoint(TAI->getNormalBB()->begin()); for (auto Arg : ToBeReleasedArgs) { Builder.emitReleaseValueOperation(PAI->getLoc(), Arg); } Builder.createStrongRelease(AI.getLoc(), PAI, Atomicity::Atomic); Builder.setInsertionPoint(TAI->getErrorBB()->begin()); // Release the non-consumed parameters. for (auto Arg : ToBeReleasedArgs) { Builder.emitReleaseValueOperation(PAI->getLoc(), Arg); } Builder.createStrongRelease(AI.getLoc(), PAI, Atomicity::Atomic); Builder.setInsertionPoint(AI.getInstruction()); } else { // Release the non-consumed parameters. for (auto Arg : ToBeReleasedArgs) { Builder.emitReleaseValueOperation(PAI->getLoc(), Arg); } Builder.createStrongRelease(AI.getLoc(), PAI, Atomicity::Atomic); } SilCombiner->replaceInstUsesWith(*AI.getInstruction(), NAI.getInstruction()); SilCombiner->eraseInstFromFunction(*AI.getInstruction()); return true; }