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()); }
void SideEffectAnalysis::getEffects(FunctionEffects &ApplyEffects, FullApplySite FAS) { assert(ApplyEffects.ParamEffects.size() == 0 && "Not using a new ApplyEffects?"); ApplyEffects.ParamEffects.resize(FAS.getNumArguments()); // Is this a call to a semantics function? ArraySemanticsCall ASC(FAS.getInstruction()); if (ASC && ASC.hasSelf()) { if (getSemanticEffects(ApplyEffects, ASC)) return; } if (SILFunction *SingleCallee = FAS.getCalleeFunction()) { // Does the function have any @effects? if (getDefinedEffects(ApplyEffects, SingleCallee)) return; } auto Callees = BCA->getCalleeList(FAS); if (!Callees.allCalleesVisible() || // @callee_owned function calls implicitly release the context, which // may call deinits of boxed values. // TODO: be less conservative about what destructors might be called. FAS.getOrigCalleeType()->isCalleeConsumed()) { ApplyEffects.setWorstEffects(); return; } // We can see all the callees. So we just merge the effects from all of // them. for (auto *Callee : Callees) { const FunctionEffects &CalleeFE = getEffects(Callee); ApplyEffects.mergeFrom(CalleeFE); } }
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 SideEffectAnalysis::getEffects(FunctionEffects &ApplyEffects, FullApplySite FAS) { assert(ApplyEffects.ParamEffects.size() == 0 && "Not using a new ApplyEffects?"); ApplyEffects.ParamEffects.resize(FAS.getNumArguments()); // Is this a call to a semantics function? ArraySemanticsCall ASC(FAS.getInstruction()); if (ASC && ASC.hasSelf()) { if (getSemanticEffects(ApplyEffects, ASC)) return; } if (SILFunction *SingleCallee = FAS.getCalleeFunction()) { // Does the function have any @effects? if (getDefinedEffects(ApplyEffects, SingleCallee)) return; } auto Callees = BCA->getCalleeList(FAS); if (!Callees.allCalleesVisible()) { ApplyEffects.setWorstEffects(); return; } // We can see all the callees. So we just merge the effects from all of // them. for (auto *Callee : Callees) { const FunctionEffects &CalleeFE = getEffects(Callee); ApplyEffects.mergeFrom(CalleeFE); } }
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(); }
// Summarize the callee side effects of a call instruction using this // FunctionSideEffects object without analyzing the callee function bodies or // scheduling the callees for bottom-up propagation. // // Return true if this call-site's effects are summarized without visiting the // callee. bool FunctionSideEffects::summarizeCall(FullApplySite fullApply) { assert(ParamEffects.empty() && "Expect uninitialized effects."); ParamEffects.resize(fullApply.getNumArguments()); // Is this a call to a semantics function? if (auto apply = dyn_cast<ApplyInst>(fullApply.getInstruction())) { ArraySemanticsCall ASC(apply); if (ASC && ASC.hasSelf()) { if (setSemanticEffects(ASC)) return true; } } if (SILFunction *SingleCallee = fullApply.getReferencedFunction()) { // Does the function have any @effects? if (setDefinedEffects(SingleCallee)) return true; } return false; }