void SILCombiner::eraseApply(FullApplySite FAS, const UserListTy &Users) { // Make sure to release and destroy any owned or in-arguments. auto FuncType = FAS.getOrigCalleeType(); assert(FuncType->getParameters().size() == FAS.getNumArguments() && "mismatching number of arguments"); for (int i = 0, e = FAS.getNumArguments(); i < e; ++i) { SILParameterInfo PI = FuncType->getParameters()[i]; auto Arg = FAS.getArgument(i); switch (PI.getConvention()) { case ParameterConvention::Indirect_In: Builder.createDestroyAddr(FAS.getLoc(), Arg); break; case ParameterConvention::Direct_Owned: Builder.createReleaseValue(FAS.getLoc(), Arg, Atomicity::Atomic); break; case ParameterConvention::Indirect_In_Guaranteed: case ParameterConvention::Indirect_Inout: case ParameterConvention::Indirect_InoutAliasable: case ParameterConvention::Direct_Unowned: case ParameterConvention::Direct_Deallocating: case ParameterConvention::Direct_Guaranteed: break; } } // Erase all of the reference counting instructions (in reverse order to have // no dangling uses). for (auto rit = Users.rbegin(), re = Users.rend(); rit != re; ++rit) eraseInstFromFunction(**rit); // And the Apply itself. eraseInstFromFunction(*FAS.getInstruction()); }
bool AliasAnalysis::canApplyDecrementRefCount(FullApplySite FAS, SILValue Ptr) { // Treat applications of @noreturn functions as decrementing ref counts. This // causes the apply to become a sink barrier for ref count increments. if (FAS.getCallee().getType().getAs<SILFunctionType>()->isNoReturn()) return true; /// If the pointer cannot escape to the function we are done. if (!EA->canEscapeTo(Ptr, FAS)) return false; SideEffectAnalysis::FunctionEffects ApplyEffects; SEA->getEffects(ApplyEffects, FAS); auto &GlobalEffects = ApplyEffects.getGlobalEffects(); if (ApplyEffects.mayReadRC() || GlobalEffects.mayRelease()) return true; /// The function has no unidentified releases, so let's look at the arguments // in detail. for (unsigned Idx = 0, End = FAS.getNumArguments(); Idx < End; ++Idx) { auto &ArgEffect = ApplyEffects.getParameterEffects()[Idx]; if (ArgEffect.mayRelease()) { // The function may release this argument, so check if the pointer can // escape to it. if (EA->canEscapeToValue(Ptr, FAS.getArgument(Idx))) return true; } } return false; }
void ArgumentDescriptor::addCallerArgs( SILBuilder &B, FullApplySite FAS, llvm::SmallVectorImpl<SILValue> &NewArgs) const { if (IsDead) return; SILValue Arg = FAS.getArgument(Index); if (!shouldExplode()) { NewArgs.push_back(Arg); return; } ProjTree.createTreeFromValue(B, FAS.getLoc(), Arg, NewArgs); }
bool FunctionEffects::mergeFromApply( const FunctionEffects &ApplyEffects, FullApplySite FAS) { bool Changed = mergeFlags(ApplyEffects); Changed |= GlobalEffects.mergeFrom(ApplyEffects.GlobalEffects); unsigned numCallerArgs = FAS.getNumArguments(); unsigned numCalleeArgs = ApplyEffects.ParamEffects.size(); assert(numCalleeArgs >= numCallerArgs); for (unsigned Idx = 0; Idx < numCalleeArgs; Idx++) { // Map the callee argument effects to parameters of this function. // If there are more callee parameters than arguments it means that the // callee is the result of a partial_apply. Effects *E = (Idx < numCallerArgs ? getEffectsOn(FAS.getArgument(Idx)) : &GlobalEffects); Changed |= E->mergeFrom(ApplyEffects.ParamEffects[Idx]); } return Changed; }
/// Returns the argument of the full apply or partial apply corresponding to the /// callee's parameter index, or returns an invalid SILValue if the applied /// closure cannot be found. This walks up the apply chain starting at the given /// `fullApply` to find the applied argument. static SILValue getCallerArg(FullApplySite fullApply, unsigned paramIndex) { if (paramIndex < fullApply.getNumArguments()) return fullApply.getArgument(paramIndex); SILValue callee = fullApply.getCalleeOrigin(); auto *PAI = dyn_cast<PartialApplyInst>(callee); if (!PAI) return SILValue(); unsigned appliedIndex = paramIndex - ApplySite(PAI).getCalleeArgIndexOfFirstAppliedArg(); if (appliedIndex < PAI->getNumArguments()) return PAI->getArgument(appliedIndex); // This must be a chain of partial_applies. We don't expect this in practice, // so handle it conservatively. return SILValue(); }