Skip to content

Commit f243bc5

Browse files
authored
Merge pull request #26332 from slavapestov/tbdgen-protocol-cleanup
TBD: Use SILWitnessVisitor instead of baking in knowledge of witness table layout
2 parents 98ebfeb + 28f1bb9 commit f243bc5

File tree

2 files changed

+42
-69
lines changed

2 files changed

+42
-69
lines changed

include/swift/SIL/SILWitnessVisitor.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,12 @@ namespace swift {
3838
/// physical projection (if we decide to support that).
3939
///
4040
/// You must override the following methods:
41+
/// - addProtocolConformanceDescriptor()
4142
/// - addOutOfLineBaseProtocol()
42-
/// - addMethod()
43-
/// - addConstructor()
4443
/// - addAssociatedType()
44+
/// - addAssociatedConformance()
45+
/// - addMethod()
46+
/// - addPlaceholder()
4547

4648
template <class T> class SILWitnessVisitor : public ASTVisitor<T> {
4749
T &asDerived() { return *static_cast<T*>(this); }

lib/TBDGen/TBDGen.cpp

Lines changed: 38 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "swift/SIL/SILModule.h"
2929
#include "swift/SIL/SILVTableVisitor.h"
3030
#include "swift/SIL/SILWitnessTable.h"
31+
#include "swift/SIL/SILWitnessVisitor.h"
3132
#include "swift/SIL/TypeLowering.h"
3233
#include "llvm/ADT/StringSet.h"
3334
#include "llvm/Support/Error.h"
@@ -280,7 +281,7 @@ void TBDGenVisitor::visitAbstractStorageDecl(AbstractStorageDecl *ASD) {
280281

281282
// Explicitly look at each accessor here: see visitAccessorDecl.
282283
for (auto accessor : ASD->getAllAccessors()) {
283-
visitAbstractFunctionDecl(accessor);
284+
visitFuncDecl(accessor);
284285
}
285286
}
286287

@@ -365,16 +366,8 @@ void TBDGenVisitor::visitClassDecl(ClassDecl *CD) {
365366

366367
// Some members of classes get extra handling, beyond members of struct/enums,
367368
// so let's walk over them manually.
368-
for (auto *member : CD->getMembers()) {
369-
auto value = dyn_cast<ValueDecl>(member);
370-
if (!value)
371-
continue;
372-
373-
auto var = dyn_cast<VarDecl>(value);
374-
auto hasFieldOffset = var && var->hasStorage() && !var->isStatic();
375-
if (hasFieldOffset)
376-
addSymbol(LinkEntity::forFieldOffset(var));
377-
}
369+
for (auto *var : CD->getStoredProperties())
370+
addSymbol(LinkEntity::forFieldOffset(var));
378371

379372
visitNominalTypeDecl(CD);
380373

@@ -465,28 +458,6 @@ void TBDGenVisitor::visitExtensionDecl(ExtensionDecl *ED) {
465458
visit(member);
466459
}
467460

468-
/// Determine whether the protocol descriptor for the given protocol will
469-
/// contain any protocol requirements.
470-
static bool protocolDescriptorHasRequirements(ProtocolDecl *proto) {
471-
if (!proto->getRequirementSignature().empty())
472-
return true;
473-
474-
for (auto *member : proto->getMembers()) {
475-
if (auto func = dyn_cast<AbstractFunctionDecl>(member)) {
476-
if (SILDeclRef::requiresNewWitnessTableEntry(func))
477-
return true;
478-
}
479-
480-
if (auto assocType = dyn_cast<AssociatedTypeDecl>(member)) {
481-
if (assocType->getOverriddenDecls().empty()) {
482-
return true;
483-
}
484-
}
485-
}
486-
487-
return false;
488-
}
489-
490461
#ifndef NDEBUG
491462
static bool isValidProtocolMemberForTBDGen(const Decl *D) {
492463
switch (D->getKind()) {
@@ -530,45 +501,45 @@ void TBDGenVisitor::visitProtocolDecl(ProtocolDecl *PD) {
530501
if (!PD->isObjC()) {
531502
addSymbol(LinkEntity::forProtocolDescriptor(PD));
532503

533-
// If there are any requirements, emit a requirements base descriptor.
534-
if (protocolDescriptorHasRequirements(PD))
535-
addProtocolRequirementsBaseDescriptor(PD);
536-
537-
for (const auto &req : PD->getRequirementSignature()) {
538-
if (req.getKind() != RequirementKind::Conformance)
539-
continue;
540-
541-
if (req.getFirstType()->isEqual(PD->getSelfInterfaceType())) {
542-
BaseConformance conformance(
543-
PD,
544-
req.getSecondType()->castTo<ProtocolType>()->getDecl());
545-
addBaseConformanceDescriptor(conformance);
546-
} else {
547-
AssociatedConformance conformance(
548-
PD,
549-
req.getFirstType()->getCanonicalType(),
550-
req.getSecondType()->castTo<ProtocolType>()->getDecl());
551-
addAssociatedConformanceDescriptor(conformance);
552-
}
553-
}
504+
struct WitnessVisitor : public SILWitnessVisitor<WitnessVisitor> {
505+
TBDGenVisitor &TBD;
506+
ProtocolDecl *PD;
554507

555-
for (auto *member : PD->getMembers()) {
556-
if (PD->isResilient()) {
557-
if (auto *funcDecl = dyn_cast<AbstractFunctionDecl>(member)) {
558-
if (SILDeclRef::requiresNewWitnessTableEntry(funcDecl)) {
559-
addDispatchThunk(SILDeclRef(funcDecl));
560-
addMethodDescriptor(SILDeclRef(funcDecl));
561-
}
508+
public:
509+
WitnessVisitor(TBDGenVisitor &TBD, ProtocolDecl *PD)
510+
: TBD(TBD), PD(PD) {}
511+
512+
void addMethod(SILDeclRef declRef) {
513+
if (PD->isResilient()) {
514+
TBD.addDispatchThunk(declRef);
515+
TBD.addMethodDescriptor(declRef);
562516
}
563517
}
564518

565-
// Always produce associated type descriptors, because they can
566-
// be referenced by generic signatures.
567-
if (auto *assocType = dyn_cast<AssociatedTypeDecl>(member)) {
568-
if (assocType->getOverriddenDecls().empty())
569-
addAssociatedTypeDescriptor(assocType);
519+
void addAssociatedType(AssociatedType associatedType) {
520+
TBD.addAssociatedTypeDescriptor(associatedType.getAssociation());
570521
}
571-
}
522+
523+
void addProtocolConformanceDescriptor() {
524+
TBD.addProtocolRequirementsBaseDescriptor(PD);
525+
}
526+
527+
void addOutOfLineBaseProtocol(ProtocolDecl *proto) {
528+
TBD.addBaseConformanceDescriptor(BaseConformance(PD, proto));
529+
}
530+
531+
void addAssociatedConformance(AssociatedConformance associatedConf) {
532+
TBD.addAssociatedConformanceDescriptor(associatedConf);
533+
}
534+
535+
void addPlaceholder(MissingMemberDecl *decl) {}
536+
537+
void doIt() {
538+
visitProtocolDecl(PD);
539+
}
540+
};
541+
542+
WitnessVisitor(*this, PD).doIt();
572543

573544
// Include the self-conformance.
574545
addConformances(PD);

0 commit comments

Comments
 (0)