ManagedValue SILGenBuilder::createEnum(SILLocation loc, ManagedValue payload, EnumElementDecl *decl, SILType type) { SILValue result = createEnum(loc, payload.forward(SGF), decl, type); if (result.getOwnershipKind() != ValueOwnershipKind::Owned) return ManagedValue::forUnmanaged(result); return SGF.emitManagedRValueWithCleanup(result); }
SILValue SILInliner::borrowFunctionArgument(SILValue callArg, FullApplySite AI) { if (!AI.getFunction()->hasQualifiedOwnership() || callArg.getOwnershipKind() != ValueOwnershipKind::Owned) { return callArg; } auto *borrow = getBuilder().createBeginBorrow(AI.getLoc(), callArg); if (auto *tryAI = dyn_cast<TryApplyInst>(AI)) { SILBuilder returnBuilder(tryAI->getNormalBB()->begin()); returnBuilder.createEndBorrow(AI.getLoc(), borrow, callArg); SILBuilder throwBuilder(tryAI->getErrorBB()->begin()); throwBuilder.createEndBorrow(AI.getLoc(), borrow, callArg); } else { SILBuilder returnBuilder(std::next(AI.getInstruction()->getIterator())); returnBuilder.createEndBorrow(AI.getLoc(), borrow, callArg); } return borrow; }
void SILInstruction::verifyOperandOwnership() const { #ifndef NDEBUG if (DisableOwnershipVerification) return; if (isStaticInitializerInst()) return; // If SILOwnership is not enabled, do not perform verification. if (!getModule().getOptions().VerifySILOwnership) return; // 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 (!getFunction()->hasOwnership() || !getFunction()->shouldVerifyOwnership()) return; // If we are testing the verifier, bail so we only print errors once when // performing a full verification, instead of additionally in the SILBuilder. if (IsSILOwnershipVerifierTestingEnabled) return; // If this is a terminator instruction, do not verify in SILBuilder. This is // because when building a new function, one must create the destination block // first which is an unnatural pattern and pretty brittle. if (isa<TermInst>(this)) return; ErrorBehaviorKind errorBehavior; if (IsSILOwnershipVerifierTestingEnabled) { errorBehavior = ErrorBehaviorKind::PrintMessageAndReturnFalse; } else { errorBehavior = ErrorBehaviorKind::PrintMessageAndAssert; } for (const Operand &op : getAllOperands()) { // Skip type dependence operands. if (isTypeDependentOperand(op)) continue; SILValue opValue = op.get(); auto operandOwnershipKindMap = op.getOwnershipKindMap(); auto valueOwnershipKind = opValue.getOwnershipKind(); if (operandOwnershipKindMap.canAcceptKind(valueOwnershipKind)) continue; if (errorBehavior.shouldPrintMessage()) { llvm::errs() << "Found an operand with a value that is not compatible " "with the operand's operand ownership kind map.\n"; llvm::errs() << "Value: " << opValue; llvm::errs() << "Value Ownership Kind: " << valueOwnershipKind << "\n"; llvm::errs() << "Instruction: " << *this; llvm::errs() << "Operand Ownership Kind Map: " << operandOwnershipKindMap; } if (errorBehavior.shouldReturnFalse()) continue; assert(errorBehavior.shouldAssert() && "At this point, we are expected to assert"); llvm_unreachable("triggering standard assertion failure routine"); } #endif }
void SILGenFunction::emitDestroyingDestructor(DestructorDecl *dd) { MagicFunctionName = DeclName(SGM.M.getASTContext().getIdentifier("deinit")); RegularLocation Loc(dd); if (dd->isImplicit()) Loc.markAutoGenerated(); auto cd = cast<ClassDecl>(dd->getDeclContext()); SILValue selfValue = emitSelfDecl(dd->getImplicitSelfDecl()); // Create a basic block to jump to for the implicit destruction behavior // of releasing the elements and calling the superclass destructor. // We won't actually emit the block until we finish with the destructor body. prepareEpilog(Type(), false, CleanupLocation::get(Loc)); emitProfilerIncrement(dd->getBody()); // Emit the destructor body. emitStmt(dd->getBody()); Optional<SILValue> maybeReturnValue; SILLocation returnLoc(Loc); std::tie(maybeReturnValue, returnLoc) = emitEpilogBB(Loc); if (!maybeReturnValue) return; auto cleanupLoc = CleanupLocation::get(Loc); // If we have a superclass, invoke its destructor. SILValue resultSelfValue; SILType objectPtrTy = SILType::getNativeObjectType(F.getASTContext()); SILType classTy = selfValue->getType(); if (cd->hasSuperclass()) { Type superclassTy = dd->mapTypeIntoContext(cd->getSuperclass()); ClassDecl *superclass = superclassTy->getClassOrBoundGenericClass(); auto superclassDtorDecl = superclass->getDestructor(); SILDeclRef dtorConstant = SILDeclRef(superclassDtorDecl, SILDeclRef::Kind::Destroyer); SILType baseSILTy = getLoweredLoadableType(superclassTy); SILValue baseSelf = B.createUpcast(cleanupLoc, selfValue, baseSILTy); ManagedValue dtorValue; SILType dtorTy; auto subMap = superclassTy->getContextSubstitutionMap(SGM.M.getSwiftModule(), superclass); std::tie(dtorValue, dtorTy) = emitSiblingMethodRef(cleanupLoc, baseSelf, dtorConstant, subMap); resultSelfValue = B.createApply(cleanupLoc, dtorValue.forward(*this), dtorTy, objectPtrTy, subMap, baseSelf); } else { resultSelfValue = selfValue; } ArgumentScope S(*this, Loc); ManagedValue borrowedValue = ManagedValue::forUnmanaged(resultSelfValue).borrow(*this, cleanupLoc); if (classTy != borrowedValue.getType()) { borrowedValue = B.createUncheckedRefCast(cleanupLoc, borrowedValue, classTy); } // Release our members. emitClassMemberDestruction(borrowedValue, cd, cleanupLoc); S.pop(); if (resultSelfValue->getType() != objectPtrTy) { resultSelfValue = B.createUncheckedRefCast(cleanupLoc, resultSelfValue, objectPtrTy); } if (resultSelfValue.getOwnershipKind() != ValueOwnershipKind::Owned) { assert(resultSelfValue.getOwnershipKind() == ValueOwnershipKind::Guaranteed); resultSelfValue = B.createUncheckedOwnershipConversion( cleanupLoc, resultSelfValue, ValueOwnershipKind::Owned); } B.createReturn(returnLoc, resultSelfValue); }
void SILGenFunction::emitObjCDestructor(SILDeclRef dtor) { auto dd = cast<DestructorDecl>(dtor.getDecl()); auto cd = cast<ClassDecl>(dd->getDeclContext()); MagicFunctionName = DeclName(SGM.M.getASTContext().getIdentifier("deinit")); RegularLocation loc(dd); if (dd->isImplicit()) loc.markAutoGenerated(); SILValue selfValue = emitSelfDecl(dd->getImplicitSelfDecl()); // Create a basic block to jump to for the implicit destruction behavior // of releasing the elements and calling the superclass destructor. // We won't actually emit the block until we finish with the destructor body. prepareEpilog(Type(), false, CleanupLocation::get(loc)); emitProfilerIncrement(dd->getBody()); // Emit the destructor body. emitStmt(dd->getBody()); Optional<SILValue> maybeReturnValue; SILLocation returnLoc(loc); std::tie(maybeReturnValue, returnLoc) = emitEpilogBB(loc); if (!maybeReturnValue) return; auto cleanupLoc = CleanupLocation::get(loc); // Note: the ivar destroyer is responsible for destroying the // instance variables before the object is actually deallocated. // Form a reference to the superclass -dealloc. Type superclassTy = dd->mapTypeIntoContext(cd->getSuperclass()); assert(superclassTy && "Emitting Objective-C -dealloc without superclass?"); ClassDecl *superclass = superclassTy->getClassOrBoundGenericClass(); auto superclassDtorDecl = superclass->getDestructor(); auto superclassDtor = SILDeclRef(superclassDtorDecl, SILDeclRef::Kind::Deallocator) .asForeign(); auto superclassDtorType = SGM.Types.getConstantType(superclassDtor); SILValue superclassDtorValue = B.createObjCSuperMethod( cleanupLoc, selfValue, superclassDtor, superclassDtorType); // Call the superclass's -dealloc. SILType superclassSILTy = getLoweredLoadableType(superclassTy); SILValue superSelf = B.createUpcast(cleanupLoc, selfValue, superclassSILTy); assert(superSelf.getOwnershipKind() == ValueOwnershipKind::Owned); auto subMap = superclassTy->getContextSubstitutionMap(SGM.M.getSwiftModule(), superclass); auto substDtorType = superclassDtorType.substGenericArgs(SGM.M, subMap); CanSILFunctionType substFnType = substDtorType.castTo<SILFunctionType>(); SILFunctionConventions dtorConv(substFnType, SGM.M); assert(substFnType->getSelfParameter().getConvention() == ParameterConvention::Direct_Unowned && "Objective C deinitializing destructor takes self as unowned"); B.createApply(cleanupLoc, superclassDtorValue, substDtorType, dtorConv.getSILResultType(), subMap, superSelf); // We know that the givne value came in at +1, but we pass the relevant value // as unowned to the destructor. Create a fake balance for the verifier to be // happy. B.createEndLifetime(cleanupLoc, superSelf); // Return. B.createReturn(returnLoc, emitEmptyTuple(cleanupLoc)); }
bool swift::isValueAddressOrTrivial(SILValue v, SILModule &m) { return v->getType().isAddress() || v.getOwnershipKind() == ValueOwnershipKind::Trivial || v.getOwnershipKind() == ValueOwnershipKind::Any; }