Skip to content

Commit 4289f76

Browse files
committed
AST: Introduce ClassDecl::hasResilientMetadata()
1 parent 0902741 commit 4289f76

File tree

4 files changed

+56
-0
lines changed

4 files changed

+56
-0
lines changed

include/swift/AST/Decl.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3589,6 +3589,17 @@ class ClassDecl final : public NominalTypeDecl {
35893589
return SourceRange(ClassLoc, getBraces().End);
35903590
}
35913591

3592+
/// Determine whether the member area of this class's metadata (which consists
3593+
/// of field offsets and vtable entries) is to be considered opaque by clients.
3594+
///
3595+
/// Note that even @_fixed_layout classes have resilient metadata if they are
3596+
/// in a resilient module.
3597+
bool hasResilientMetadata() const;
3598+
3599+
/// Determine whether this class has resilient metadata when accessed from the
3600+
/// given module and resilience expansion.
3601+
bool hasResilientMetadata(ModuleDecl *M, ResilienceExpansion expansion) const;
3602+
35923603
/// Determine whether this class has a superclass.
35933604
bool hasSuperclass() const { return (bool)getSuperclassDecl(); }
35943605

lib/AST/Decl.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3355,6 +3355,36 @@ ClassDecl::ClassDecl(SourceLoc ClassLoc, Identifier Name, SourceLoc NameLoc,
33553355
Bits.ClassDecl.HasMissingVTableEntries = 0;
33563356
}
33573357

3358+
bool ClassDecl::hasResilientMetadata() const {
3359+
// Imported classes don't have a vtable, etc, at all.
3360+
if (hasClangNode())
3361+
return false;
3362+
3363+
// If the module is not resilient, neither is the class metadata.
3364+
if (getParentModule()->getResilienceStrategy()
3365+
!= ResilienceStrategy::Resilient)
3366+
return false;
3367+
3368+
// If the class is not public, we can't use it outside the module at all.
3369+
if (!getFormalAccessScope(/*useDC=*/nullptr,
3370+
/*treatUsableFromInlineAsPublic=*/true).isPublic())
3371+
return false;
3372+
3373+
// Otherwise we access metadata members, such as vtable entries, resiliently.
3374+
return true;
3375+
}
3376+
3377+
bool ClassDecl::hasResilientMetadata(ModuleDecl *M,
3378+
ResilienceExpansion expansion) const {
3379+
switch (expansion) {
3380+
case ResilienceExpansion::Minimal:
3381+
return hasResilientMetadata();
3382+
case ResilienceExpansion::Maximal:
3383+
return M != getModuleContext() && hasResilientMetadata();
3384+
}
3385+
llvm_unreachable("bad resilience expansion");
3386+
}
3387+
33583388
DestructorDecl *ClassDecl::getDestructor() {
33593389
auto results = lookupDirect(DeclBaseName::createDestructor());
33603390
assert(!results.empty() && "Class without destructor?");

lib/IRGen/GenDecl.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3859,6 +3859,20 @@ bool IRGenModule::isResilient(NominalTypeDecl *D, ResilienceExpansion expansion)
38593859
return D->isResilient(getSwiftModule(), expansion);
38603860
}
38613861

3862+
/// Do we have to use resilient access patterns when working with this
3863+
/// class?
3864+
///
3865+
/// For classes, this means that virtual method calls use dispatch thunks
3866+
/// rather than accessing metadata members directly.
3867+
bool IRGenModule::hasResilientMetadata(ClassDecl *D,
3868+
ResilienceExpansion expansion) {
3869+
if (expansion == ResilienceExpansion::Maximal &&
3870+
Types.getLoweringMode() == TypeConverter::Mode::CompletelyFragile) {
3871+
return false;
3872+
}
3873+
return D->hasResilientMetadata(getSwiftModule(), expansion);
3874+
}
3875+
38623876
// The most general resilience expansion where the given declaration is visible.
38633877
ResilienceExpansion
38643878
IRGenModule::getResilienceExpansionForAccess(NominalTypeDecl *decl) {

lib/IRGen/IRGenModule.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -784,6 +784,7 @@ class IRGenModule {
784784
clang::CodeGen::CodeGenModule &getClangCGM() const;
785785

786786
bool isResilient(NominalTypeDecl *decl, ResilienceExpansion expansion);
787+
bool hasResilientMetadata(ClassDecl *decl, ResilienceExpansion expansion);
787788
ResilienceExpansion getResilienceExpansionForAccess(NominalTypeDecl *decl);
788789
ResilienceExpansion getResilienceExpansionForLayout(NominalTypeDecl *decl);
789790
ResilienceExpansion getResilienceExpansionForLayout(SILGlobalVariable *var);

0 commit comments

Comments
 (0)