bool OwnershipChecker::checkValue(SILValue value) { regularUsers.clear(); lifetimeEndingUsers.clear(); liveBlocks.clear(); // Since we do not have SILUndef, we now know that getFunction() should return // a real function. Assert in case this assumption is no longer true. SILFunction *f = value->getFunction(); assert(f && "Instructions and arguments should have a function"); // If the given function has unqualified ownership, there is nothing further // to verify. if (!f->hasQualifiedOwnership()) return false; ErrorBehaviorKind errorBehavior(ErrorBehaviorKind::ReturnFalse); SILValueOwnershipChecker checker(mod, deadEndBlocks, value, errorBehavior, liveBlocks); if (!checker.check()) { return false; } // TODO: Make this more efficient. copy(checker.getRegularUsers(), std::back_inserter(regularUsers)); copy(checker.getLifetimeEndingUsers(), std::back_inserter(lifetimeEndingUsers)); return true; }
void SILValue::verifyOwnership(SILModule &mod, DeadEndBlocks *deadEndBlocks) const { #ifndef NDEBUG if (DisableOwnershipVerification) return; // Since we do not have SILUndef, we now know that getFunction() should return // a real function. Assert in case this assumption is no longer true. SILFunction *f = (*this)->getFunction(); assert(f && "Instructions and arguments should have a function"); // If the given function has unqualified ownership or we have been asked by // the user not to verify this function, there is nothing to verify. if (!f->hasQualifiedOwnership() || !f->shouldVerifyOwnership()) return; assert(getOwnershipKind() != ValueOwnershipKind::Any && "No values should have any ownership anymore"); ErrorBehaviorKind errorBehavior; if (IsSILOwnershipVerifierTestingEnabled) { errorBehavior = ErrorBehaviorKind::PrintMessageAndReturnFalse; } else { errorBehavior = ErrorBehaviorKind::PrintMessageAndAssert; } llvm::SmallPtrSet<SILBasicBlock *, 32> liveBlocks; if (deadEndBlocks) { SILValueOwnershipChecker(mod, *deadEndBlocks, *this, errorBehavior, liveBlocks) .check(); } else { DeadEndBlocks deadEndBlocks(f); SILValueOwnershipChecker(mod, deadEndBlocks, *this, errorBehavior, liveBlocks) .check(); } #endif }
/// In this function we create the actual cloned function and its proper cloned /// type. But we do not create any body. This implies that the creation of the /// actual arguments in the function is in populateCloned. /// /// \arg PAUser The function that is being passed the partial apply. /// \arg PAI The partial apply that is being passed to PAUser. /// \arg ClosureIndex The index of the partial apply in PAUser's function /// signature. /// \arg ClonedName The name of the cloned function that we will create. SILFunction * ClosureSpecCloner::initCloned(SILOptFunctionBuilder &FunctionBuilder, const CallSiteDescriptor &CallSiteDesc, StringRef ClonedName) { SILFunction *ClosureUser = CallSiteDesc.getApplyCallee(); // This is the list of new interface parameters of the cloned function. llvm::SmallVector<SILParameterInfo, 4> NewParameterInfoList; // First add to NewParameterInfoList all of the SILParameterInfo in the // original function except for the closure. CanSILFunctionType ClosureUserFunTy = ClosureUser->getLoweredFunctionType(); auto ClosureUserConv = ClosureUser->getConventions(); unsigned Index = ClosureUserConv.getSILArgIndexOfFirstParam(); for (auto ¶m : ClosureUserConv.getParameters()) { if (Index != CallSiteDesc.getClosureIndex()) NewParameterInfoList.push_back(param); ++Index; } // Then add any arguments that are captured in the closure to the function's // argument type. Since they are captured, we need to pass them directly into // the new specialized function. SILFunction *ClosedOverFun = CallSiteDesc.getClosureCallee(); auto ClosedOverFunConv = ClosedOverFun->getConventions(); SILModule &M = ClosureUser->getModule(); // Captured parameters are always appended to the function signature. If the // type of the captured argument is: // - direct and trivial, pass the argument as Direct_Unowned. // - direct and non-trivial, pass the argument as Direct_Owned. // - indirect, pass the argument using the same parameter convention as in the // original closure. // // We use the type of the closure here since we allow for the closure to be an // external declaration. unsigned NumTotalParams = ClosedOverFunConv.getNumParameters(); unsigned NumNotCaptured = NumTotalParams - CallSiteDesc.getNumArguments(); for (auto &PInfo : ClosedOverFunConv.getParameters().slice(NumNotCaptured)) { ParameterConvention ParamConv; if (PInfo.isFormalIndirect()) { ParamConv = PInfo.getConvention(); assert(!SILModuleConventions(M).useLoweredAddresses() || ParamConv == ParameterConvention::Indirect_Inout || ParamConv == ParameterConvention::Indirect_InoutAliasable); } else { ParamConv = ClosedOverFunConv.getSILType(PInfo).isTrivial(M) ? ParameterConvention::Direct_Unowned : ParameterConvention::Direct_Owned; } SILParameterInfo NewPInfo(PInfo.getType(), ParamConv); NewParameterInfoList.push_back(NewPInfo); } // The specialized function is always a thin function. This is important // because we may add additional parameters after the Self parameter of // witness methods. In this case the new function is not a method anymore. auto ExtInfo = ClosureUserFunTy->getExtInfo(); ExtInfo = ExtInfo.withRepresentation(SILFunctionTypeRepresentation::Thin); auto ClonedTy = SILFunctionType::get( ClosureUserFunTy->getGenericSignature(), ExtInfo, ClosureUserFunTy->getCoroutineKind(), ClosureUserFunTy->getCalleeConvention(), NewParameterInfoList, ClosureUserFunTy->getYields(), ClosureUserFunTy->getResults(), ClosureUserFunTy->getOptionalErrorResult(), M.getASTContext()); // We make this function bare so we don't have to worry about decls in the // SILArgument. auto *Fn = FunctionBuilder.createFunction( // It's important to use a shared linkage for the specialized function // and not the original linkage. // Otherwise the new function could have an external linkage (in case the // original function was de-serialized) and would not be code-gen'd. // It's also important to disconnect this specialized function from any // classes (the classSubclassScope), because that may incorrectly // influence the linkage. getSpecializedLinkage(ClosureUser, ClosureUser->getLinkage()), ClonedName, ClonedTy, ClosureUser->getGenericEnvironment(), ClosureUser->getLocation(), IsBare, ClosureUser->isTransparent(), CallSiteDesc.isSerialized(), IsNotDynamic, ClosureUser->getEntryCount(), ClosureUser->isThunk(), /*classSubclassScope=*/SubclassScope::NotApplicable, ClosureUser->getInlineStrategy(), ClosureUser->getEffectsKind(), ClosureUser, ClosureUser->getDebugScope()); if (!ClosureUser->hasQualifiedOwnership()) { Fn->setUnqualifiedOwnership(); } for (auto &Attr : ClosureUser->getSemanticsAttrs()) Fn->addSemanticsAttr(Attr); return Fn; }