//===--- SILGenDestructor.cpp - SILGen for destructors --------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See http://swift.org/LICENSE.txt for license information // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// #include "SILGenFunction.h" #include "RValue.h" #include "swift/AST/AST.h" #include "swift/SIL/TypeLowering.h" using namespace swift; using namespace Lowering; void SILGenFunction::emitDestroyingDestructor(DestructorDecl *dd) { MagicFunctionName = DeclName(SGM.M.getASTContext().getIdentifier("deinit")); RegularLocation Loc(dd); if (dd->isImplicit()) Loc.markAutoGenerated(); auto cd = cast(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 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()); if (cd->hasSuperclass()) { Type superclassTy = ArchetypeBuilder::mapTypeIntoContext(dd, 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; ArrayRef subs = superclassTy->gatherAllSubstitutions(SGM.M.getSwiftModule(), nullptr); std::tie(dtorValue, dtorTy, subs) = emitSiblingMethodRef(cleanupLoc, baseSelf, dtorConstant, subs); resultSelfValue = B.createApply(cleanupLoc, dtorValue.forward(*this), dtorTy, objectPtrTy, subs, baseSelf); } else { resultSelfValue = B.createUncheckedRefCast(cleanupLoc, selfValue, objectPtrTy); } // Release our members. emitClassMemberDestruction(selfValue, cd, cleanupLoc); B.createReturn(returnLoc, resultSelfValue); } void SILGenFunction::emitDeallocatingDestructor(DestructorDecl *dd) { MagicFunctionName = DeclName(SGM.M.getASTContext().getIdentifier("deinit")); // The deallocating destructor is always auto-generated. RegularLocation loc(dd); loc.markAutoGenerated(); // Emit the prolog. auto cd = cast(dd->getDeclContext()); SILValue selfValue = emitSelfDecl(dd->getImplicitSelfDecl()); // Form a reference to the destroying destructor. SILDeclRef dtorConstant(dd, SILDeclRef::Kind::Destroyer); auto classTy = cd->getDeclaredTypeInContext(); ManagedValue dtorValue; SILType dtorTy; ArrayRef subs = classTy->gatherAllSubstitutions(SGM.M.getSwiftModule(), nullptr); std::tie(dtorValue, dtorTy, subs) = emitSiblingMethodRef(loc, selfValue, dtorConstant, subs); // Call the destroying destructor. SILType objectPtrTy = SILType::getNativeObjectType(F.getASTContext()); selfValue = B.createApply(loc, dtorValue.forward(*this), dtorTy, objectPtrTy, subs, selfValue); // Deallocate the object. selfValue = B.createUncheckedRefCast(loc, selfValue, getLoweredType(classTy)); B.createDeallocRef(loc, selfValue, false); // Return. B.createReturn(loc, emitEmptyTuple(loc)); } void SILGenFunction::emitIVarDestroyer(SILDeclRef ivarDestroyer) { auto cd = cast(ivarDestroyer.getDecl()); RegularLocation loc(cd); loc.markAutoGenerated(); SILValue selfValue = emitSelfDecl(cd->getDestructor()->getImplicitSelfDecl()); auto cleanupLoc = CleanupLocation::get(loc); prepareEpilog(TupleType::getEmpty(getASTContext()), false, cleanupLoc); emitClassMemberDestruction(selfValue, cd, cleanupLoc); B.createReturn(loc, emitEmptyTuple(loc)); emitEpilog(loc); } void SILGenFunction::emitClassMemberDestruction(SILValue selfValue, ClassDecl *cd, CleanupLocation cleanupLoc) { for (VarDecl *vd : cd->getStoredProperties()) { const TypeLowering &ti = getTypeLowering(vd->getType()); if (!ti.isTrivial()) { SILValue addr = B.createRefElementAddr(cleanupLoc, selfValue, vd, ti.getLoweredType().getAddressType()); B.emitDestroyAddrAndFold(cleanupLoc, addr); } } } void SILGenFunction::emitObjCDestructor(SILDeclRef dtor) { auto dd = cast(dtor.getDecl()); auto cd = cast(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)); // Emit the destructor body. emitStmt(dd->getBody()); Optional 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 = ArchetypeBuilder::mapTypeIntoContext(dd, cd->getSuperclass()); assert(superclassTy && "Emitting Objective-C -dealloc without superclass?"); ClassDecl *superclass = superclassTy->getClassOrBoundGenericClass(); auto superclassDtorDecl = superclass->getDestructor(); SILDeclRef superclassDtor(superclassDtorDecl, SILDeclRef::Kind::Deallocator, SILDeclRef::ConstructAtBestResilienceExpansion, SILDeclRef::ConstructAtNaturalUncurryLevel, /*isForeign=*/true); auto superclassDtorType = SGM.getConstantType(superclassDtor); SILValue superclassDtorValue = B.createSuperMethod( cleanupLoc, selfValue, superclassDtor, superclassDtorType); // Call the superclass's -dealloc. SILType superclassSILTy = getLoweredLoadableType(superclassTy); SILValue superSelf = B.createUpcast(cleanupLoc, selfValue, superclassSILTy); ArrayRef subs = superclassTy->gatherAllSubstitutions(SGM.M.getSwiftModule(), nullptr); auto substDtorType = superclassDtorType.castTo() ->substGenericArgs(SGM.M, SGM.M.getSwiftModule(), subs); B.createApply(cleanupLoc, superclassDtorValue, SILType::getPrimitiveObjectType(substDtorType), substDtorType->getSILResult(), subs, superSelf); // Return. B.createReturn(returnLoc, emitEmptyTuple(cleanupLoc)); }