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); } }
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 GenericFunctionEffectAnalysis<FunctionEffects>::analyzeCall( FunctionInfo *functionInfo, FullApplySite fullApply, FunctionOrder &bottomUpOrder, int recursionDepth) { FunctionEffects applyEffects; if (applyEffects.summarizeCall(fullApply)) { functionInfo->functionEffects.mergeFromApply(applyEffects, fullApply); return; } if (recursionDepth >= MaxRecursionDepth) { functionInfo->functionEffects.setWorstEffects(); return; } CalleeList callees = BCA->getCalleeList(fullApply); 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. fullApply.getOrigCalleeType()->isCalleeConsumed()) { functionInfo->functionEffects.setWorstEffects(); return; } // Derive the effects of the apply from the known callees. // Defer merging callee effects until the callee is scheduled for (SILFunction *callee : callees) { FunctionInfo *calleeInfo = getFunctionInfo(callee); calleeInfo->addCaller(functionInfo, fullApply); if (!calleeInfo->isVisited()) { // Recursively visit the called function. analyzeFunction(calleeInfo, bottomUpOrder, recursionDepth + 1); bottomUpOrder.tryToSchedule(calleeInfo); } } }
// Start with the substitutions from the apply. // Try to propagate them to find out the real substitutions required // to invoke the method. static SubstitutionMap getSubstitutionsForCallee(SILModule &M, CanSILFunctionType baseCalleeType, CanType derivedSelfType, FullApplySite AI) { // If the base method is not polymorphic, no substitutions are required, // even if we originally had substitutions for calling the derived method. if (!baseCalleeType->isPolymorphic()) return SubstitutionMap(); // Add any generic substitutions for the base class. Type baseSelfType = baseCalleeType->getSelfParameter().getType(); if (auto metatypeType = baseSelfType->getAs<MetatypeType>()) baseSelfType = metatypeType->getInstanceType(); auto *baseClassDecl = baseSelfType->getClassOrBoundGenericClass(); assert(baseClassDecl && "not a class method"); unsigned baseDepth = 0; SubstitutionMap baseSubMap; if (auto baseClassSig = baseClassDecl->getGenericSignatureOfContext()) { baseDepth = baseClassSig->getGenericParams().back()->getDepth() + 1; // Compute the type of the base class, starting from the // derived class type and the type of the method's self // parameter. Type derivedClass = derivedSelfType; if (auto metatypeType = derivedClass->getAs<MetatypeType>()) derivedClass = metatypeType->getInstanceType(); baseSubMap = derivedClass->getContextSubstitutionMap( M.getSwiftModule(), baseClassDecl); } SubstitutionMap origSubMap = AI.getSubstitutionMap(); Type calleeSelfType = AI.getOrigCalleeType()->getSelfParameter().getType(); if (auto metatypeType = calleeSelfType->getAs<MetatypeType>()) calleeSelfType = metatypeType->getInstanceType(); auto *calleeClassDecl = calleeSelfType->getClassOrBoundGenericClass(); assert(calleeClassDecl && "self is not a class type"); // Add generic parameters from the method itself, ignoring any generic // parameters from the derived class. unsigned origDepth = 0; if (auto calleeClassSig = calleeClassDecl->getGenericSignatureOfContext()) origDepth = calleeClassSig->getGenericParams().back()->getDepth() + 1; auto baseCalleeSig = baseCalleeType->getGenericSignature(); return SubstitutionMap::combineSubstitutionMaps(baseSubMap, origSubMap, CombineSubstitutionMaps::AtDepth, baseDepth, origDepth, baseCalleeSig); }
void GenericFunctionEffectAnalysis<FunctionEffects>::getCalleeEffects( FunctionEffects &calleeEffects, FullApplySite fullApply) { if (calleeEffects.summarizeCall(fullApply)) return; auto callees = BCA->getCalleeList(fullApply); 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. fullApply.getOrigCalleeType()->isCalleeConsumed()) { calleeEffects.setWorstEffects(); return; } // We can see all the callees, so merge the effects from all of them. for (auto *callee : callees) calleeEffects.mergeFrom(getEffects(callee)); }
// Start with the substitutions from the apply. // Try to propagate them to find out the real substitutions required // to invoke the method. static void getSubstitutionsForCallee(SILModule &M, CanSILFunctionType baseCalleeType, CanType derivedSelfType, FullApplySite AI, SmallVectorImpl<Substitution> &newSubs) { // If the base method is not polymorphic, no substitutions are required, // even if we originally had substitutions for calling the derived method. if (!baseCalleeType->isPolymorphic()) return; auto derivedClass = derivedSelfType; if (auto metatypeType = dyn_cast<MetatypeType>(derivedClass)) derivedClass = CanType(metatypeType->getInstanceType()); SubstitutionMap subMap; if (auto origCalleeSig = AI.getOrigCalleeType()->getGenericSignature()) { auto calleeSelfType = AI.getSubstCalleeType()->getSelfParameter().getType(); if (auto metatypeType = dyn_cast<MetatypeType>(calleeSelfType)) calleeSelfType = CanType(metatypeType->getInstanceType()); auto *calleeClassDecl = calleeSelfType->getClassOrBoundGenericClass(); assert(calleeClassDecl && "self is not a class type"); auto origSubs = AI.getSubstitutions(); // Add generic parameters from the method itself, ignoring any generic // parameters from the derived class. unsigned minDepth = 0; if (auto derivedClassSig = calleeClassDecl->getGenericSignatureOfContext()) minDepth = derivedClassSig->getGenericParams().back()->getDepth() + 1; for (auto depTy : origCalleeSig->getAllDependentTypes()) { // Grab the next substitution. auto sub = origSubs.front(); origSubs = origSubs.slice(1); // If the dependent type doesn't contain any generic parameter with // a depth of at least the minimum, skip this type. auto canTy = depTy->getCanonicalType(); auto hasInnerGenericParameter = [minDepth](Type type) -> bool { if (auto gp = type->getAs<GenericTypeParamType>()) { return gp->getDepth() >= minDepth; } return false; }; if (!Type(canTy.getPointer()).findIf(hasInnerGenericParameter)) continue; // Otherwise, record the replacement and conformances for the mapped // type. subMap.addSubstitution(canTy, sub.getReplacement()); subMap.addConformances(canTy, sub.getConformances()); } assert(origSubs.empty()); } // Add any generic substitutions for the base class. auto baseSelfType = baseCalleeType->getSelfParameter().getType(); if (auto metatypeType = dyn_cast<MetatypeType>(baseSelfType)) baseSelfType = CanType(metatypeType->getInstanceType()); auto *baseClassDecl = baseSelfType.getClassOrBoundGenericClass(); assert(baseClassDecl && "not a class method"); if (auto baseClassSig = baseClassDecl->getGenericSignatureOfContext()) { // Compute the type of the base class, starting from the // derived class type and the type of the method's self // parameter. auto baseClass = derivedClass->getSuperclassForDecl(baseClassDecl, nullptr) ->getCanonicalType(); auto baseClassSubs = baseClass->gatherAllSubstitutions( M.getSwiftModule(), nullptr); // Decompose the base class substitutions, adding them to the same // substitution maps as above. baseClassSig->getSubstitutionMap(baseClassSubs, subMap); } // Build the new substitutions using the base method signature. auto baseCalleeSig = baseCalleeType->getGenericSignature(); baseCalleeSig->getSubstitutions(subMap, newSubs); }