/// \brief True if the function should have its body serialized. bool SILDeclRef::isFragile() const { DeclContext *dc; if (auto closure = getAbstractClosureExpr()) dc = closure->getLocalContext(); else { dc = getDecl()->getInnermostDeclContext(); // Enum case constructors are serialized if the enum is @_versioned // or public. if (isEnumElement()) if (cast<EnumDecl>(dc)->getEffectiveAccess() >= Accessibility::Public) return true; // The allocating entry point for designated initializers are serialized // if the class is @_versioned or public. if (kind == SILDeclRef::Kind::Allocator) { auto *ctor = cast<ConstructorDecl>(getDecl()); if (ctor->isDesignatedInit() && ctor->getDeclContext()->getAsClassOrClassExtensionContext()) { if (ctor->getEffectiveAccess() >= Accessibility::Public && !ctor->hasClangNode()) return true; } } } // Otherwise, ask the AST if we're inside an @_inlineable context. return (dc->getResilienceExpansion() == ResilienceExpansion::Minimal); }
/// \brief True if the function should have its body serialized. bool SILDeclRef::isFragile() const { DeclContext *dc; if (auto closure = getAbstractClosureExpr()) dc = closure->getLocalContext(); else dc = getDecl()->getInnermostDeclContext(); // This is stupid return (dc->getResilienceExpansion() == ResilienceExpansion::Minimal); }
/// \brief True if the function should have its body serialized. IsSerialized_t SILDeclRef::isSerialized() const { DeclContext *dc; if (auto closure = getAbstractClosureExpr()) dc = closure->getLocalContext(); else { auto *d = getDecl(); // Default argument generators are serialized if the function was // type-checked in Swift 4 mode. if (kind == SILDeclRef::Kind::DefaultArgGenerator) { auto *afd = cast<AbstractFunctionDecl>(d); switch (afd->getDefaultArgumentResilienceExpansion()) { case ResilienceExpansion::Minimal: return IsSerialized; case ResilienceExpansion::Maximal: return IsNotSerialized; } } // 'read' and 'modify' accessors synthesized on-demand are serialized if // visible outside the module. if (auto fn = dyn_cast<FuncDecl>(d)) if (!isClangImported() && fn->hasForcedStaticDispatch() && fn->getEffectiveAccess() >= AccessLevel::Public) return IsSerialized; dc = getDecl()->getInnermostDeclContext(); // Enum element constructors are serialized if the enum is // @usableFromInline or public. if (isEnumElement()) if (d->getEffectiveAccess() >= AccessLevel::Public) return IsSerialized; // Currying thunks are serialized if referenced from an inlinable // context -- Sema's semantic checks ensure the serialization of // such a thunk is valid, since it must in turn reference a public // symbol, or dispatch via class_method or witness_method. if (isCurried) if (d->getEffectiveAccess() >= AccessLevel::Public) return IsSerializable; if (isForeignToNativeThunk()) return IsSerializable; // The allocating entry point for designated initializers are serialized // if the class is @usableFromInline or public. if (kind == SILDeclRef::Kind::Allocator) { auto *ctor = cast<ConstructorDecl>(d); if (ctor->isDesignatedInit() && ctor->getDeclContext()->getSelfClassDecl()) { if (ctor->getEffectiveAccess() >= AccessLevel::Public && !ctor->hasClangNode()) return IsSerialized; } } // Stored property initializers are inlinable if the type is explicitly // marked as @_fixed_layout. if (isStoredPropertyInitializer()) { auto *nominal = cast<NominalTypeDecl>(d->getDeclContext()); auto scope = nominal->getFormalAccessScope(/*useDC=*/nullptr, /*treatUsableFromInlineAsPublic=*/true); if (!scope.isPublic()) return IsNotSerialized; if (nominal->isFormallyResilient()) return IsNotSerialized; return IsSerialized; } } // Declarations imported from Clang modules are serialized if // referenced from an inlinable context. if (isClangImported()) return IsSerializable; // Otherwise, ask the AST if we're inside an @inlinable context. if (dc->getResilienceExpansion() == ResilienceExpansion::Minimal) return IsSerialized; return IsNotSerialized; }
/// True if the function should have its body serialized. IsSerialized_t SILDeclRef::isSerialized() const { DeclContext *dc; if (auto closure = getAbstractClosureExpr()) { dc = closure->getLocalContext(); // Otherwise, ask the AST if we're inside an @inlinable context. if (dc->getResilienceExpansion() == ResilienceExpansion::Minimal) { if (isForeign) return IsSerializable; return IsSerialized; } return IsNotSerialized; } if (isIVarInitializerOrDestroyer()) return IsNotSerialized; auto *d = getDecl(); // Default argument generators are serialized if the containing // declaration is public. if (isDefaultArgGenerator()) { ResilienceExpansion expansion; if (auto *EED = dyn_cast<EnumElementDecl>(d)) { expansion = EED->getDefaultArgumentResilienceExpansion(); } else { expansion = cast<AbstractFunctionDecl>(d) ->getDefaultArgumentResilienceExpansion(); } switch (expansion) { case ResilienceExpansion::Minimal: return IsSerialized; case ResilienceExpansion::Maximal: return IsNotSerialized; } } // Stored property initializers are inlinable if the type is explicitly // marked as @_fixed_layout. if (isStoredPropertyInitializer()) { auto *nominal = cast<NominalTypeDecl>(d->getDeclContext()); auto scope = nominal->getFormalAccessScope(/*useDC=*/nullptr, /*treatUsableFromInlineAsPublic=*/true); if (!scope.isPublic()) return IsNotSerialized; if (nominal->isFormallyResilient()) return IsNotSerialized; return IsSerialized; } // Note: if 'd' is a function, then 'dc' is the function itself, not // its parent context. dc = d->getInnermostDeclContext(); // Local functions are serializable if their parent function is // serializable. if (d->getDeclContext()->isLocalContext()) { if (dc->getResilienceExpansion() == ResilienceExpansion::Minimal) return IsSerializable; return IsNotSerialized; } // Anything else that is not public is not serializable. if (d->getEffectiveAccess() < AccessLevel::Public) return IsNotSerialized; // 'read' and 'modify' accessors synthesized on-demand are serialized if // visible outside the module. if (auto fn = dyn_cast<FuncDecl>(d)) if (!isClangImported() && fn->hasForcedStaticDispatch()) return IsSerialized; // Enum element constructors are serializable if the enum is // @usableFromInline or public. if (isEnumElement()) return IsSerializable; // Currying thunks are serialized if referenced from an inlinable // context -- Sema's semantic checks ensure the serialization of // such a thunk is valid, since it must in turn reference a public // symbol, or dispatch via class_method or witness_method. if (isCurried) return IsSerializable; if (isForeignToNativeThunk()) return IsSerializable; // The allocating entry point for designated initializers are serialized // if the class is @usableFromInline or public. if (kind == SILDeclRef::Kind::Allocator) { auto *ctor = cast<ConstructorDecl>(d); if (ctor->isDesignatedInit() && ctor->getDeclContext()->getSelfClassDecl()) { if (!ctor->hasClangNode()) return IsSerialized; } } if (isForeign) { // @objc thunks for methods are not serializable since they're only // referenced from the method table. if (d->getDeclContext()->isTypeContext()) return IsNotSerialized; // @objc thunks for top-level functions are serializable since they're // referenced from @convention(c) conversions inside inlinable // functions. return IsSerializable; } // Declarations imported from Clang modules are serialized if // referenced from an inlinable context. if (isClangImported()) return IsSerializable; // Otherwise, ask the AST if we're inside an @inlinable context. if (dc->getResilienceExpansion() == ResilienceExpansion::Minimal) return IsSerialized; return IsNotSerialized; }