Skip to content

Commit 730a60f

Browse files
committed
AST: Introduce ClassDecl::hasResilientMetadata()
1 parent 2f4a995 commit 730a60f

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
@@ -3584,6 +3584,17 @@ class ClassDecl final : public NominalTypeDecl {
35843584
return SourceRange(ClassLoc, getBraces().End);
35853585
}
35863586

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

lib/AST/Decl.cpp

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

3317+
bool ClassDecl::hasResilientMetadata() const {
3318+
// Imported classes don't have a vtable, etc, at all.
3319+
if (hasClangNode())
3320+
return false;
3321+
3322+
// If the module is not resilient, neither is the class metadata.
3323+
if (getParentModule()->getResilienceStrategy()
3324+
!= ResilienceStrategy::Resilient)
3325+
return false;
3326+
3327+
// If the class is not public, we can't use it outside the module at all.
3328+
if (!getFormalAccessScope(/*useDC=*/nullptr,
3329+
/*treatUsableFromInlineAsPublic=*/true).isPublic())
3330+
return false;
3331+
3332+
// Otherwise we access metadata members, such as vtable entries, resiliently.
3333+
return true;
3334+
}
3335+
3336+
bool ClassDecl::hasResilientMetadata(ModuleDecl *M,
3337+
ResilienceExpansion expansion) const {
3338+
switch (expansion) {
3339+
case ResilienceExpansion::Minimal:
3340+
return hasResilientMetadata();
3341+
case ResilienceExpansion::Maximal:
3342+
return M != getModuleContext() && hasResilientMetadata();
3343+
}
3344+
llvm_unreachable("bad resilience expansion");
3345+
}
3346+
33173347
DestructorDecl *ClassDecl::getDestructor() {
33183348
auto results = lookupDirect(DeclBaseName::createDestructor());
33193349
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)